diff --git a/demos/01_animatePoint.html b/demos/01_animatePoint.html
new file mode 100644
index 0000000000..96f2acf9c4
--- /dev/null
+++ b/demos/01_animatePoint.html
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+ point_circle
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/01_point_circle.html b/demos/01_point_circle.html
index fef2948b0d..ce3ac03fb3 100644
--- a/demos/01_point_circle.html
+++ b/demos/01_point_circle.html
@@ -39,39 +39,46 @@ const scene = new L7.Scene({
center: [ 120.19382669582967, 30.258134 ],
pitch: 0,
zoom: 12,
- maxZoom:14,
- minZoom:11,
+ maxZoom:20,
+ minZoom:0,
});
window.scene = scene;
scene.on('loaded', () => {
$.get('https://gw.alipayobjects.com/os/rmsportal/epnZEheZeDgsiSjSPcCv.json', data => {
const circleLayer = scene.PointLayer({
- zIndex: 2,
+ zIndex: 0,
})
- .source(data)
- .shape('circle')
- .size('value', [ 2, 30]) // default 1
- .scale('value', {
- type:'log',
+ .source(data,{
+ isCluster:true
})
+ .shape('hexagon')
+ .size('point_count', [ 2, 30]) // default 1
//.size('value', [ 10, 300]) // default 1
.active(true)
- .filter('value', field_8 => {
- return field_8 * 1 > 500;
- })
- .color('type', colorObj.blue)
+ .color('#2894E0')
.style({
stroke: 'rgb(255,255,255)',
strokeWidth: 1,
- opacity: 1.
+ opacity: 0.8
})
.render();
- console.log(circleLayer);
- var a = circleLayer.getLegendCfg('type','color');
- console.log(a);
- circleLayer.on('click',(e)=>{
- console.log(e);
- })
+ window.circleLayer = circleLayer;
+ const layerText = scene.PointLayer({
+ zIndex: 3
+ })
+ .source(circleLayer.layerSource)
+ .shape('point_count', 'text')
+ .active(true)
+ .size('point_count', [ 0, 16]) // default 1
+ .color('#f00')
+ .style({
+ stroke: '#999',
+ strokeWidth: 0,
+ opacity: 1.0
+ })
+ .render();
+ console.log(layerText);
+
});
});
diff --git a/demos/02_animateline.html b/demos/02_animateline.html
new file mode 100644
index 0000000000..9d78576db4
--- /dev/null
+++ b/demos/02_animateline.html
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+ animateLine
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/core/atlas/font-manager.js b/src/core/atlas/font-manager.js
new file mode 100644
index 0000000000..0fdb8bb53f
--- /dev/null
+++ b/src/core/atlas/font-manager.js
@@ -0,0 +1,227 @@
+import TinySDF from '@mapbox/tiny-sdf';
+import { buildMapping } from '../../../../util/font-util';
+import * as THREE from '../../../../core/three';
+import LRUCache from './lru-cache';
+export const DEFAULT_CHAR_SET = getDefaultCharacterSet();
+export const DEFAULT_FONT_FAMILY = 'sans-serif';
+export const DEFAULT_FONT_WEIGHT = 'normal';
+export const DEFAULT_FONT_SIZE = 24;
+export const DEFAULT_BUFFER = 3;
+export const DEFAULT_CUTOFF = 0.25;
+export const DEFAULT_RADIUS = 8;
+const MAX_CANVAS_WIDTH = 1024;
+const BASELINE_SCALE = 0.9;
+const HEIGHT_SCALE = 1.2;
+const CACHE_LIMIT = 3;
+const cache = new LRUCache(CACHE_LIMIT);
+
+const VALID_PROPS = [
+ 'fontFamily',
+ 'fontWeight',
+ 'characterSet',
+ 'fontSize',
+ 'sdf',
+ 'buffer',
+ 'cutoff',
+ 'radius'
+];
+
+function getDefaultCharacterSet() {
+ const charSet = [];
+ for (let i = 32; i < 128; i++) {
+ charSet.push(String.fromCharCode(i));
+ }
+ return charSet;
+}
+
+function setTextStyle(ctx, fontFamily, fontSize, fontWeight) {
+ ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
+ ctx.fillStyle = '#000';
+ ctx.textBaseline = 'baseline';
+ ctx.textAlign = 'left';
+}
+function getNewChars(key, characterSet) {
+ const cachedFontAtlas = cache.get(key);
+ if (!cachedFontAtlas) {
+ return characterSet;
+ }
+
+ const newChars = [];
+ const cachedMapping = cachedFontAtlas.mapping;
+ let cachedCharSet = Object.keys(cachedMapping);
+ cachedCharSet = new Set(cachedCharSet);
+
+ let charSet = characterSet;
+ if (charSet instanceof Array) {
+ charSet = new Set(charSet);
+ }
+
+ charSet.forEach(char => {
+ if (!cachedCharSet.has(char)) {
+ newChars.push(char);
+ }
+ });
+
+ return newChars;
+}
+
+function populateAlphaChannel(alphaChannel, imageData) {
+ // populate distance value from tinySDF to image alpha channel
+ for (let i = 0; i < alphaChannel.length; i++) {
+ imageData.data[4 * i + 3] = alphaChannel[i];
+ }
+}
+
+export default class FontAtlasManager {
+ constructor() {
+
+ // font settings
+ this.props = {
+ fontFamily: DEFAULT_FONT_FAMILY,
+ fontWeight: DEFAULT_FONT_WEIGHT,
+ characterSet: DEFAULT_CHAR_SET,
+ fontSize: DEFAULT_FONT_SIZE,
+ buffer: DEFAULT_BUFFER,
+ // sdf only props
+ // https://github.com/mapbox/tiny-sdf
+ sdf: true,
+ cutoff: DEFAULT_CUTOFF,
+ radius: DEFAULT_RADIUS
+ };
+
+ // key is used for caching generated fontAtlas
+ this._key = null;
+ this._texture = new THREE.Texture();
+ }
+
+ get texture() {
+ return this._texture;
+ }
+
+ get mapping() {
+ const data = cache.get(this._key);
+ return data && data.mapping;
+ }
+
+ get scale() {
+ return HEIGHT_SCALE;
+ }
+
+ get fontAtlas() {
+ return this._fontAtlas;
+ }
+
+ setProps(props = {}) {
+ VALID_PROPS.forEach(prop => {
+ if (prop in props) {
+ this.props[prop] = props[prop];
+ }
+ });
+
+ // update cache key
+ const oldKey = this._key;
+ this._key = this._getKey();
+
+ const charSet = getNewChars(this._key, this.props.characterSet);
+ const cachedFontAtlas = cache.get(this._key);
+
+ // if a fontAtlas associated with the new settings is cached and
+ // there are no new chars
+ if (cachedFontAtlas && charSet.length === 0) {
+ // update texture with cached fontAtlas
+ if (this._key !== oldKey) {
+ this._updateTexture(cachedFontAtlas);
+ }
+ return;
+ }
+
+ // update fontAtlas with new settings
+ const fontAtlas = this._generateFontAtlas(this._key, charSet, cachedFontAtlas);
+ this._fontAtlas = fontAtlas;
+ this._updateTexture(fontAtlas);
+
+ // update cache
+ cache.set(this._key, fontAtlas);
+ }
+
+ _updateTexture({ data: canvas }) {
+ this._texture = new THREE.CanvasTexture(canvas);
+ this._texture.wrapS = THREE.ClampToEdgeWrapping;
+ this._texture.wrapT = THREE.ClampToEdgeWrapping;
+ this._texture.minFilter = THREE.LinearFilter;
+ this._texture.flipY = false;
+ this._texture.needUpdate = true;
+ }
+
+ _generateFontAtlas(key, characterSet, cachedFontAtlas) {
+ const { fontFamily, fontWeight, fontSize, buffer, sdf, radius, cutoff } = this.props;
+ let canvas = cachedFontAtlas && cachedFontAtlas.data;
+ if (!canvas) {
+ canvas = document.createElement('canvas');
+ canvas.width = MAX_CANVAS_WIDTH;
+ }
+ const ctx = canvas.getContext('2d');
+
+ setTextStyle(ctx, fontFamily, fontSize, fontWeight);
+
+ // 1. build mapping
+ const { mapping, canvasHeight, xOffset, yOffset } = buildMapping(
+ Object.assign(
+ {
+ getFontWidth: char => ctx.measureText(char).width,
+ fontHeight: fontSize * HEIGHT_SCALE,
+ buffer,
+ characterSet,
+ maxCanvasWidth: MAX_CANVAS_WIDTH
+ },
+ cachedFontAtlas && {
+ mapping: cachedFontAtlas.mapping,
+ xOffset: cachedFontAtlas.xOffset,
+ yOffset: cachedFontAtlas.yOffset
+ }
+ )
+ );
+
+ // 2. update canvas
+ // copy old canvas data to new canvas only when height changed
+ if (canvas.height !== canvasHeight) {
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
+ canvas.height = canvasHeight;
+ ctx.putImageData(imageData, 0, 0);
+ }
+ setTextStyle(ctx, fontFamily, fontSize, fontWeight);
+
+ // 3. layout characters
+ if (sdf) {
+ const tinySDF = new TinySDF(fontSize, buffer, radius, cutoff, fontFamily, fontWeight);
+ // used to store distance values from tinySDF
+ // tinySDF.size equals `fontSize + buffer * 2`
+ const imageData = ctx.getImageData(0, 0, tinySDF.size, tinySDF.size);
+
+ for (const char of characterSet) {
+ populateAlphaChannel(tinySDF.draw(char), imageData);
+ ctx.putImageData(imageData, mapping[char].x - buffer, mapping[char].y - buffer);
+ }
+ } else {
+ for (const char of characterSet) {
+ ctx.fillText(char, mapping[char].x, mapping[char].y + fontSize * BASELINE_SCALE);
+ }
+ }
+ return {
+ xOffset,
+ yOffset,
+ mapping,
+ data: canvas,
+ width: canvas.width,
+ height: canvas.height
+ };
+ }
+
+ _getKey() {
+ const { fontFamily, fontWeight, fontSize, buffer, sdf, radius, cutoff } = this.props;
+ if (sdf) {
+ return `${fontFamily} ${fontWeight} ${fontSize} ${buffer} ${radius} ${cutoff}`;
+ }
+ return `${fontFamily} ${fontWeight} ${fontSize} ${buffer}`;
+ }
+}
diff --git a/src/core/atlas/icon-manager.js b/src/core/atlas/icon-manager.js
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/core/atlas/lru-cache.js b/src/core/atlas/lru-cache.js
new file mode 100644
index 0000000000..8b417e53e2
--- /dev/null
+++ b/src/core/atlas/lru-cache.js
@@ -0,0 +1,71 @@
+/**
+ * LRU Cache class with limit
+ *
+ * Update order for each get/set operation
+ * Delete oldest when reach given limit
+ */
+
+export default class LRUCache {
+ constructor(limit = 5) {
+ this.limit = limit;
+
+ this.clear();
+ }
+
+ clear() {
+ this._cache = {};
+ // access/update order, first item is oldest, last item is newest
+ this._order = [];
+ }
+
+ get(key) {
+ const value = this._cache[key];
+ if (value) {
+ // update order
+ this._deleteOrder(key);
+ this._appendOrder(key);
+ }
+ return value;
+ }
+
+ set(key, value) {
+ if (!this._cache[key]) {
+ // if reach limit, delete the oldest
+ if (Object.keys(this._cache).length === this.limit) {
+ this.delete(this._order[0]);
+ }
+
+ this._cache[key] = value;
+ this._appendOrder(key);
+ } else {
+ // if found in cache, delete the old one, insert new one to the first of list
+ this.delete(key);
+
+ this._cache[key] = value;
+ this._appendOrder(key);
+ }
+ }
+
+ delete(key) {
+ const value = this._cache[key];
+ if (value) {
+ this._deleteCache(key);
+ this._deleteOrder(key);
+ }
+ }
+
+ _deleteCache(key) {
+ delete this._cache[key];
+ }
+
+ _deleteOrder(key) {
+ const index = this._order.findIndex(o => o === key);
+ if (index >= 0) {
+ this._order.splice(index, 1);
+ }
+ }
+
+ _appendOrder(key) {
+ this._order.push(key);
+ }
+}
diff --git a/src/core/layer.js b/src/core/layer.js
index 1403fee10e..6b974bddbc 100644
--- a/src/core/layer.js
+++ b/src/core/layer.js
@@ -8,7 +8,7 @@ import ColorUtil from '../attr/color-util';
import Controller from './controller/index';
import source from './source';
import pickingFragmentShader from '../core/engine/picking/picking_frag.glsl';
-// import PickingMaterial from '../core/engine/picking/pickingMaterial';
+import { getInteraction } from '../interaction/index';
import Attr from '../attr/index';
import Util from '../util';
import Global from '../global';
@@ -53,6 +53,7 @@ export default class Layer extends Base {
activedOptions: {
fill: [ 1.0, 0, 0, 1.0 ]
},
+ interactions: {},
animateOptions: {
enable: false
}
@@ -66,6 +67,7 @@ export default class Layer extends Base {
this._pickObject3D = new THREE.Object3D();
this._object3D.visible = this.get('visible');
this._object3D.renderOrder = this.get('zIndex') || 0;
+ this._mapEventHandlers = [];
const layerId = this._getUniqueId();
this.layerId = layerId;
this._activeIds = null;
@@ -88,12 +90,8 @@ export default class Layer extends Base {
this.scene._engine.composerLayers.push(object);
return;
}
-
type === 'fill' ? this.layerMesh = object : this.layerLineMesh = object;
this._visibleWithZoom();
- this._zoomchangeHander = this._visibleWithZoom.bind(this);
- this.scene.on('zoomchange', this._zoomchangeHander);
-
object.onBeforeRender = () => { // 每次渲染前改变状态
const zoom = this.scene.getZoom();
object.material.setUniformsValue('u_time', this.scene._engine.clock.getElapsedTime());
@@ -113,7 +111,7 @@ export default class Layer extends Base {
this._addPickMesh(object);// 不对边界线进行拾取
}
this.scene._engine.update();
- setTimeout(() => this.scene._engine.update(), 500);
+ setTimeout(() => this.scene._engine.update(), 200);
}
remove(object) {
if (object.type === 'composer') {
@@ -132,8 +130,13 @@ export default class Layer extends Base {
this._object3D.visible = this.get('visible');
}
source(data, cfg = {}) {
+ if (data instanceof source) {
+ this.layerSource = data;
+ return this;
+ }
cfg.data = data;
cfg.mapType = this.scene.mapType;
+ cfg.zoom = this.scene.getZoom();
this.layerSource = new source(cfg);
// this.scene.workerPool.runTask({
// command: 'geojson',
@@ -263,6 +266,10 @@ export default class Layer extends Base {
this._visible(true);
return this;
}
+ setData(data, cfg) {
+ this.layerSource.setData(data, cfg);
+ this.repaint();
+ }
_createScale(field) {
// TODO scale更新
const scales = this.get('scales');
@@ -316,25 +323,53 @@ export default class Layer extends Base {
}
return scale;
}
+ // 重绘 度量, 映射,顶点构建
+ repaint() {
+ this.set('scales', {});
+ this._initControllers();
+ this._initAttrs();
+ this._mapping();
+ this.redraw();
+ }
// 初始化图层
init() {
this._initControllers();
this._initAttrs();
this._scaleByZoom();
+ this._initInteraction();
+ this._initMapEvent();
+
this._mapping();
-
- const activeHander = this._addActiveFeature.bind(this);
- const resetHander = this._resetStyle.bind(this);
+ }
+ _initInteraction() {
if (this.get('allowActive')) {
-
- this.on('mousemove', activeHander);
- this.on('mouseleave', resetHander);
-
- } else {
- this.off('mousemove', activeHander);
- this.off('mouseleave', resetHander);
+ this.interaction('active');
}
}
+ _initMapEvent() {
+ // zoomchange mapmove resize
+ const EVENT_TYPES = [ 'zoomchange', 'dragend' ];
+ Util.each(EVENT_TYPES, type => {
+ const handler = Util.wrapBehavior(this, `${type}`);
+ this.map.on(`${type}`, handler);
+ this._mapEventHandlers.push({ type, handler });
+ });
+ }
+ clearMapEvent() {
+ const eventHandlers = this._mapEventHandlers;
+ Util.each(eventHandlers, eh => {
+ this.map.off(eh.type, eh.handler);
+ });
+ }
+ zoomchange(ev) {
+ // 地图缩放等级变化
+ this._visibleWithZoom(ev);
+ }
+ dragend() {
+
+ }
+ resize() {
+ }
setActive(id, color) {
this._activeIds = id;
@@ -483,17 +518,6 @@ export default class Layer extends Base {
const values = attr.mapping(...params);
return values;
}
-
- // temp
- _getDataType(data) {
- if (data.hasOwnProperty('type')) {
- const type = data.type;
- if (type === 'FeatureCollection') {
- return 'geojson';
- }
- }
- return 'basic';
- }
_scaleByZoom() {
if (this._zoomScale) {
this.map.on('zoomend', () => {
@@ -502,11 +526,7 @@ export default class Layer extends Base {
});
}
}
- // on(type, callback) {
- // this._addPickingEvents();
- // super.on(type, callback);
- // }
getPickingId() {
return this.scene._engine._picking.getNextId();
}
@@ -519,19 +539,9 @@ export default class Layer extends Base {
_addPickMesh(mesh) {
this._pickingMesh = new THREE.Object3D();
this._pickingMesh.name = this.layerId;
- // this._visibleWithZoom();
- // this.scene.on('zoomchange', () => {
- // this._visibleWithZoom();
- // });
this.addToPicking(this._pickingMesh);
const pickmaterial = mesh.material.clone();
-
pickmaterial.fragmentShader = pickingFragmentShader;
- // const pickmaterial = new PickingMaterial({
- // u_zoom: this.scene.getZoom(),
- // vs: mesh.material.
- // });
-
const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
pickingMesh.name = this.layerId;
pickmaterial.setDefinesvalue(this.type, true);
@@ -542,9 +552,6 @@ export default class Layer extends Base {
this._pickingMesh.add(pickingMesh);
}
- _setPickingId() {
- this._pickingId = this.getPickingId();
- }
_initEvents() {
this.scene.on('pick-' + this.layerId, e => {
let { featureId, point2d, type } = e;
@@ -552,6 +559,7 @@ export default class Layer extends Base {
type = 'mouseleave';
// featureId = this._activeIds;
}
+ this._activeIds = featureId;
const feature = this.layerSource.getSelectFeature(featureId);
const lnglat = this.scene.containerToLngLat(point2d);
const style = this.layerData[featureId - 1];
@@ -569,39 +577,6 @@ export default class Layer extends Base {
});
}
- /**
- * 更新active操作
- * @param {*} featureStyleId 需要更新的要素Id
- * @param {*} style 更新的要素样式
- */
- updateStyle(featureStyleId, style) {
- if (this._activeIds) {
- this._resetStyle();
- }
- this._activeIds = featureStyleId;
- const pickingId = this.layerMesh.geometry.attributes.pickingId.array;
- const color = style.color;
- const colorAttr = this.layerMesh.geometry.attributes.a_color;
- const firstId = pickingId.indexOf(featureStyleId[0]);
- for (let i = firstId; i < pickingId.length; i++) {
- if (pickingId[i] === featureStyleId[0]) {
- colorAttr.array[i * 4 + 0] = color[0];
- colorAttr.array[i * 4 + 1] = color[1];
- colorAttr.array[i * 4 + 2] = color[2];
- colorAttr.array[i * 4 + 3] = color[3];
- } else {
- break;
- }
- }
- colorAttr.needsUpdate = true;
- return;
- }
-
- _updateColor() {
-
- this._updateMaping();
-
- }
/**
* 用于过滤数据
* @param {*} object 需要过滤的mesh
@@ -642,6 +617,8 @@ export default class Layer extends Base {
let offset = 0;
if (this.type === 'point') {
offset = 5;
+ this.shapeType = 'text' && (offset = 10);
+
} else if (this.type === 'polyline') {
offset = 2;
}
@@ -652,6 +629,51 @@ export default class Layer extends Base {
this._object3D.visible = true;
}
}
+ // 重新构建mesh
+ redraw() {
+ this._object3D.children.forEach(child => {
+ this._object3D.remove(child);
+ });
+ this.removeFromPicking(this._pickingMesh);
+ this.draw();
+ }
+ // 更新mesh
+ updateDraw() {
+
+ }
+
+ // interaction 方法
+ clearAllInteractions() {
+ const interactions = this.get('interactions');
+ Util.each(interactions, (interaction, key) => {
+ interaction.destory();
+ delete interactions[key];
+ });
+ return this;
+ }
+ clearInteraction(type) {
+ const interactions = this.get('interactions');
+ if (interactions[type]) {
+ interactions[type].destory();
+ delete interactions[type];
+ }
+ return this;
+ }
+ interaction(type, cfg = {}) {
+ cfg.layer = this;
+ const Ctor = getInteraction(type);
+ const interaction = new Ctor(cfg);
+ this._setInteraction(type, interaction);
+ return this;
+ }
+ _setInteraction(type, interaction) {
+ const interactions = this.get('interactions');
+ if (interactions[type]) {
+ interactions[type].destory();
+ }
+ interactions[type] = interaction;
+ }
+
/**
* 重置高亮要素
*/
@@ -664,6 +686,8 @@ export default class Layer extends Base {
*/
destroy() {
this.removeAllListeners();
+ this.clearAllInteractions();
+ this.clearMapEvent();
if (this._object3D.type === 'composer') {
this.remove(this._object3D);
@@ -696,7 +720,6 @@ export default class Layer extends Base {
this._object3D = null;
this.scene._engine._scene.remove(this._object3D);
this.scene._engine._picking.remove(this._pickingMesh);
- this.scene.off('zoomchange', this._zoomchangeHander);
this.destroyed = true;
}
diff --git a/src/core/scene.js b/src/core/scene.js
index 5d22c4e67d..e662d45b9f 100644
--- a/src/core/scene.js
+++ b/src/core/scene.js
@@ -69,14 +69,6 @@ export default class Scene extends Base {
super.off(type, hander);
}
- _initAttribution() {
- const message = 'AntV | L7 ';
- const element = document.createElement('div');
-
- element.innerHTML = message;
- element.style.cssText += 'position: absolute; pointer-events:none;background: rgba(255, 255, 255, 0.7);font-size: 11px;z-index:100; padding:4px;bottom: 0;right:0px;';
- this._container.appendChild(element);
- }
addImage() {
this.image = new LoadImage();
}
diff --git a/src/core/source.js b/src/core/source.js
index 305e535178..25841350ea 100644
--- a/src/core/source.js
+++ b/src/core/source.js
@@ -1,6 +1,8 @@
import Base from './base';
import { getTransform, getParser } from '../source';
+import { cluster, formatData } from '../source/transform/cluster';
import { extent, tranfrormCoord } from '../util/geo';
+import { clone } from '@antv/util';
import { getMap } from '../map/index';
export default class Source extends Base {
getDefaultCfg() {
@@ -21,18 +23,40 @@ export default class Source extends Base {
const mapType = this.get('mapType');
this.projectFlat = getMap(mapType).project;
// 数据解析
+ this._init();
+
+ }
+ _init() {
this._excuteParser();
+ const isCluster = this.get('isCluster') || false;
+ isCluster && this._executeCluster();
// 数据转换 统计,聚合,分类
this._executeTrans();
// 坐标转换
this._projectCoords();
-
}
+ setData(data, cfg = {}) {
+ Object.assign(this._attrs, cfg);
+ const transform = this.get('transforms');
+ this._transforms = transform || [];
+ this.set('data', data);
+ this._init();
+ }
+ // 数据更新
+ updateTransfrom(cfg) {
+ const { transforms } = cfg;
+ this._transforms = transforms;
+ this.data = clone(this.originData);
+ this._executeTrans();
+ this._projectCoords();
+ }
+
_excuteParser() {
const parser = this.get('parser');
const { type = 'geojson' } = parser;
const data = this.get('data');
- this.data = getParser(type)(data, parser);
+ this.originData = getParser(type)(data, parser);
+ this.data = clone(this.originData);
this.data.extent = extent(this.data.dataArray);
}
/**
@@ -51,6 +75,24 @@ export default class Source extends Base {
const data = getTransform(option.type)(this.data, option);
Object.assign(this.data, data);
}
+ _executeCluster() {
+ const clusterCfg = this.get('Cluster') || {};
+ const zoom = this.get('zoom');
+ clusterCfg.zoom = Math.floor(zoom);
+ this.set('cluster', clusterCfg);
+ const clusterData = cluster(this.data, clusterCfg);
+ this.data = clusterData.data;
+ this.pointIndex = clusterData.pointIndex;
+ }
+ updateCusterData(zoom, bbox) {
+ const clusterPoint = this.pointIndex.getClusters(bbox, zoom);
+ this.data.dataArray = formatData(clusterPoint);
+ const clusterCfg = this.get('Cluster') || {};
+ clusterCfg.zoom = Math.floor(zoom);
+ clusterCfg.bbox = bbox;
+ this.set('cluster', clusterCfg);
+ this._projectCoords();
+ }
_projectCoords() {
this.data.dataArray.forEach(data => {
// data.coordinates = this._coordProject(data.coordinates);
diff --git a/src/geom/base.js b/src/geom/base.js
new file mode 100644
index 0000000000..9e1488b9df
--- /dev/null
+++ b/src/geom/base.js
@@ -0,0 +1,21 @@
+import Base from '../core/base';
+export class GeomBase extends Base {
+ geometryBuffer() {
+
+ }
+ geometry() {
+ }
+
+ material() {
+
+ }
+
+ drawMesh() {
+
+ }
+
+
+}
+
+
+export default GeomBase;
diff --git a/src/geom/buffer/point/text.js b/src/geom/buffer/point/text.js
index 2552bdf894..9b2f5f50b8 100644
--- a/src/geom/buffer/point/text.js
+++ b/src/geom/buffer/point/text.js
@@ -29,12 +29,11 @@ function drawGlyph(layerData, fontAtlasManager) {
const size = element.size;
const pos = element.coordinates;
let text = element.shape || '';
+ text = text.toString();
const pen = {
x: (-text.length * size) / 2,
y: 0
};
- text = text.toString();
-
for (let i = 0; i < text.length; i++) {
const metric = mapping[text[i]];
const { x, y, width, height } = metric;
diff --git a/src/geom/geom.js b/src/geom/geom.js
deleted file mode 100644
index 9684109ea2..0000000000
--- a/src/geom/geom.js
+++ /dev/null
@@ -1,62 +0,0 @@
-const geom = {
- point: {
- symbol: [ 'circle', 'hexagon', 'triangle', 'diamond' ],
- native: {
- buffer: '',
- geometry: 'PointGeometry',
- material: 'PointMaterial'
- },
- line: {
- buffer: 'PointBuffer',
- geometry: 'PolygonLine',
- material: 'MeshlineMaterial'
- },
- fill: {
- buffer: 'PointBuffer',
- geometry: 'PolygonGeometry',
- material: 'PolygonMaterial'
- },
- extrude: {
- buffer: 'PointBuffer',
- geometry: 'PolygonGeometry',
- material: 'PolygonMaterial'
- },
- extrudeline: {
- buffer: 'PointBuffer',
- geometry: 'PolygonLine',
- material: 'MeshlineMaterial'
- },
- pointGrid: {
- buffer: 'pointGrid',
- geometry: 'PolygonLine',
- material: 'MeshlineMaterial'
-
- }
- },
- line: {
- shape: [ 'native' ]
- },
- polygon: {
- line: {
- buffer: 'polygonLineBuffer',
- geometry: 'PolygonLine',
- material: 'MeshlineMaterial'
- },
- fill: {
- buffer: 'PolygonBuffer',
- geometry: 'PolygonGeometry',
- material: 'PolygonMaterial'
- },
- extrude: {
- buffer: 'PolygonBuffer',
- geometry: 'PolygonGeometry',
- material: 'PolygonMaterial'
- },
- extrudeline: {
- buffer: 'polygonLineBuffer',
- geometry: 'PolygonLine',
- material: 'MeshlineMaterial'
- }
- }
-};
-export default geom;
diff --git a/src/geom/shader/point_meshLine_vert.glsl b/src/geom/shader/point_meshLine_vert.glsl
index 3493808811..d4773d23e6 100644
--- a/src/geom/shader/point_meshLine_vert.glsl
+++ b/src/geom/shader/point_meshLine_vert.glsl
@@ -15,7 +15,7 @@ varying vec4 v_color;
void main() {
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
float scale = pow(2.0,(20.0 - u_zoom));
- vec3 newposition = position + (a_size + vec3(u_strokeWidth/2.,u_strokeWidth/2.,0)) * scale* a_shape;
+ vec3 newposition = position + (a_size + vec3(u_strokeWidth/2.,u_strokeWidth/2.,0)) * scale* a_shape + vec3(0., a_size.y * scale / 4., 0.);;
#ifdef ANIMATE
vTime = 1.0- (mod(u_time*50.,3600.)- position.z) / 100.;
#endif
diff --git a/src/geom/shader/polygon_vert.glsl b/src/geom/shader/polygon_vert.glsl
index 36474bde79..2015bee5f5 100644
--- a/src/geom/shader/polygon_vert.glsl
+++ b/src/geom/shader/polygon_vert.glsl
@@ -21,7 +21,7 @@ void main() {
vec3 newposition = position;
// newposition.x -= 128.0;
#ifdef SHAPE
- newposition =position + a_size * scale* a_shape;
+ newposition =position + a_size * scale* a_shape + vec3(0., a_size.y * scale / 4., 0.);
#endif
v_texCoord = faceUv;
if(normal == vec3(0.,0.,1.)){
diff --git a/src/geom/shader/text_frag.glsl b/src/geom/shader/text_frag.glsl
index f29d97a435..7fe59c4257 100644
--- a/src/geom/shader/text_frag.glsl
+++ b/src/geom/shader/text_frag.glsl
@@ -7,9 +7,11 @@ uniform float u_buffer;
uniform float u_gamma;
uniform float u_opacity;
varying vec2 v_texcoord;
+varying float v_size;
void main(){
float dist=texture2D(u_texture,vec2(v_texcoord.x,v_texcoord.y)).a;
float alpha;
+
if(u_strokeWidth==0.){
alpha=smoothstep(u_buffer-u_gamma,u_buffer+u_gamma,dist);
gl_FragColor=vec4(v_color.rgb,alpha*v_color.a);
diff --git a/src/geom/shader/text_vert.glsl b/src/geom/shader/text_vert.glsl
index 51ff8a0150..f4290df289 100644
--- a/src/geom/shader/text_vert.glsl
+++ b/src/geom/shader/text_vert.glsl
@@ -7,12 +7,14 @@ uniform vec2 u_textTextureSize;// 纹理大小
uniform vec2 u_glSize;
varying vec2 v_texcoord;
varying vec4 v_color;
+varying float v_size;
uniform float u_activeId;
uniform vec4 u_activeColor;
void main(){
mat4 matModelViewProjection=projectionMatrix*modelViewMatrix;
vec4 cur_position=matModelViewProjection*vec4(position.xy,0,1);
+ v_size = 12. / u_glSize.x;
gl_Position=cur_position/cur_position.w+vec4((a_txtOffsets+a_txtsize)/u_glSize*2.,0.,0.);
v_color=vec4(a_color.rgb,a_color.a*u_opacity);
if(pickingId==u_activeId){
diff --git a/src/geom/shape/path.js b/src/geom/shape/path.js
index d4c2842a50..a693484d9c 100644
--- a/src/geom/shape/path.js
+++ b/src/geom/shape/path.js
@@ -33,7 +33,7 @@ export function polygonPath(pointCount) {
const step = Math.PI * 2 / pointCount;
const line = [];
for (let i = 0; i < pointCount; i++) {
- line.push(step * i);
+ line.push(step * i - Math.PI / 12);
}
const path = line.map(t => {
const x = Math.sin(t + Math.PI / 4),
diff --git a/src/index.js b/src/index.js
index f791d2df22..399f8df9ec 100755
--- a/src/index.js
+++ b/src/index.js
@@ -2,10 +2,19 @@
// import Util from './util';
import Scene from './core/scene';
import Global from './global';
-
+import Source from './core/source';
+import { registerParser, registerTransform } from './source';
+import { registerInteraction, getInteraction } from './interaction';
+import { registerLayer } from './layer';
const version = Global.version;
export {
version,
- Scene
+ Scene,
+ Source,
+ registerParser,
+ registerTransform,
+ registerLayer,
+ registerInteraction,
+ getInteraction
};
diff --git a/src/interaction/active.js b/src/interaction/active.js
new file mode 100644
index 0000000000..d4e8807d45
--- /dev/null
+++ b/src/interaction/active.js
@@ -0,0 +1,16 @@
+import Interaction from './base';
+export default class Active extends Interaction {
+ constructor(cfg) {
+ super({
+ processEvent: 'mousemove',
+ resetEvent: 'mouseleave',
+ ...cfg
+ });
+ }
+ process(ev) {
+ this.layer._addActiveFeature(ev);
+ }
+ reset() {
+ this.layer._resetStyle();
+ }
+}
diff --git a/src/interaction/base.js b/src/interaction/base.js
new file mode 100644
index 0000000000..2103c1a5cd
--- /dev/null
+++ b/src/interaction/base.js
@@ -0,0 +1,87 @@
+import * as _ from '@antv/util';
+const EVENT_TYPES = [ 'start', 'process', 'end', 'reset' ];
+
+export default class Interaction {
+ constructor(cfg) {
+ const defaultCfg = this._getDefaultCfg();
+ Object.assign(this, defaultCfg, cfg);
+ this._eventHandlers = [];
+ this._bindEvents();
+ }
+ _getDefaultCfg() {
+ return {
+ startEvent: 'mousedown',
+ processEvent: 'mousemove',
+ endEvent: 'mouseup',
+ resetEvent: 'dblclick'
+ };
+ }
+ _start(ev) {
+ this.preStart(ev);
+ this.start(ev);
+ this.afterStart(ev);
+ }
+
+ preStart() {}
+
+ start() {}
+
+ afterStart() {}
+
+ _process(ev) {
+ this.preProcess(ev);
+ this.process(ev);
+ this.afterProcess(ev);
+ }
+
+ preProcess() {}
+
+ process() {
+ }
+
+ afterProcess() {}
+
+ _end(ev) {
+ this.preEnd(ev);
+ this.end(ev);
+ this.afterEnd(ev);
+ }
+ preEnd() {}
+
+ end() {}
+
+ afterEnd() {}
+
+ _reset() {
+ this.preReset();
+ this.reset();
+ this.afterReset();
+ }
+
+ preReset() {}
+
+ reset() {}
+
+ afterReset() {}
+
+ _bindEvents() {
+ _.each(EVENT_TYPES, type => {
+ const eventName = this[`${type}Event`];
+ const handler = _.wrapBehavior(this, `_${type}`);
+ this.layer.on(eventName, handler);
+ this._eventHandlers.push({ type: eventName, handler });
+ });
+ }
+
+ _unbindEvents() {
+ const eventHandlers = this._eventHandlers;
+ _.each(eventHandlers, eh => {
+ this.layer.off(eh.type, eh.handler);
+ });
+ }
+
+ destory() {
+ this._unbindEvents();
+ this._reset();
+ }
+}
diff --git a/src/interaction/factory.js b/src/interaction/factory.js
new file mode 100644
index 0000000000..4442e4b7e9
--- /dev/null
+++ b/src/interaction/factory.js
@@ -0,0 +1,14 @@
+export const INTERACTION_MAP = {};
+
+export const getInteraction = type => {
+ return INTERACTION_MAP[type];
+};
+
+export const registerInteraction = (type, ctor) => {
+ // 注册的时候,需要校验 type 重名,不区分大小写
+ if (getInteraction(type)) {
+ throw new Error(`Interaction type '${type}' existed.`);
+ }
+ // 存储到 map 中
+ INTERACTION_MAP[type] = ctor;
+};
diff --git a/src/interaction/index.js b/src/interaction/index.js
new file mode 100644
index 0000000000..838f27ddac
--- /dev/null
+++ b/src/interaction/index.js
@@ -0,0 +1,9 @@
+import Interaction from './base';
+import Active from './active';
+import Select from './select';
+import { getInteraction, registerInteraction } from './factory';
+
+registerInteraction('active', Active);
+registerInteraction('select', Select);
+
+export { Interaction, registerInteraction, getInteraction };
diff --git a/src/interaction/select.js b/src/interaction/select.js
new file mode 100644
index 0000000000..2cf5e4d001
--- /dev/null
+++ b/src/interaction/select.js
@@ -0,0 +1,12 @@
+import Interaction from './base';
+export default class Select extends Interaction {
+ constructor(cfg) {
+ super({
+ processEvent: 'click',
+ ...cfg
+ });
+ }
+ process(ev) {
+ this.layer._addActiveFeature(ev);
+ }
+}
diff --git a/src/layer/heatmapLayer.js b/src/layer/heatmapLayer.js
index ae8e34b1df..1c729001df 100644
--- a/src/layer/heatmapLayer.js
+++ b/src/layer/heatmapLayer.js
@@ -11,10 +11,10 @@ export default class HeatMapLayer extends Layer {
return this;
}
render() {
- this._prepareRender();
+ this.draw();
return this;
}
- _prepareRender() {
+ draw() {
this.init();
this.type = 'heatmap';
switch (this.shapeType) {
@@ -56,10 +56,4 @@ export default class HeatMapLayer extends Layer {
this.add(girdMesh);
}
- // afterRender() {
- // if (this.shapeType !== 'grid' && this.shapeType !== 'hexagon') {
- // updateIntensityPass(this);
- // }
- // }
-
}
diff --git a/src/layer/index.js b/src/layer/index.js
index f7754776e2..02e72edceb 100644
--- a/src/layer/index.js
+++ b/src/layer/index.js
@@ -14,4 +14,5 @@ registerLayer('RasterLayer', RasterLayer);
registerLayer('HeatmapLayer', HeatmapLayer);
export { LAYER_MAP } from './factory';
+export { registerLayer };
diff --git a/src/layer/lineLayer.js b/src/layer/lineLayer.js
index b31f8e96fa..bd039bc178 100644
--- a/src/layer/lineLayer.js
+++ b/src/layer/lineLayer.js
@@ -1,7 +1,12 @@
import Layer from '../core/layer';
import * as THREE from '../core/three';
import { LineBuffer } from '../geom/buffer/index';
-import { LineMaterial, ArcLineMaterial, MeshLineMaterial, DashLineMaterial } from '../geom/material/lineMaterial';
+import {
+ LineMaterial,
+ ArcLineMaterial,
+ MeshLineMaterial,
+ DashLineMaterial
+} from '../geom/material/lineMaterial';
export default class LineLayer extends Layer {
shape(type) {
this.shapeType = type;
@@ -10,26 +15,60 @@ export default class LineLayer extends Layer {
render() {
this.type = 'polyline';
this.init();
+ this.draw();
+ return this;
+ }
+ preRender() {
+ if (
+ this.animateDuration > 0 &&
+ this.animateDuration < this.scene._engine.clock.getElapsedTime()
+ ) {
+ this.layerMesh.material.setDefinesvalue('ANIMATE', false);
+ this.emit('animateEnd');
+ this.scene.stopAnimate();
+ this.animateDuration = Infinity;
+ }
+ }
+ draw() {
const layerData = this.layerData;
const style = this.get('styleOptions');
- const buffer = this._buffer = new LineBuffer({
+ const buffer = (this._buffer = new LineBuffer({
layerData,
shapeType: this.shapeType,
style
- });
+ }));
const { opacity } = this.get('styleOptions');
const animateOptions = this.get('animateOptions');
const activeOption = this.get('activedOptions');
+ // const layerCfg = {
+ // ...style,
+ // ...animateOptions,
+ // ...activeOption
+ // };
const geometry = new THREE.BufferGeometry();
const { attributes } = buffer;
-
if (this.shapeType === 'arc') {
geometry.setIndex(attributes.indexArray);
- geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
- geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
- geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
- geometry.addAttribute('a_instance', new THREE.Float32BufferAttribute(attributes.instances, 4));
- geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
+ geometry.addAttribute(
+ 'pickingId',
+ new THREE.Float32BufferAttribute(attributes.pickingIds, 1)
+ );
+ geometry.addAttribute(
+ 'position',
+ new THREE.Float32BufferAttribute(attributes.positions, 3)
+ );
+ geometry.addAttribute(
+ 'a_color',
+ new THREE.Float32BufferAttribute(attributes.colors, 4)
+ );
+ geometry.addAttribute(
+ 'a_instance',
+ new THREE.Float32BufferAttribute(attributes.instances, 4)
+ );
+ geometry.addAttribute(
+ 'a_size',
+ new THREE.Float32BufferAttribute(attributes.sizes, 1)
+ );
const material = new ArcLineMaterial({
u_opacity: opacity,
u_zoom: this.scene.getZoom(),
@@ -38,20 +77,40 @@ export default class LineLayer extends Layer {
const mesh = new THREE.Mesh(geometry, material);
this.add(mesh);
} else if (this.shapeType === 'line') {
-
+ // DrawLine(attributes, layerCfg)
geometry.setIndex(attributes.indexArray);
- geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
- geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
- geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
- geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
- geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normal, 3));
- geometry.addAttribute('a_miter', new THREE.Float32BufferAttribute(attributes.miter, 1));
- geometry.addAttribute('a_distance', new THREE.Float32BufferAttribute(attributes.attrDistance, 1));
+ geometry.addAttribute(
+ 'pickingId',
+ new THREE.Float32BufferAttribute(attributes.pickingIds, 1)
+ );
+ geometry.addAttribute(
+ 'position',
+ new THREE.Float32BufferAttribute(attributes.positions, 3)
+ );
+ geometry.addAttribute(
+ 'a_color',
+ new THREE.Float32BufferAttribute(attributes.colors, 4)
+ );
+ geometry.addAttribute(
+ 'a_size',
+ new THREE.Float32BufferAttribute(attributes.sizes, 1)
+ );
+ geometry.addAttribute(
+ 'normal',
+ new THREE.Float32BufferAttribute(attributes.normal, 3)
+ );
+ geometry.addAttribute(
+ 'a_miter',
+ new THREE.Float32BufferAttribute(attributes.miter, 1)
+ );
+ geometry.addAttribute(
+ 'a_distance',
+ new THREE.Float32BufferAttribute(attributes.attrDistance, 1)
+ );
const lineType = style.lineType;
let material;
if (lineType !== 'dash') {
-
material = new MeshLineMaterial({
u_opacity: opacity,
u_zoom: this.scene.getZoom(),
@@ -59,21 +118,27 @@ export default class LineLayer extends Layer {
});
if (animateOptions.enable) {
-
material.setDefinesvalue('ANIMATE', true);
this.scene.startAnimate();
- const { duration, interval, trailLength, repeat = Infinity } = animateOptions;
- this.animateDuration = this.scene._engine.clock.getElapsedTime() + duration * repeat;
+ const {
+ duration,
+ interval,
+ trailLength,
+ repeat = Infinity
+ } = animateOptions;
+ this.animateDuration =
+ this.scene._engine.clock.getElapsedTime() + duration * repeat;
material.upDateUninform({
u_duration: duration,
u_interval: interval,
u_trailLength: trailLength
});
-
-
}
} else {
- geometry.addAttribute('a_distance', new THREE.Float32BufferAttribute(attributes.attrDistance, 1));
+ geometry.addAttribute(
+ 'a_distance',
+ new THREE.Float32BufferAttribute(attributes.attrDistance, 1)
+ );
material = new DashLineMaterial({
u_opacity: opacity,
u_zoom: this.scene.getZoom(),
@@ -82,10 +147,20 @@ export default class LineLayer extends Layer {
}
const mesh = new THREE.Mesh(geometry, material);
this.add(mesh);
- } else { // 直线
- geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
- geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
- geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
+ } else {
+ // 直线
+ geometry.addAttribute(
+ 'pickingId',
+ new THREE.Float32BufferAttribute(attributes.pickingIds, 1)
+ );
+ geometry.addAttribute(
+ 'position',
+ new THREE.Float32BufferAttribute(attributes.vertices, 3)
+ );
+ geometry.addAttribute(
+ 'a_color',
+ new THREE.Float32BufferAttribute(attributes.colors, 4)
+ );
const material = new LineMaterial({
u_opacity: opacity,
u_time: 0,
@@ -99,14 +174,5 @@ export default class LineLayer extends Layer {
const mesh = new THREE.LineSegments(geometry, material);
this.add(mesh);
}
- return this;
- }
- preRender() {
- if (this.animateDuration > 0 && this.animateDuration < this.scene._engine.clock.getElapsedTime()) {
- this.layerMesh.material.setDefinesvalue('ANIMATE', false);
- this.emit('animateEnd');
- this.scene.stopAnimate();
- this.animateDuration = Infinity;
- }
}
}
diff --git a/src/layer/pointLayer.js b/src/layer/pointLayer.js
index de3cbf3a57..922830f94b 100644
--- a/src/layer/pointLayer.js
+++ b/src/layer/pointLayer.js
@@ -18,7 +18,7 @@ export default class PointLayer extends Layer {
this.type = 'point';
this.init();
if (!this._hasRender) {
- this._prepareRender(this.shapeType);
+ this.draw();
this._hasRender = true;
} else {
this._initAttrs();
@@ -28,7 +28,7 @@ export default class PointLayer extends Layer {
}
return this;
}
- _prepareRender() {
+ draw() {
const { stroke, fill } = this.get('styleOptions');
const style = this.get('styleOptions');
const activeOption = this.get('activedOptions');
@@ -37,6 +37,7 @@ export default class PointLayer extends Layer {
activeColor: activeOption.fill
};
const pointShapeType = this._getShape();
+ this.shapeType = pointShapeType;
switch (pointShapeType) {
case 'fill': { // 填充图形
if (fill !== 'none') {
@@ -112,4 +113,33 @@ export default class PointLayer extends Layer {
}
return 'text';
}
+ zoomchange(ev) {
+ super.zoomchange(ev);
+ this._updateData();
+ }
+ dragend(ev) {
+ super.dragend(ev);
+ this._updateData();
+
+ }
+ _updateData() {
+ if (this.layerSource.get('isCluster')) {
+ const bounds = this.scene.getBounds().toBounds();
+ const SW = bounds.getSouthWest();
+ const NE = bounds.getNorthEast();
+ const zoom = this.scene.getZoom();
+ const step = Math.max(NE.lng - SW.lng, NE.lat - SW.lat) / 2;
+ const bbox = [ SW.lng, SW.lat, NE.lng, NE.lat ];
+ // const bbox = [ SW.lng - step, SW.lat - step, NE.lng + step, NE.lat + step ];
+ const cfg = this.layerSource.get('cluster');
+ const preBox = cfg.bbox;
+ const preZoom = cfg.zoom;
+ if (!(preBox && preBox[0] < bbox[0] && preBox[1] < bbox[1] && preBox[2] > bbox[2] && preBox[3] < bbox[3] && // 当前范围在范围内
+ (Math.abs(zoom - preZoom)) < 1)) {
+ const newbbox = [ SW.lng - step, SW.lat - step, NE.lng + step, NE.lat + step ];
+ this.layerSource.updateCusterData(Math.floor(zoom), newbbox);
+ this.repaint();
+ }
+ }
+ }
}
diff --git a/src/layer/polygonLayer.js b/src/layer/polygonLayer.js
index 17c95244ef..267e29cc9b 100644
--- a/src/layer/polygonLayer.js
+++ b/src/layer/polygonLayer.js
@@ -9,7 +9,7 @@ export default class PolygonLayer extends Layer {
render() {
if (!this._hasRender) { // 首次渲染
this._hasRender = true;
- this._prepareRender();
+ this.draw();
} else {
this._initAttrs();
@@ -18,7 +18,7 @@ export default class PolygonLayer extends Layer {
}
return this;
}
- _prepareRender() {
+ draw() {
this.init();
this.type = 'polygon';
this._buffer = new PolygonBuffer({
@@ -29,7 +29,6 @@ export default class PolygonLayer extends Layer {
}
update() {
this.updateFilter(this.layerMesh);
- // 动态更新相关属性
}
_getLayerRender() {
const animateOptions = this.get('animateOptions');
diff --git a/src/layer/render/line/drawLine.js b/src/layer/render/line/drawLine.js
index e0a6f7a228..c509db47f4 100644
--- a/src/layer/render/line/drawLine.js
+++ b/src/layer/render/line/drawLine.js
@@ -23,5 +23,21 @@ export default function DrawLine(attributes, style) {
ANIMATE: animate
});
const arcMesh = new THREE.Mesh(geometry, lineMaterial);
+ if (animate) {
+ this.scene.startAnimate();
+ const {
+ duration,
+ interval,
+ trailLength,
+ repeat = Infinity
+ } = style;
+ this.animateDuration =
+ this.scene._engine.clock.getElapsedTime() + duration * repeat;
+ lineMaterial.upDateUninform({
+ u_duration: duration,
+ u_interval: interval,
+ u_trailLength: trailLength
+ });
+ }
return arcMesh;
}
diff --git a/src/layer/render/point/drawText.js b/src/layer/render/point/drawText.js
index 0604938e61..32fa9a28d5 100644
--- a/src/layer/render/point/drawText.js
+++ b/src/layer/render/point/drawText.js
@@ -37,7 +37,7 @@ export default function DrawText(attributes, style) {
attributes.fontAtlas.width,
attributes.fontAtlas.height
],
- u_gamma: 0.2,
+ u_gamma: (1.0 / 12.0) * (1.4142135623730951 / (2.0)),
u_buffer: 0.75,
u_opacity: opacity,
u_glSize: [ width, height ],
diff --git a/src/map/AMap.js b/src/map/AMap.js
index 29374ad778..b5666bee4a 100644
--- a/src/map/AMap.js
+++ b/src/map/AMap.js
@@ -128,6 +128,9 @@ export default class GaodeMap extends Base {
scene.setZoom = zoom => {
return map.setZoom(zoom);
};
+ scene.getBounds = () => {
+ return map.getBounds();
+ };
scene.setZoomAndCenter = (zoom, center) => {
const lnglat = new AMap.LngLat(center[0], center[1]);
return map.setZoomAndCenter(zoom, lnglat);
diff --git a/src/source/transform/cluster.js b/src/source/transform/cluster.js
index 645c7abcc0..4d87f3f360 100644
--- a/src/source/transform/cluster.js
+++ b/src/source/transform/cluster.js
@@ -38,10 +38,9 @@ export function cluster(data, option) {
};
});
data.dataArray = resultData;
- data.pointIndex = pointIndex;
- return data;
+ return { data, pointIndex };
}
-function formatData(clusterPoint) {
+export function formatData(clusterPoint) {
return clusterPoint.map((point, index) => {
return {
coordinates: point.geometry.coordinates,
diff --git a/test/unit/source/transfrom/cluster-spec.js b/test/unit/source/transfrom/cluster-spec.js
index f46ed7c23a..bd37f2a145 100644
--- a/test/unit/source/transfrom/cluster-spec.js
+++ b/test/unit/source/transfrom/cluster-spec.js
@@ -1,7 +1,7 @@
import { expect } from 'chai';
import { pointData } from '../../../asset/data/point';
import { cluster } from '../../../../src/source/transform/cluster';
-describe('hexagon Test', function() {
+describe('cluster Test', function() {
it('pointToCuster', function() {
const dataArray = pointData.map(item => {
@@ -17,7 +17,7 @@ describe('hexagon Test', function() {
dataArray,
extent: [ -180, -85, 180, 85 ]
};
- const grid = cluster(data, { radius: 40, field: 'v', zoom: 13 });
- expect(grid.dataArray.length).eql(26);
+ const grid = cluster(data, { radius: 40, field: 'v', zoom: 13, bbox: [ -180, -85, 180, 85 ] });
+ expect(grid.data.dataArray.length).eql(26);
});
});