diff --git a/demos/01_point_circle.html b/demos/01_point_circle.html
index f63a295ae3..88efe97d33 100644
--- a/demos/01_point_circle.html
+++ b/demos/01_point_circle.html
@@ -66,7 +66,7 @@
.color('point_count',["#002466","#105CB3","#2894E0","#CFF6FF","#FFF5B8","#FFAB5C","#F27049","#730D1C"])
.style({
stroke: 'rgb(255,255,255)',
- strokeWidth: 1,
+ strokeWidth: 2,
opacity: 1
})
.render();
@@ -76,7 +76,7 @@
})
.source(circleLayer.layerSource)
.shape('point_count', 'text')
- .active(true)
+ .active(false)
.filter('point_count',(p)=>{
return p > 50
})
@@ -84,10 +84,10 @@
.color('#fff')
.style({
stroke: '#999',
- strokeWidth: 0,
+ strokeWidth: 1,
opacity: 1.0
})
- .render();
+ .render();
console.log(layerText);
});
diff --git a/demos/06_text.html b/demos/06_text.html
index 79f636e663..3fd2bc4f61 100644
--- a/demos/06_text.html
+++ b/demos/06_text.html
@@ -29,8 +29,7 @@
});
window.scene = scene;
scene.on('loaded', () => {
- $.get('./data/provincePoint.geojson', data => {
- // data.features = data.features.slice(0,1);
+ $.get('./data/provincePoint.json', data => {
scene.PointLayer({
zIndex: 2
})
diff --git a/demos/assets/color-hash.js b/demos/assets/color-hash.js
new file mode 100644
index 0000000000..ce0dca5ef7
--- /dev/null
+++ b/demos/assets/color-hash.js
@@ -0,0 +1,173 @@
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ColorHash = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o MAX_SAFE_INTEGER) {
+ hash = parseInt(hash / seed2);
+ }
+ hash = hash * seed + str.charCodeAt(i);
+ }
+ return hash;
+ };
+
+ module.exports = BKDRHash;
+
+ },{}],2:[function(require,module,exports){
+ var BKDRHash = require('./bkdr-hash');
+
+ /**
+ * Convert RGB Array to HEX
+ *
+ * @param {Array} RGBArray - [R, G, B]
+ * @returns {String} 6 digits hex starting with #
+ */
+ var RGB2HEX = function(RGBArray) {
+ var hex = '#';
+ RGBArray.forEach(function(value) {
+ if (value < 16) {
+ hex += 0;
+ }
+ hex += value.toString(16);
+ });
+ return hex;
+ };
+
+ /**
+ * Convert HSL to RGB
+ *
+ * @see {@link http://zh.wikipedia.org/wiki/HSL和HSV色彩空间} for further information.
+ * @param {Number} H Hue ∈ [0, 360)
+ * @param {Number} S Saturation ∈ [0, 1]
+ * @param {Number} L Lightness ∈ [0, 1]
+ * @returns {Array} R, G, B ∈ [0, 255]
+ */
+ var HSL2RGB = function(H, S, L) {
+ H /= 360;
+
+ var q = L < 0.5 ? L * (1 + S) : L + S - L * S;
+ var p = 2 * L - q;
+
+ return [H + 1/3, H, H - 1/3].map(function(color) {
+ if(color < 0) {
+ color++;
+ }
+ if(color > 1) {
+ color--;
+ }
+ if(color < 1/6) {
+ color = p + (q - p) * 6 * color;
+ } else if(color < 0.5) {
+ color = q;
+ } else if(color < 2/3) {
+ color = p + (q - p) * 6 * (2/3 - color);
+ } else {
+ color = p;
+ }
+ return Math.round(color * 255);
+ });
+ };
+
+ function isArray(o) {
+ return Object.prototype.toString.call(o) === '[object Array]';
+ }
+
+ /**
+ * Color Hash Class
+ *
+ * @class
+ */
+ var ColorHash = function(options) {
+ options = options || {};
+
+ var LS = [options.lightness, options.saturation].map(function(param) {
+ param = param || [0.35, 0.5, 0.65]; // note that 3 is a prime
+ return isArray(param) ? param.concat() : [param];
+ });
+
+ this.L = LS[0];
+ this.S = LS[1];
+
+ if (typeof options.hue === 'number') {
+ options.hue = {min: options.hue, max: options.hue};
+ }
+ if (typeof options.hue === 'object' && !isArray(options.hue)) {
+ options.hue = [options.hue];
+ }
+ if (typeof options.hue === 'undefined') {
+ options.hue = [];
+ }
+ this.hueRanges = options.hue.map(function (range) {
+ return {
+ min: typeof range.min === 'undefined' ? 0 : range.min,
+ max: typeof range.max === 'undefined' ? 360: range.max
+ };
+ });
+
+ this.hash = options.hash || BKDRHash;
+ };
+
+ /**
+ * Returns the hash in [h, s, l].
+ * Note that H ∈ [0, 360); S ∈ [0, 1]; L ∈ [0, 1];
+ *
+ * @param {String} str string to hash
+ * @returns {Array} [h, s, l]
+ */
+ ColorHash.prototype.hsl = function(str) {
+ var H, S, L;
+ var hash = this.hash(str);
+
+ if (this.hueRanges.length) {
+ var range = this.hueRanges[hash % this.hueRanges.length];
+ var hueResolution = 727; // note that 727 is a prime
+ H = ((hash / this.hueRanges.length) % hueResolution) * (range.max - range.min) / hueResolution + range.min;
+ } else {
+ H = hash % 359; // note that 359 is a prime
+ }
+ hash = parseInt(hash / 360);
+ S = this.S[hash % this.S.length];
+ hash = parseInt(hash / this.S.length);
+ L = this.L[hash % this.L.length];
+
+ return [H, S, L];
+ };
+
+ /**
+ * Returns the hash in [r, g, b].
+ * Note that R, G, B ∈ [0, 255]
+ *
+ * @param {String} str string to hash
+ * @returns {Array} [r, g, b]
+ */
+ ColorHash.prototype.rgb = function(str) {
+ var hsl = this.hsl(str);
+ return HSL2RGB.apply(this, hsl);
+ };
+
+ /**
+ * Returns the hash in hex
+ *
+ * @param {String} str string to hash
+ * @returns {String} hex with #
+ */
+ ColorHash.prototype.hex = function(str) {
+ var rgb = this.rgb(str);
+ return RGB2HEX(rgb);
+ };
+
+ module.exports = ColorHash;
+
+ },{"./bkdr-hash":1}]},{},[2])(2)
+ });
\ No newline at end of file
diff --git a/demos/taxi.html b/demos/taxi.html
index d8ea264443..dc2edc621e 100644
--- a/demos/taxi.html
+++ b/demos/taxi.html
@@ -39,7 +39,7 @@
//.color('#F08D41')
.color('#ff893a')
.animate({enable:true})
- .render();
+ //.render();
});
$.get('https://gw.alipayobjects.com/os/rmsportal/vmvAxgsEwbpoSWbSYvix.json', data => {
buildLayer = scene.PolygonLayer({
diff --git a/demos/tile.html b/demos/tile.html
index b3ac0aaae2..cd97a2c849 100644
--- a/demos/tile.html
+++ b/demos/tile.html
@@ -47,6 +47,7 @@
}
)
.source(city)
+ .active(false)
.color('pm2_5_24h',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"])
.shape('fill')
.style({
diff --git a/demos/vectorTile.html b/demos/vectorTile.html
new file mode 100644
index 0000000000..720922f3aa
--- /dev/null
+++ b/demos/vectorTile.html
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+ hexagon demo
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/vectorTilepolygon.html b/demos/vectorTilepolygon.html
new file mode 100644
index 0000000000..ce4df2bf67
--- /dev/null
+++ b/demos/vectorTilepolygon.html
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+ hexagon demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/vectorheatMap.html b/demos/vectorheatMap.html
new file mode 100644
index 0000000000..4dd387940d
--- /dev/null
+++ b/demos/vectorheatMap.html
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+ hexagon demo
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
index 5e4095f1c6..723a1e1cf1 100755
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@antv/l7",
- "version": "1.1.10",
+ "version": "1.1.11",
"description": "Large-scale WebGL-powered Geospatial Data Visualization",
"main": "build/l7.js",
"browser": "build/l7.js",
diff --git a/src/core/engine/index.js b/src/core/engine/index.js
index 9f04690f43..5a379e0778 100644
--- a/src/core/engine/index.js
+++ b/src/core/engine/index.js
@@ -10,11 +10,11 @@ export default class Engine extends EventEmitter {
this._scene = Scene;
this._camera = new Camera(container).camera;
this._renderer = new Renderer(container).renderer;
- this._world = world;
+ this._world = world;// 地图场景实例
// for MapBox
this.world = new THREE.Group();
this._scene.add(this.world);
- this._picking = Picking(this._world, this._renderer, this._camera, this._scene);
+ this._picking = Picking(this._world, this._renderer, this._camera);
this.clock = new THREE.Clock();
this.composerLayers = [];
}
@@ -24,11 +24,15 @@ export default class Engine extends EventEmitter {
});
}
update() {
+ this._renderer.clear();
this._renderer.render(this._scene, this._camera);
this._initPostProcessing();
}
destroy() {
-
+ }
+ // 渲染第三方Scene对象
+ renderScene(scene) {
+ this._renderer.render(scene, this._camera);
}
run() {
this.update();
diff --git a/src/core/engine/picking/picking.js b/src/core/engine/picking/picking.js
index 3d61d86427..a332d1ea51 100755
--- a/src/core/engine/picking/picking.js
+++ b/src/core/engine/picking/picking.js
@@ -3,13 +3,10 @@ import * as THREE from '../../three';
let nextId = 1;
class Picking {
- constructor(world, renderer, camera, scene) {
+ constructor(world, renderer, camera) {
this._world = world;
this._renderer = renderer;
this._camera = camera;
- this._raycaster = new THREE.Raycaster();
- this.scene = scene;
- this._raycaster.linePrecision = 10;
this._pickingScene = PickingScene;
this.world = new THREE.Group();
this._pickingScene.add(this.world);
@@ -49,12 +46,11 @@ class Picking {
this._height = size.height;
this._pickingTexture.setSize(this._width, this._height);
this._pixelBuffer = new Uint8Array(4 * this._width * this._height);
-
this._needUpdate = true;
}
_update(point) {
-
const texture = this._pickingTexture;
+ // this._pickingTexture
this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);
this.pixelBuffer = new Uint8Array(4);
this._renderer.readRenderTargetPixels(texture, point.x, this._height - point.y, 1, 1, this.pixelBuffer);
@@ -76,9 +72,9 @@ class Picking {
});
}
- _updateRender() {
- this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);
- }
+ // _updateRender() {
+ // this._renderer.render(this._pickingScene, this._camera, this._pickingTexture);
+ // }
_pick(point, normalisedPoint, layerId) {
this._update(point);
@@ -125,8 +121,6 @@ class Picking {
this._world._container.removeEventListener(event[0], event[1], false);
});
- this._world.off('move', this._onWorldMove);
-
if (this._pickingScene.children) {
// Remove everything else in the layer
let child;
diff --git a/src/core/engine/renderer.js b/src/core/engine/renderer.js
index fd4d64a6d5..4607a8fe3b 100644
--- a/src/core/engine/renderer.js
+++ b/src/core/engine/renderer.js
@@ -9,7 +9,8 @@ export default class Renderer {
initRender() {
this.renderer = new THREE.WebGLRenderer({
antialias: true,
- alpha: true
+ alpha: true,
+ autoClear: false
});
this.renderer.setClearColor(0xff0000, 0.0);
this.pixelRatio = window.devicePixelRatio;
diff --git a/src/core/layer.js b/src/core/layer.js
index 9523aa21eb..c8714d232d 100644
--- a/src/core/layer.js
+++ b/src/core/layer.js
@@ -11,6 +11,7 @@ import pickingFragmentShader from '../core/engine/picking/picking_frag.glsl';
import { getInteraction } from '../interaction/index';
import Attr from '../attr/index';
import diff from '../util/diff';
+import { updateObjecteUniform } from '../util/object3d-util';
import Util from '../util';
import Global from '../global';
let id = 1;
@@ -97,8 +98,10 @@ export default class Layer extends Base {
this._visibleWithZoom();
object.onBeforeRender = () => { // 每次渲染前改变状态
const zoom = this.scene.getZoom();
- object.material.setUniformsValue('u_time', this.scene._engine.clock.getElapsedTime());
- object.material.setUniformsValue('u_zoom', zoom);
+ updateObjecteUniform(this._object3D, {
+ u_time: this.scene._engine.clock.getElapsedTime(),
+ u_zoom: zoom
+ });
this.preRender();
};
@@ -309,7 +312,7 @@ export default class Layer extends Base {
}
createScale(field) {
- const data = this.layerSource.data.dataArray;
+ const data = this.layerSource ? this.layerSource.data.dataArray : null;
const scales = this.get('scales');
let scale = scales[field];
const scaleController = this.get('scaleController');
@@ -370,17 +373,20 @@ export default class Layer extends Base {
setActive(id, color) {
this._activeIds = id;
- this.layerMesh.material.setUniformsValue('u_activeId', id);
if (!Array.isArray(color)) {
color = ColorUtil.color2RGBA(color);
}
- this.layerMesh.material.setUniformsValue('u_activeColor', color);
+ updateObjecteUniform(this._object3D, {
+ u_activeColor: color,
+ u_activeId: id
+ });
+ this.scene._engine.update();
}
_addActiveFeature(e) {
const { featureId } = e;
this._activeIds = featureId;
- this.layerMesh.material.setUniformsValue('u_activeId', featureId);
+ updateObjecteUniform(this._object3D, { u_activeId: featureId });
}
@@ -404,7 +410,7 @@ export default class Layer extends Base {
const nextAttrs = this.get('attrOptions');
const preStyle = this.get('preStyleOption');
const nextStyle = this.get('styleOptions');
- if (preAttrs === undefined && preStyle === undefined) {
+ if (preAttrs === undefined && preStyle === undefined) { // 首次渲染
this._mapping();
this._setPreOption();
this._scaleByZoom();
@@ -487,15 +493,15 @@ export default class Layer extends Base {
for (const key in option) {
newOption['u_' + key] = option[key];
}
- this.layerMesh.material.updateUninform(newOption);
-
+ updateObjecteUniform(this._object3D, newOption);
}
- _mapping() {
+ _mapping(source) {
const self = this;
const attrs = self.get('attrs');
const mappedData = [];
// const data = this.layerSource.propertiesData;
- const data = this.layerSource.data.dataArray;
+ let data;
+ source ? data = source.data.dataArray : data = this.layerSource.data.dataArray;
for (let i = 0; i < data.length; i++) {
const record = data[i];
const newRecord = {};
@@ -528,14 +534,16 @@ export default class Layer extends Base {
});
}
this.layerData = mappedData;
+ return mappedData;
}
// 更新地图映射
- _updateMaping() {
+ _updateMaping(source, layer) {
const self = this;
const attrs = self.get('attrs');
- const data = this.layerSource.data.dataArray;
+ const data = source ? source.data.dataArray : this.layerSource.data.dataArray;
+ const layerData = layer || this.layerData;
for (let i = 0; i < data.length; i++) {
const record = data[i];
for (const attrName in attrs) {
@@ -547,10 +555,10 @@ export default class Layer extends Base {
for (let j = 0; j < values.length; j++) {
const val = values[j];
const name = names[j];
- this.layerData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
+ layerData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
}
} else {
- this.layerData[i][names[0]] = values.length === 1 ? values[0] : values;
+ layerData[i][names[0]] = values.length === 1 ? values[0] : values;
}
attr.neadUpdate = true;
@@ -603,10 +611,9 @@ export default class Layer extends Base {
pickmaterial.fragmentShader = pickingFragmentShader;
const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
pickingMesh.name = this.layerId;
- pickmaterial.setDefinesvalue(this.type, true);
pickingMesh.onBeforeRender = () => {
const zoom = this.scene.getZoom();
- pickingMesh.material.setUniformsValue('u_zoom', zoom);
+ updateObjecteUniform(pickingMesh, { u_zoom: zoom });
};
this._pickingMesh.add(pickingMesh);
@@ -618,9 +625,10 @@ export default class Layer extends Base {
type = 'mouseleave';
}
this._activeIds = featureId;
- const feature = this.layerSource.getSelectFeature(featureId);
+ // TODO 瓦片图层获取选中数据信息
const lnglat = this.scene.containerToLngLat(point2d);
- const style = this.layerData[featureId - 1];
+ const { feature, style } = this.getSelectFeature(featureId, lnglat);
+ // const style = this.layerData[featureId - 1];
const target = {
featureId,
feature,
@@ -629,12 +637,20 @@ export default class Layer extends Base {
type,
lnglat: { lng: lnglat.lng, lat: lnglat.lat }
};
- if (featureId >= 0 || this._activeIds !== null) { // 拾取到元素,或者离开元素
+ if (featureId >= 0 || this._activeIds >= 0) { // 拾取到元素,或者离开元素
this.emit(type, target);
}
});
}
+ getSelectFeature(featureId) {
+ const feature = this.layerSource.getSelectFeature(featureId);
+ const style = this.layerData[featureId - 1];
+ return {
+ feature,
+ style
+ };
+ }
/**
* 用于过滤数据
* @param {*} object 更新颜色和数据过滤
@@ -668,6 +684,7 @@ export default class Layer extends Base {
pickAttr.needsUpdate = true;
}
_visibleWithZoom() {
+ if (this._object3D === null) return;
const zoom = this.scene.getZoom();
const minZoom = this.get('minZoom');
const maxZoom = this.get('maxZoom');
@@ -734,13 +751,16 @@ export default class Layer extends Base {
}
interactions[type] = interaction;
}
+ styleCfg() {
+
+ }
/**
* 重置高亮要素
*/
_resetStyle() {
this._activeIds = null;
- this.layerMesh.material.setUniformsValue('u_activeId', 0);
+ updateObjecteUniform(this._object3D, { u_activeId: 0 });
}
/**
* 销毁Layer对象
@@ -751,7 +771,6 @@ export default class Layer extends Base {
this.clearMapEvent();
if (this._object3D.type === 'composer') {
this.remove(this._object3D);
-
return;
}
if (this._object3D && this._object3D.children) {
@@ -778,8 +797,19 @@ export default class Layer extends Base {
child = null;
}
}
+ this.layerMesh.geometry = null;
+ this.layerMesh.material.dispose();
+ this.layerMesh.material = null;
+ if (this._pickingMesh) {
+ this._pickingMesh.children[0].geometry = null;
+ this._pickingMesh.children[0].material.dispose();
+ this._pickingMesh.children[0].material = null;
+ }
+ this._buffer = null;
this._object3D = null;
this.scene._engine._scene.remove(this._object3D);
+ this.layerData.length = 0;
+ this.layerSource = null;
this.scene._engine._picking.remove(this._pickingMesh);
this.destroyed = true;
}
diff --git a/src/core/scene.js b/src/core/scene.js
index 0789516806..50823980fd 100644
--- a/src/core/scene.js
+++ b/src/core/scene.js
@@ -26,6 +26,7 @@ export default class Scene extends Base {
_initEngine(mapContainer) {
this._engine = new Engine(mapContainer, this);
this.registerMapEvent();
+ // this._engine.run();
// this.workerPool = new WorkerPool();
compileBuiltinModules();
}
@@ -73,7 +74,6 @@ export default class Scene extends Base {
}
off(type, hander) {
if (this.map) { this.map.off(type, hander); }
-
super.off(type, hander);
}
addImage() {
diff --git a/src/core/source.js b/src/core/source.js
index 765636ea5d..8b8fd97a92 100644
--- a/src/core/source.js
+++ b/src/core/source.js
@@ -56,7 +56,9 @@ export default class Source extends Base {
const { type = 'geojson' } = parser;
const data = this.get('data');
this.originData = getParser(type)(data, parser);
- this.data = clone(this.originData);
+ this.data = {
+ dataArray: clone(this.originData.dataArray)
+ };
this.data.extent = extent(this.data.dataArray);
}
/**
@@ -150,4 +152,8 @@ export default class Source extends Base {
}
return featureIndex;
}
+ destroy() {
+ this.data = null;
+ this.originData = null;
+ }
}
diff --git a/src/geom/buffer/point/normalBuffer.js b/src/geom/buffer/point/normalBuffer.js
index 755e7697a3..696cbb6290 100644
--- a/src/geom/buffer/point/normalBuffer.js
+++ b/src/geom/buffer/point/normalBuffer.js
@@ -13,7 +13,5 @@ export default function NormalBuffer(layerData) {
attributes.sizes.push(size);
});
-
-
return attributes;
}
diff --git a/src/geom/material/heatmapMateial.js b/src/geom/material/heatmapMaterial.js
similarity index 100%
rename from src/geom/material/heatmapMateial.js
rename to src/geom/material/heatmapMaterial.js
diff --git a/src/geom/material/pointLineMaterial.js b/src/geom/material/pointLineMaterial.js
index ca6242e0f2..c84c5911f5 100644
--- a/src/geom/material/pointLineMaterial.js
+++ b/src/geom/material/pointLineMaterial.js
@@ -8,7 +8,7 @@ export default class PointLineMaterial extends Material {
u_stroke: { value: [ 1.0, 1.0, 1.0, 1.0 ] },
u_strokeWidth: { value: 1.0 },
u_zoom: { value: 10 },
- u_activeId: { value: -1 },
+ u_activeId: { value: 0 },
u_activeColor: { value: [ 1.0, 0, 0, 1.0 ] }
}
diff --git a/src/geom/material/tile/maskMaterial.js b/src/geom/material/tile/maskMaterial.js
new file mode 100644
index 0000000000..36ddd9e098
--- /dev/null
+++ b/src/geom/material/tile/maskMaterial.js
@@ -0,0 +1,24 @@
+import Material from './../material';
+import { getModule } from '../../../util/shaderModule';
+export default class MaskMaterial extends Material {
+ getDefaultParameters() {
+ return {
+ uniforms: {
+ },
+ defines: {
+
+ }
+ };
+ }
+ constructor(_uniforms, _defines, parameters) {
+ super(parameters);
+ const { uniforms, defines } = this.getDefaultParameters();
+ const { vs, fs } = getModule('mask_quard');
+ this.uniforms = Object.assign(uniforms, this.setUniform(_uniforms));
+ this.type = 'MaskMaterial';
+ this.defines = Object.assign(defines, _defines);
+ this.vertexShader = vs;
+ this.fragmentShader = fs;
+ this.transparent = true;
+ }
+}
diff --git a/src/geom/shader/index.js b/src/geom/shader/index.js
index 23e47bf8df..e6ff0c5c79 100644
--- a/src/geom/shader/index.js
+++ b/src/geom/shader/index.js
@@ -41,6 +41,11 @@ import raster_frag from '../shader/raster_frag.glsl';
import tile_polygon_vert from '../shader/tile/polygon_vert.glsl';
import tile_polygon_frag from '../shader/tile/polygon_frag.glsl';
+// mask
+import mask_quard_vert from '../shader/tile/mask_quard_vert.glsl';
+import mask_quard_frag from '../shader/tile/mask_quard_frag.glsl';
+
+
import common from './common.glsl';
import { registerModule } from '../../util/shaderModule';
import pick_color from './shaderChunks/pick_color.glsl';
@@ -60,5 +65,6 @@ export function compileBuiltinModules() {
registerModule('image', { vs: image_vert, fs: image_frag });
registerModule('raster', { vs: raster_vert, fs: raster_frag });
registerModule('tilepolygon', { vs: tile_polygon_vert, fs: tile_polygon_frag });
+ registerModule('mask_quard', { vs: mask_quard_vert, fs: mask_quard_frag });
}
diff --git a/src/geom/shader/meshline_vert.glsl b/src/geom/shader/meshline_vert.glsl
index 2a5a87aefe..2bf13b88ea 100644
--- a/src/geom/shader/meshline_vert.glsl
+++ b/src/geom/shader/meshline_vert.glsl
@@ -6,7 +6,7 @@ attribute float a_dash_array;
uniform float u_zoom;
uniform float u_time : 0;
-uniform float u_activeId : 1;
+uniform float u_activeId : 0;
uniform vec4 u_activeColor : [ 1.0, 0, 0, 1.0 ];
varying float v_time;
diff --git a/src/geom/shader/point_frag.glsl b/src/geom/shader/point_frag.glsl
index f14cbd46c2..30ff5a6623 100644
--- a/src/geom/shader/point_frag.glsl
+++ b/src/geom/shader/point_frag.glsl
@@ -20,11 +20,11 @@ const vec3 halo = vec3( 1.0 );
void main() {
// 纹理坐标
#ifdef TEXCOORD_0
- vec2 pos = v_uv + gl_PointCoord / 512.0 * 64.0;
- pos.y = 1.0 - pos.y;
- vec4 textureColor = texture2D(u_texture, pos);
- gl_FragColor =textureColor;
- return;
+ vec2 pos = v_uv + gl_PointCoord / 512.0 * 64.0;
+ pos.y = 1.0 - pos.y;
+ vec4 textureColor = texture2D(u_texture, pos);
+ gl_FragColor =textureColor;
+ return;
#endif
if(v_color.a == 0.)
discard;
diff --git a/src/geom/shader/point_meshLine_vert.glsl b/src/geom/shader/point_meshLine_vert.glsl
index d4773d23e6..023a75f17d 100644
--- a/src/geom/shader/point_meshLine_vert.glsl
+++ b/src/geom/shader/point_meshLine_vert.glsl
@@ -21,10 +21,12 @@ void main() {
#endif
v_color = u_stroke;
v_color.a *= u_strokeOpacity;
+
+ v_pickingId = pickingId;
if(v_pickingId == u_activeId) {
v_color = u_activeColor;
}
- v_pickingId = pickingId;
+
//vec3 pointPos = newposition.xyz + vec3(normal * u_strokeWidth * pow(2.0,20.0-u_zoom) / 2.0 * a_miter);
vec3 pointPos = newposition.xyz + vec3(normal * u_strokeWidth * scale / 2.0 * a_miter);
gl_Position = matModelViewProjection * vec4(pointPos, 1.0);
diff --git a/src/geom/shader/point_vert.glsl b/src/geom/shader/point_vert.glsl
index d394e556fc..874376fe9a 100644
--- a/src/geom/shader/point_vert.glsl
+++ b/src/geom/shader/point_vert.glsl
@@ -16,7 +16,7 @@ void main() {
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
v_color = a_color;
v_color.a *= u_opacity;
- if(pickingId == u_activeId) {
+ if(pickingId == u_activeId) {
v_color = u_activeColor;
}
gl_Position = matModelViewProjection * vec4(position, 1.0);
diff --git a/src/geom/shader/tile/mask_quard_frag.glsl b/src/geom/shader/tile/mask_quard_frag.glsl
new file mode 100644
index 0000000000..6b4ceede8f
--- /dev/null
+++ b/src/geom/shader/tile/mask_quard_frag.glsl
@@ -0,0 +1,4 @@
+ precision highp float;
+ void main() {
+ gl_FragColor = vec4(1.0);
+}
\ No newline at end of file
diff --git a/src/geom/shader/tile/mask_quard_vert.glsl b/src/geom/shader/tile/mask_quard_vert.glsl
new file mode 100644
index 0000000000..b8988414c9
--- /dev/null
+++ b/src/geom/shader/tile/mask_quard_vert.glsl
@@ -0,0 +1,6 @@
+precision highp float;
+void main(){
+ mat4 matModelViewProjection=projectionMatrix*modelViewMatrix;
+ gl_Position = matModelViewProjection * vec4(position, 1.0);
+
+}
\ No newline at end of file
diff --git a/src/geom/shape/line.js b/src/geom/shape/line.js
index c3849a8f8d..5ac514067b 100644
--- a/src/geom/shape/line.js
+++ b/src/geom/shape/line.js
@@ -65,8 +65,11 @@ export function defaultLine(geo, index) {
return { positions, indexes: indexArray };
}
// mesh line
+
export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
- if (path.length === 1) path = path[0];// 面坐标转线坐标
+ if (Array.isArray(path[0][0])) {
+ path = path[0]; // 面坐标转线坐标
+ }
const positions = [];
const pickingIds = [];
const normal = [];
@@ -78,12 +81,13 @@ export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
let attrDistance = [];
const sizes = [];
- const { size, color, id } = props;
+ let { size, color, id } = props;
+ !Array.isArray(size) && (size = [ size ]);
attrPos.forEach((point, pointIndex) => {
colors.push(...color);
pickingIds.push(id);
sizes.push(size[0]);
- point[2] = size[1];
+ point[2] = size[1] || 0;
positions.push(...point);
if (pointIndex === 0 || pointIndex === 1) {
@@ -109,7 +113,6 @@ export function Line(path, props, positionsIndex, lengthPerDashSegment = 200) {
attrDistance = attrDistance.map(d => {
return d / totalLength;
});
-
return {
positions,
normal,
diff --git a/src/global.js b/src/global.js
index f33666f102..b6f5e5341e 100644
--- a/src/global.js
+++ b/src/global.js
@@ -5,7 +5,7 @@
// const Global = {};
const FONT_FAMILY = '"-apple-system", BlinkMacSystemFont, "Segoe UI", Roboto,"Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",SimSun, "sans-serif"';
const Global = {
- version: '1.0.0',
+ version: '1.11.1',
scene: {
mapType: 'AMAP',
zoom: 5,
diff --git a/src/interaction/hash.js b/src/interaction/hash.js
index 04b1bcb86d..abe5cc48a9 100644
--- a/src/interaction/hash.js
+++ b/src/interaction/hash.js
@@ -13,7 +13,7 @@ export default class Hash extends Interaction {
this._updateHash();
}
reset() {
- this.layer._resetStyle();
+ // this.layer._resetStyle();
}
_getHashString() {
const center = this.layer.getCenter(),
diff --git a/src/layer/heatmapLayer.js b/src/layer/heatmapLayer.js
index e47b5656fd..b75c270c1f 100644
--- a/src/layer/heatmapLayer.js
+++ b/src/layer/heatmapLayer.js
@@ -1,9 +1,5 @@
import Layer from '../core/layer';
-import gridBuffer from '../geom/buffer/heatmap/grid';
-import DrawGrid from './render/heatmap/gird';
-import DrawHexagon from './render/heatmap/hexagon';
-import { drawHeatmap } from './render/heatmap/heatmap';
-import hexagonBuffer from '../geom/buffer/heatmap/hexagon';
+import { getRender } from './render/';
export default class HeatMapLayer extends Layer {
shape(type) {
@@ -12,43 +8,6 @@ export default class HeatMapLayer extends Layer {
}
draw() {
this.type = 'heatmap';
- switch (this.shapeType) {
- case 'grid' :
- this._drawGrid();
- break;
- case 'hexagon' :
- this._drawHexagon();
- break;
- default:
- drawHeatmap(this);
- }
+ this.add(getRender('heatmap', this.shapeType || 'heatmap')(this.layerData, this, this.layerSource));
}
- _drawHexagon() {
- const style = this.get('styleOptions');
- const activeOption = this.get('activedOptions');
- const { radius } = this.layerSource.data;
- this._buffer = new hexagonBuffer(this.layerData);
- const config = {
- ...style,
- radius,
- activeColor: activeOption.fill
- };
- const Mesh = new DrawHexagon(this._buffer, config);
- this.add(Mesh);
- }
- _drawGrid() {
- const style = this.get('styleOptions');
- const activeOption = this.get('activedOptions');
- const { xOffset, yOffset } = this.layerSource.data;
- this._buffer = new gridBuffer(this.layerData);
- const config = {
- ...style,
- xOffset,
- yOffset,
- activeColor: activeOption.fill
- };
- const girdMesh = new DrawGrid(this._buffer, config);
- this.add(girdMesh);
- }
-
}
diff --git a/src/layer/index.js b/src/layer/index.js
index 8b33d8534e..04c572c984 100644
--- a/src/layer/index.js
+++ b/src/layer/index.js
@@ -7,6 +7,7 @@ import RasterLayer from './rasterLayer';
import HeatmapLayer from './heatmapLayer';
import TileLayer from './tile/tileLayer';
import ImageTileLayer from './tile/imageTileLayer';
+import VectorTileLayer from './tile/VectorTileLayer';
registerLayer('PolygonLayer', PolygonLayer);
registerLayer('PointLayer', PointLayer);
@@ -16,7 +17,8 @@ registerLayer('RasterLayer', RasterLayer);
registerLayer('HeatmapLayer', HeatmapLayer);
registerLayer('TileLayer', TileLayer);
registerLayer('ImageTileLayer', ImageTileLayer);
+registerLayer('VectorTileLayer', VectorTileLayer);
-export { LAYER_MAP } from './factory';
+export { LAYER_MAP, getLayer } from './factory';
export { registerLayer };
diff --git a/src/layer/lineLayer.js b/src/layer/lineLayer.js
index 4a2046686e..489c1ac999 100644
--- a/src/layer/lineLayer.js
+++ b/src/layer/lineLayer.js
@@ -1,7 +1,5 @@
import Layer from '../core/layer';
-import DrawLine from './render/line/drawMeshLine';
-import DrawArc from './render/line/drawArc';
-import { LineBuffer } from '../geom/buffer/index';
+import { getRender } from './render/';
export default class LineLayer extends Layer {
shape(type) {
this.shapeType = type;
@@ -19,27 +17,7 @@ export default class LineLayer extends Layer {
}
}
draw() {
- this.type = 'polyline';
- const layerData = this.layerData;
- const style = this.get('styleOptions');
- const animateOptions = this.get('animateOptions');
- const activeOption = this.get('activedOptions');
- const layerCfg = {
- zoom: this.scene.getZoom(),
- style,
- animateOptions,
- activeOption
- };
- const buffer = (this._buffer = new LineBuffer({
- layerData,
- shapeType: this.shapeType,
- style
- }));
- const { attributes } = buffer;
- if (this.shapeType === 'arc') {
- DrawArc(attributes, layerCfg, this);
- } else {
- DrawLine(attributes, layerCfg, this);
- }
+ this.type = 'line';
+ this.add(getRender('line', this.shapeType || 'line')(this.layerData, this, this.layerSource));
}
}
diff --git a/src/layer/pointLayer.js b/src/layer/pointLayer.js
index 1e6efc7ae3..07d915c127 100644
--- a/src/layer/pointLayer.js
+++ b/src/layer/pointLayer.js
@@ -1,10 +1,6 @@
import Layer from '../core/layer';
-import * as drawPoint from '../layer/render/point';
-import TextBuffer from '../geom/buffer/point/text';
-import DrawText from './render/point/drawText';
import Global from '../global';
-// import PointBuffer from '../geom/buffer/point';
-import * as PointBuffer from '../geom/buffer/point/index';
+import { getRender } from './render/';
const { pointShape } = Global;
/**
* point shape 2d circle, traingle text,image
@@ -16,67 +12,9 @@ const { pointShape } = Global;
export default class PointLayer extends Layer {
draw() {
this.type = 'point';
- const { stroke, fill } = this.get('styleOptions');
- const style = this.get('styleOptions');
- const activeOption = this.get('activedOptions');
- const config = {
- ...style,
- activeColor: activeOption.fill
- };
- const pointShapeType = this._getShape();
- this.shapeType = pointShapeType;
- switch (pointShapeType) {
- case 'fill': { // 填充图形
- if (fill !== 'none') {
- // 是否填充
- const attributes = PointBuffer.FillBuffer(this.layerData, style);
- const meshfill = drawPoint.DrawFill(attributes, config);
- this.add(meshfill);
- }
- if (stroke !== 'none') {
- // 是否绘制边界
- const lineAttribute = PointBuffer.StrokeBuffer(this.layerData, style);
- const meshStroke = drawPoint.DrawStroke(lineAttribute, config);
- this.add(meshStroke, 'line');
- }
- break;
- }
- case 'image': { // 绘制图片标注
- const imageAttribute = PointBuffer.ImageBuffer(this.layerData, {
- imagePos: this.scene.image.imagePos
- });
- const imageMesh = drawPoint.DrawImage(imageAttribute, {
- ...style,
- texture: this.scene.image.texture
- });
- this.add(imageMesh);
- break;
- }
- case 'normal': { // 原生点
- const normalAttribute = PointBuffer.NormalBuffer(this.layerData, style);
- const normalPointMesh = drawPoint.DrawNormal(normalAttribute, config);
- this.add(normalPointMesh);
- break;
- }
- case 'text': { // 原生点
- const { width, height } = this.scene.getSize();
- const textCfg = {
- ...style,
- width,
- height,
- activeColor: activeOption.fill
- };
- const buffer = new TextBuffer(
- this.layerData,
- this.scene.fontAtlasManager
- );
- const mesh = new DrawText(buffer, textCfg);
- this.add(mesh);
- break;
- }
- default:
- return null;
- }
+ this.shapeType = this._getShape();
+ const mesh = getRender(this.type, this.shapeType)(this.layerData, this, this.layerSource);
+ this.add(mesh);
}
_getShape() {
diff --git a/src/layer/polygonLayer.js b/src/layer/polygonLayer.js
index e25c052038..32779aa2c2 100644
--- a/src/layer/polygonLayer.js
+++ b/src/layer/polygonLayer.js
@@ -1,6 +1,5 @@
import Layer from '../core/layer';
-import * as drawPolygon from './render/polygon';
-import PolygonBuffer from '../geom/buffer/polygon';
+import { getRender } from './render/';
export default class PolygonLayer extends Layer {
shape(type) {
this.shape = type;
@@ -9,33 +8,13 @@ export default class PolygonLayer extends Layer {
draw() {
this.init();
this.type = 'polygon';
- this._buffer = new PolygonBuffer({
- shape: this.shape,
- layerData: this.layerData
- });
- this.add(this._getLayerRender());
+ const animateOptions = this.get('animateOptions');
+ if (animateOptions.enable) {
+ this.shape = 'animate';
+ }
+ this.add(getRender(this.type, this.shape)(this.layerData, this));
}
update() {
this.updateFilter(this.layerMesh);
}
- _getLayerRender() {
- const animateOptions = this.get('animateOptions');
- const { attributes } = this._buffer;
- const style = this.get('styleOptions');
- const activeOption = this.get('activedOptions');
- const config = {
- ...style,
- activeColor: activeOption.fill
- };
- if (this.shape === 'line') {
- return drawPolygon.DrawLine(attributes, style);
- } else if (animateOptions.enable) {
- const { near, far } = this.map.getCameraState();
- this.scene.startAnimate();
- return drawPolygon.DrawAnimate(attributes, { ...style, near, far });
- }
- return drawPolygon.DrawFill(attributes, config);
-
- }
-
}
diff --git a/src/layer/render/factory.js b/src/layer/render/factory.js
new file mode 100644
index 0000000000..9f6d53b333
--- /dev/null
+++ b/src/layer/render/factory.js
@@ -0,0 +1,12 @@
+export const Render_MAP = {};
+export const getRender = (layerType, shapeType) => {
+ return Render_MAP[layerType.toLowerCase()] && Render_MAP[layerType.toLowerCase()][shapeType.toLowerCase()];
+};
+export const registerRender = (layerType, shapeType, render) => {
+ if (getRender(layerType, shapeType)) {
+ throw new Error(`Render shapeType '${shapeType}' existed.`);
+ }
+ // 存储到 map 中
+ if (!Render_MAP[layerType.toLowerCase()]) Render_MAP[layerType.toLowerCase()] = {};
+ Render_MAP[layerType.toLowerCase()][shapeType.toLowerCase()] = render;
+};
diff --git a/src/layer/render/heatmap/gird.js b/src/layer/render/heatmap/gird.js
index aa83cedc92..04b31b40bf 100644
--- a/src/layer/render/heatmap/gird.js
+++ b/src/layer/render/heatmap/gird.js
@@ -1,7 +1,11 @@
import * as THREE from '../../../core/three';
+import gridBuffer from '../../../geom/buffer/heatmap/grid';
import GridMaterial from '../../../geom/material/grid';
-export default function DrawGrid(attributes, style) {
- const { opacity, xOffset, yOffset, coverage, activeColor } = style;
+export default function DrawGrid(layerdata, layer, source) {
+ const { opacity, coverage } = layer.get('styleOptions');
+ const activeOption = layer.get('activedOptions');
+ const { xOffset, yOffset } = source.data;
+ const attributes = new gridBuffer(layerdata);
const geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('miter', new THREE.Float32BufferAttribute(attributes.miter, 2));
@@ -12,7 +16,7 @@ export default function DrawGrid(attributes, style) {
u_xOffset: xOffset,
u_yOffset: yOffset,
u_coverage: coverage,
- u_activeColor: activeColor
+ u_activeColor: activeOption.fill
}, {
SHAPE: false
});
diff --git a/src/layer/render/heatmap/heatmap.js b/src/layer/render/heatmap/heatmap.js
index 887f41f954..5ce24e1f68 100644
--- a/src/layer/render/heatmap/heatmap.js
+++ b/src/layer/render/heatmap/heatmap.js
@@ -1,24 +1,23 @@
import HeatmapBuffer from '../../../geom/buffer/heatmap/heatmap';
import { createColorRamp } from '../../../geom/buffer/heatmap/heatmap';
-import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../../../geom/material/heatmapMateial';
+import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../../../geom/material/heatmapMaterial';
// import Renderpass from '../../../core/engine/renderpass.bak';
import RenderPass from '../../../core/engine/render-pass';
import ShaderPass from '../../../core/engine/shader-pass';
import EffectComposer from '../../../core/engine/effect-composer';
import * as THREE from '../../../core/three';
-export function drawHeatmap(layer) {
+export default function DrawHeatmap(layerdata, layer) {
const colors = layer.get('styleOptions').rampColors;
layer.rampColors = createColorRamp(colors);
- const heatmap = new heatmapPass(layer);
+ const heatmap = new heatmapPass(layerdata, layer);
const copy = new copyPass(layer);
copy.renderToScreen = true;
const composer = new EffectComposer(layer.scene._engine._renderer, layer.scene._container);
composer.addPass(heatmap);
composer.addPass(copy);
- layer.add(composer);
layer.scene._engine.update();
layer._updateStyle = style => {
if (style.rampColors) {
@@ -31,13 +30,14 @@ export function drawHeatmap(layer) {
heatmap.scene.children[0].material.updateUninform(newOption);
copy.scene.children[0].material.updateUninform(newOption);
};
+ return composer;
}
-function heatmapPass(layer) {
+function heatmapPass(layerdata, layer) {
const scene = new THREE.Scene();
const style = layer.get('styleOptions');
- const data = layer.layerData;
+ const data = layerdata;
const camera = layer.scene._engine._camera;
// get attributes data
const buffer = new HeatmapBuffer({
diff --git a/src/layer/render/heatmap/hexagon.js b/src/layer/render/heatmap/hexagon.js
index 639deaa645..8c2c42ee14 100644
--- a/src/layer/render/heatmap/hexagon.js
+++ b/src/layer/render/heatmap/hexagon.js
@@ -1,7 +1,12 @@
import * as THREE from '../../../core/three';
+import hexagonBuffer from '../../../geom/buffer/heatmap/hexagon';
import GridMaterial from '../../../geom/material/hexagon';
-export default function DrawHexagon(attributes, style) {
- const { opacity, radius, angle, coverage, activeColor } = style;
+export default function DrawHexagon(layerdata, layer, source) {
+ const style = layer.get('styleOptions');
+ const { fill } = layer.get('activedOptions');
+ const { radius } = source.data;
+ const attributes = new hexagonBuffer(layerdata);
+ const { opacity, angle, coverage } = style;
const geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('miter', new THREE.Float32BufferAttribute(attributes.miter, 2));
@@ -12,7 +17,7 @@ export default function DrawHexagon(attributes, style) {
u_radius: radius,
u_angle: angle / 180 * Math.PI,
u_coverage: coverage,
- u_activeColor: activeColor
+ u_activeColor: fill
}, {
SHAPE: false
});
diff --git a/src/layer/render/index.js b/src/layer/render/index.js
new file mode 100644
index 0000000000..16a2d48273
--- /dev/null
+++ b/src/layer/render/index.js
@@ -0,0 +1,48 @@
+import { registerRender, getRender } from './factory';
+// polygon
+import DrawFill from './polygon/drawFill';
+import DrawLine from './polygon/drawLine';
+import DrawAnimate from './polygon/drawAnimate';
+
+registerRender('polygon', 'fill', DrawFill);
+registerRender('polygon', 'extrude', DrawFill);
+registerRender('polygon', 'line', DrawLine);
+registerRender('polygon', 'animate', DrawAnimate);
+
+// line
+import DrawMeshLine from './line/drawMeshLine';
+import DrawArcLine from './line/drawArc';
+
+registerRender('line', 'line', DrawMeshLine);
+registerRender('line', 'arc', DrawArcLine);
+
+// point
+import DrawPointFill from './point/drawFill';
+import DrawPointImage from './point/drawImage';
+import DrawPointNormal from './point/drawNormal';
+import DrawPointStroke from './point/drawStroke';
+import DrawPointText from './point/drawText';
+
+registerRender('point', 'fill', DrawPointFill);
+registerRender('point', 'image', DrawPointImage);
+registerRender('point', 'normal', DrawPointNormal);
+registerRender('point', 'stroke', DrawPointStroke);
+registerRender('point', 'text', DrawPointText);
+
+// heatmap
+
+import DrawGrid from './heatmap/gird';
+import DrawHeatmap from './heatmap/heatmap';
+import DrawHexagon from './heatmap/hexagon';
+
+registerRender('heatmap', 'grid', DrawGrid);
+registerRender('heatmap', 'heatmap', DrawHeatmap);
+registerRender('heatmap', 'hexagon', DrawHexagon);
+
+// image
+
+import DrawImage from './image/drawImage';
+
+registerRender('image', 'image', DrawImage);
+
+export { getRender };
diff --git a/src/layer/render/line/drawArc.js b/src/layer/render/line/drawArc.js
index 5324e0c821..a043a0b2a6 100644
--- a/src/layer/render/line/drawArc.js
+++ b/src/layer/render/line/drawArc.js
@@ -1,8 +1,14 @@
import * as THREE from '../../../core/three';
+import { LineBuffer } from '../../../geom/buffer/index';
import { ArcLineMaterial } from '../../../geom/material/lineMaterial';
-export default function DrawArcLine(attributes, cfg, layer) {
- const { style, activeOption } = cfg;
- const { opacity, zoom } = style;
+export default function DrawArcLine(layerdata, layer) {
+ const style = this.get('styleOptions');
+ const activeOption = layer.get('activedOptions');
+ const { attributes } = new LineBuffer({
+ layerdata,
+ shapeType: 'arc',
+ style
+ });
const geometry = new THREE.BufferGeometry();
geometry.setIndex(attributes.indexArray);
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
@@ -10,12 +16,12 @@ export default function DrawArcLine(attributes, cfg, layer) {
geometry.addAttribute('a_instance', new THREE.Float32BufferAttribute(attributes.instances, 4));
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
const lineMaterial = new ArcLineMaterial({
- u_opacity: opacity,
- u_zoom: zoom,
+ u_opacity: style.opacity,
+ u_zoom: layer.scene.getZoom(),
activeColor: activeOption.fill
}, {
SHAPE: false
});
const arcMesh = new THREE.Mesh(geometry, lineMaterial);
- layer.add(arcMesh);
+ return arcMesh;
}
diff --git a/src/layer/render/line/drawMeshLine.js b/src/layer/render/line/drawMeshLine.js
index 5709c5ae77..1b955faef7 100644
--- a/src/layer/render/line/drawMeshLine.js
+++ b/src/layer/render/line/drawMeshLine.js
@@ -1,7 +1,16 @@
import * as THREE from '../../../core/three';
+import { LineBuffer } from '../../../geom/buffer/index';
import { MeshLineMaterial } from '../../../geom/material/lineMaterial';
-export default function DrawLine(attributes, cfg, layer) {
- const { style, animateOptions, activeOption, zoom } = cfg;
+export default function DrawLine(layerData, layer) {
+
+ const style = layer.get('styleOptions');
+ const animateOptions = layer.get('animateOptions');
+ const activeOption = layer.get('activedOptions');
+ const { attributes } = new LineBuffer({
+ layerData,
+ shapeType: 'line',
+ style
+ });
const geometry = new THREE.BufferGeometry();
geometry.setIndex(attributes.indexArray);
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
@@ -15,7 +24,7 @@ export default function DrawLine(attributes, cfg, layer) {
const lineMaterial = new MeshLineMaterial({
u_opacity: style.opacity,
- u_zoom: zoom,
+ u_zoom: layer.scene.getZoom(),
u_time: 0,
u_dash_offset: style.dashOffset,
u_dash_ratio: style.dashRatio,
@@ -44,5 +53,5 @@ export default function DrawLine(attributes, cfg, layer) {
});
lineMaterial.setDefinesvalue('ANIMATE', true);
}
- layer.add(lineMesh);
+ return lineMesh;
}
diff --git a/src/layer/render/point/drawFill.js b/src/layer/render/point/drawFill.js
index 008d47dd35..a6ec26dc49 100644
--- a/src/layer/render/point/drawFill.js
+++ b/src/layer/render/point/drawFill.js
@@ -6,9 +6,13 @@
* @desc [description] 绘制点图层的面状填充,圆,三角形,六边形
*/
import * as THREE from '../../../core/three';
+import * as PointBuffer from '../../../geom/buffer/point/index';
+import DrawStroke from './drawStroke';
import PolygonMaterial from '../../../geom/material/polygonMaterial';
-export default function DrawFill(attributes, style) {
- const { opacity, activeColor } = style;
+export default function DrawFill(layerData, layer) {
+ const style = layer.get('styleOptions');
+ const activeOption = layer.get('activedOptions');
+ const attributes = PointBuffer.FillBuffer(layerData, style);
const geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
@@ -28,14 +32,20 @@ export default function DrawFill(attributes, style) {
// instancedGeometry.addAttribute('a_size', new THREE.InstancedBufferAttribute(new Float32Array(attributes.a_size), 3));
const material = new PolygonMaterial({
- u_opacity: opacity,
- u_activeColor: activeColor
+ u_opacity: style.opacity,
+ u_activeColor: activeOption.fill,
+ u_zoom: layer.scene.getZoom()
}, {
SHAPE: true
});
material.setDefinesvalue('SHAPE', true);
material.depthTest = false;
const fillMesh = new THREE.Mesh(geometry, material);
+ if (style.stroke !== 'none') {
+ // 是否绘制边界
+ const meshStroke = DrawStroke(layerData, layer);
+ fillMesh.add(meshStroke);
+ }
// const fillMesh = new THREE.Mesh(instancedGeometry, material);
return fillMesh;
diff --git a/src/layer/render/point/drawImage.js b/src/layer/render/point/drawImage.js
index f6fc926aac..832db247b4 100644
--- a/src/layer/render/point/drawImage.js
+++ b/src/layer/render/point/drawImage.js
@@ -1,9 +1,15 @@
import * as THREE from '../../../core/three';
+import * as PointBuffer from '../../../geom/buffer/point/index';
import PointMaterial from '../../../geom/material/pointMaterial';
-export default function DrawImage(attributes, style) {
+export default function DrawImage(layerData, layer) {
const geometry = new THREE.BufferGeometry();
- const { strokeWidth, stroke, opacity, texture } = style;
+ const style = layer.get('styleOptions');
+ const { strokeWidth, stroke, opacity } = style;
+ const texture = layer.scene.image.texture;
+ const attributes = PointBuffer.ImageBuffer(layerData, {
+ imagePos: layer.scene.image.imagePos
+ });
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
diff --git a/src/layer/render/point/drawNormal.js b/src/layer/render/point/drawNormal.js
index 077c80d6f1..c851e85341 100644
--- a/src/layer/render/point/drawNormal.js
+++ b/src/layer/render/point/drawNormal.js
@@ -2,17 +2,21 @@
* 原生点绘制
*/
import * as THREE from '../../../core/three';
+import * as PointBuffer from '../../../geom/buffer/point/index';
import PointMaterial from '../../../geom/material/pointMaterial';
-export default function DrawNormal(attributes, style) {
+export default function DrawNormal(layerData, layer) {
const geometry = new THREE.BufferGeometry();
- const { opacity, activeColor } = style;
+ const style = layer.get('styleOptions');
+ const activeOption = layer.get('activedOptions');
+ const { opacity } = style;
+ const attributes = PointBuffer.NormalBuffer(layerData, style);
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
const material = new PointMaterial({
u_opacity: opacity,
- u_activeColor: activeColor
+ u_activeColor: activeOption.fill
}, {
SHAPE: false,
TEXCOORD_0: false
diff --git a/src/layer/render/point/drawStroke.js b/src/layer/render/point/drawStroke.js
index 8b5c780e48..da4ce645aa 100644
--- a/src/layer/render/point/drawStroke.js
+++ b/src/layer/render/point/drawStroke.js
@@ -7,9 +7,13 @@
*/
import PointLineMaterial from '../../../geom/material/pointLineMaterial';
+import * as PointBuffer from '../../../geom/buffer/point/index';
import * as THREE from '../../../core/three';
-export default function DrawStroke(attributes, style) {
+export default function DrawStroke(layerData, layer) {
+ const style = layer.get('styleOptions');
+ const activeOption = layer.get('activedOptions');
const { strokeWidth, stroke, strokeOpacity } = style;
+ const attributes = PointBuffer.StrokeBuffer(layerData, style);
const geometry = new THREE.BufferGeometry();
geometry.setIndex(attributes.indexArray);
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
@@ -22,7 +26,8 @@ export default function DrawStroke(attributes, style) {
const material = new PointLineMaterial({
u_strokeOpacity: strokeOpacity,
u_stroke: stroke,
- u_strokeWidth: strokeWidth
+ u_strokeWidth: strokeWidth,
+ u_activeColor: activeOption.fill
});
const strokeMesh = new THREE.Mesh(geometry, material);
return strokeMesh;
diff --git a/src/layer/render/point/drawText.js b/src/layer/render/point/drawText.js
index 32fa9a28d5..95d1f8949d 100644
--- a/src/layer/render/point/drawText.js
+++ b/src/layer/render/point/drawText.js
@@ -1,7 +1,15 @@
import * as THREE from '../../../core/three';
import TextMaterial from '../../../geom/material/textMaterial';
+import TextBuffer from '../../../geom/buffer/point/text';
-export default function DrawText(attributes, style) {
+export default function DrawText(layerData, layer) {
+ const style = layer.get('styleOptions');
+ const activeOption = layer.get('activedOptions');
+ const { width, height } = layer.scene.getSize();
+ const attributes = new TextBuffer(
+ layerData,
+ layer.scene.fontAtlasManager
+ );
const geometry = new THREE.BufferGeometry();
geometry.addAttribute(
'position',
@@ -27,9 +35,9 @@ export default function DrawText(attributes, style) {
'pickingId',
new THREE.Float32BufferAttribute(attributes.pickingIds, 1)
);
- const { strokeWidth, width, stroke, height, opacity, activeColor } = style;
+ const { strokeWidth, stroke, opacity } = style;
const material = new TextMaterial({
- name: this.layerId,
+ name: layer.layerId,
u_texture: attributes.texture,
u_strokeWidth: strokeWidth,
u_stroke: stroke,
@@ -41,7 +49,7 @@ export default function DrawText(attributes, style) {
u_buffer: 0.75,
u_opacity: opacity,
u_glSize: [ width, height ],
- u_activeColor: activeColor
+ u_activeColor: activeOption.fill
});
const mesh = new THREE.Mesh(geometry, material);
return mesh;
diff --git a/src/layer/render/polygon/drawAnimate.js b/src/layer/render/polygon/drawAnimate.js
index 1e7bb408fa..b8eed2ab34 100644
--- a/src/layer/render/polygon/drawAnimate.js
+++ b/src/layer/render/polygon/drawAnimate.js
@@ -1,7 +1,15 @@
import * as THREE from '../../../core/three';
+import PolygonBuffer from '../../../geom/buffer/polygon';
import PolygonMaterial from '../../../geom/material/polygonMaterial';
-export default function DrawAnimate(attributes, style) {
- const { opacity, baseColor, brightColor, windowColor, near, far } = style;
+export default function DrawAnimate(layerData, layer) {
+ const style = layer.get('styleOptions');
+ const { near, far } = layer.map.getCameraState();
+ layer.scene.startAnimate();
+ const { attributes } = new PolygonBuffer({
+ shape: 'extrude',
+ layerData
+ });
+ const { opacity, baseColor, brightColor, windowColor } = style;
const geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
diff --git a/src/layer/render/polygon/drawFill.js b/src/layer/render/polygon/drawFill.js
index d9981cbdbb..11ae385a2e 100644
--- a/src/layer/render/polygon/drawFill.js
+++ b/src/layer/render/polygon/drawFill.js
@@ -1,20 +1,24 @@
import * as THREE from '../../../core/three';
+import PolygonBuffer from '../../../geom/buffer/polygon';
import PolygonMaterial from '../../../geom/material/polygonMaterial';
-// import TileMaterial from '../../../geom/material/tile/polygon';
-export default function DrawPolygonFill(attributes, style) {
- const { opacity, activeColor } = style;
+export default function DrawPolygonFill(layerData, layer) {
+ const style = layer.get('styleOptions');
+ const activeOption = layer.get('activedOptions');
+ const config = {
+ ...style,
+ activeColor: activeOption.fill
+ };
+ const { opacity, activeColor } = config;
+ const { attributes } = new PolygonBuffer({
+ shape: layer.shape,
+ layerData
+ });
const geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normals, 3));
- // const material = new PolygonMaterial({
- // u_opacity: opacity,
- // u_activeColor: activeColor
- // }, {
- // SHAPE: false
- // });
const material = new PolygonMaterial({
u_opacity: opacity,
u_activeColor: activeColor
diff --git a/src/layer/render/polygon/drawLine.js b/src/layer/render/polygon/drawLine.js
index 8755a4f573..d14d8dc3e6 100644
--- a/src/layer/render/polygon/drawLine.js
+++ b/src/layer/render/polygon/drawLine.js
@@ -1,7 +1,18 @@
import * as THREE from '../../../core/three';
+import PolygonBuffer from '../../../geom/buffer/polygon';
import { LineMaterial } from '../../../geom/material/lineMaterial';
-export default function DrawPolygonLine(attributes, style) {
- const { opacity } = style;
+export default function DrawPolygonLine(layerData, layer) {
+ const style = layer.get('styleOptions');
+ const activeOption = layer.get('activedOptions');
+ const config = {
+ ...style,
+ activeColor: activeOption.fill
+ };
+ const { opacity } = config;
+ const { attributes } = new PolygonBuffer({
+ shape: layer.shape,
+ layerData
+ });
const geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
diff --git a/src/layer/render/polygon/index.js b/src/layer/render/polygon/index.js
index afde7904a6..65a4365702 100644
--- a/src/layer/render/polygon/index.js
+++ b/src/layer/render/polygon/index.js
@@ -1,3 +1,8 @@
+
export { default as DrawAnimate } from './drawAnimate';
export { default as DrawFill } from './drawFill';
export { default as DrawLine } from './drawLine';
+
+export function polygonMesh() {
+
+}
diff --git a/src/layer/tile/VectorTileLayer.js b/src/layer/tile/VectorTileLayer.js
new file mode 100644
index 0000000000..73258a6e40
--- /dev/null
+++ b/src/layer/tile/VectorTileLayer.js
@@ -0,0 +1,7 @@
+import TileLayer from './tileLayer';
+import VectorTile from './vectorTile';
+export default class VectorTileLayer extends TileLayer {
+ _createTile(key, layer) {
+ return new VectorTile(key, this.url, layer);
+ }
+}
diff --git a/src/layer/tile/imageTile.js b/src/layer/tile/imageTile.js
index d30e336385..1a16b19c7d 100644
--- a/src/layer/tile/imageTile.js
+++ b/src/layer/tile/imageTile.js
@@ -13,30 +13,34 @@ export default class ImageTile extends Tile {
}, 0);
}
_requestTile() {
- const urlParams = {
- x: this._tile[0],
- y: this._tile[1],
- z: this._tile[2]
- };
+ const image = this._createDebugMesh();
+ this._createMesh(image);
+ this.emit('tileLoaded');
+ // return;
+ // const urlParams = {
+ // x: this._tile[0],
+ // y: this._tile[1],
+ // z: this._tile[2]
+ // };
- const url = this._getTileURL(urlParams);
- const image = document.createElement('img');
+ // const url = this._getTileURL(urlParams);
+ // const image = document.createElement('img');
- image.addEventListener('load', () => {
+ // image.addEventListener('load', () => {
+ // this._isLoaded = true;
+ // this._createMesh(image);
+ // this._ready = true;
+ // }, false);
- this._createMesh(image);
- this._ready = true;
- }, false);
+ // // image.addEventListener('progress', event => {}, false);
+ // // image.addEventListener('error', event => {}, false);
- // image.addEventListener('progress', event => {}, false);
- // image.addEventListener('error', event => {}, false);
+ // image.crossOrigin = '';
- image.crossOrigin = '';
+ // // Load image
+ // image.src = url;
- // Load image
- image.src = url;
-
- this._image = image;
+ // this._image = image;
}
_getBufferData(images) {
const NW = this._tileBounds.getTopLeft();
@@ -58,8 +62,20 @@ export default class ImageTile extends Tile {
buffer.attributes.texture = buffer.texture;
const style = this.layer.get('styleOptions');
const mesh = DrawImage(buffer.attributes, style);
- this.Object3D.add(mesh);
- return this.Object3D;
+ this._object3D.add(mesh);
+ return this._object3D;
+ }
+ _createDebugMesh() {
+ const canvas = document.createElement('canvas');
+ const context = canvas.getContext('2d');
+ canvas.width = 256;
+ canvas.height = 256;
+ context.font = 'Bold 20px Helvetica Neue, Verdana, Arial';
+ context.fillStyle = '#ff0000';
+ context.fillText(this._tile.join('/'), 20, 20);
+ context.rect(0, 0, 256, 256);
+ context.stroke();
+ return canvas;
}
_abortRequest() {
if (!this._image) {
@@ -68,7 +84,9 @@ export default class ImageTile extends Tile {
this._image.src = '';
}
-
+ getSelectFeature() {
+ return {};
+ }
destroy() {
// Cancel any pending requests
this._abortRequest();
diff --git a/src/layer/tile/tile.js b/src/layer/tile/tile.js
index 261800150c..dc504e13b7 100644
--- a/src/layer/tile/tile.js
+++ b/src/layer/tile/tile.js
@@ -1,10 +1,28 @@
import * as THREE from '../../core/three';
+import Base from '../../core/base';
+import { destoryObject } from '../../util/object3d-util';
+import Controller from '../../core/controller/index';
+import Util from '../../util';
+import Global from '../../global';
+import Attr from '../../attr/index';
import { toLngLatBounds, toBounds } from '@antv/geo-coord';
const r2d = 180 / Math.PI;
const tileURLRegex = /\{([zxy])\}/g;
-
-export default class Tile {
+function parseFields(field) {
+ if (Util.isArray(field)) {
+ return field;
+ }
+ if (Util.isString(field)) {
+ return field.split('*');
+ }
+ return [ field ];
+}
+export default class Tile extends Base {
constructor(key, url, layer) {
+ super({
+ scales: {},
+ attrs: {}
+ });
this.layer = layer;
this._tile = key.split('_').map(v => v * 1);
this._path = url;
@@ -15,10 +33,134 @@ export default class Tile {
this._center = this._tileBounds.getCenter();
this._centerLnglat = this._tileLnglatBounds.getCenter();
- this.Object3D = new THREE.Object3D();
- this.requestTileAsync();
+ this._object3D = new THREE.Object3D();
+ this._object3D.onBeforeRender = () => {
+ };
+ this._isLoaded = false;
+ this.requestTileAsync(data => this._init(data));
+ }
+ _init(data) {
+ this._initControllers();
+ this._creatSource(data);
+ this._initTileAttrs();
+ this._mapping();
+ this._createMesh();
+ }
+ _initControllers() {
+ const scales = this.layer.get('scaleOptions');
+ const scaleController = new Controller.Scale({
+ defs: {
+ ...scales
+ }
+ });
+ this.set('scaleController', scaleController);
+ }
+ _createScale(field) {
+ // TODO scale更新
+ const scales = this.get('scales');
+ let scale = scales[field];
+ if (!scale) {
+ scale = this.createScale(field);
+ scales[field] = scale;
+ }
+ return scale;
+ }
+ createScale(field) {
+ const data = this.source.data.dataArray;
+ const scales = this.get('scales');
+ let scale = scales[field];
+ const scaleController = this.get('scaleController');
+ if (!scale) {
+ scale = scaleController.createScale(field, data);
+ scales[field] = scale;
+ }
+ return scale;
+ }
+ // 获取属性映射的值
+ _getAttrValues(attr, record) {
+ const scales = attr.scales;
+ const params = [];
+ for (let i = 0; i < scales.length; i++) {
+ const scale = scales[i];
+ const field = scale.field;
+ if (scale.type === 'identity') {
+ params.push(scale.value);
+ } else {
+ params.push(record[field]);
+ }
+ }
+ const indexZoom = params.indexOf('zoom');
+ indexZoom !== -1 ? params[indexZoom] = attr.zoom : null;
+ const values = attr.mapping(...params);
+ return values;
+ }
+ _mapping() {
+ const attrs = this.get('attrs');
+ const mappedData = [];
+ // const data = this.layerSource.propertiesData;
+ const data = this.source.data.dataArray;
+ for (let i = 0; i < data.length; i++) {
+ const record = data[i];
+ const newRecord = {};
+ newRecord.id = data[i]._id;
+ for (const k in attrs) {
+ if (attrs.hasOwnProperty(k)) {
+ const attr = attrs[k];
+ const names = attr.names;
+ const values = this._getAttrValues(attr, record);
+ if (names.length > 1) { // position 之类的生成多个字段的属性
+ for (let j = 0; j < values.length; j++) {
+ const val = values[j];
+ const name = names[j];
+ newRecord[name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
+ }
+ } else {
+ newRecord[names[0]] = values.length === 1 ? values[0] : values;
+ }
+ }
+ }
+ newRecord.coordinates = record.coordinates;
+ mappedData.push(newRecord);
+ }
+ // 通过透明度过滤数据
+ if (attrs.hasOwnProperty('filter')) {
+ mappedData.forEach(item => {
+ item.filter === false && (item.color[3] = 0);
+ });
+ }
+ this.layerData = mappedData;
+ }
+ _initTileAttrs() {
+ const attrOptions = this.layer.get('attrOptions');
+ for (const type in attrOptions) {
+ if (attrOptions.hasOwnProperty(type)) {
+ this._updateTileAttr(type);
+ }
+ }
+ }
+ _updateTileAttr(type) {
+ const self = this;
+ const attrs = this.get('attrs');
+ const attrOptions = this.layer.get('attrOptions');
+ const option = attrOptions[type];
+ option.neadUpdate = true;
+ const className = Util.upperFirst(type);
+ const fields = parseFields(option.field);
+ const scales = [];
+ for (let i = 0; i < fields.length; i++) {
+ const field = fields[i];
+ const scale = self._createScale(field);
+
+ if (type === 'color' && Util.isNil(option.values)) { // 设置 color 的默认色值
+ option.values = Global.colors;
+ }
+ scales.push(scale);
+ }
+ option.scales = scales;
+ const attr = new Attr[className](option);
+ attrs[type] = attr;
}
_createMesh() {}
_getTileURL(urlParams) {
@@ -34,12 +176,12 @@ export default class Tile {
}
// 经纬度范围转瓦片范围
_tileBounds(lnglatBound) {
- const ne = this.layer.scene.project([ lnglatBound.getNorthWest().lng, lnglatBound.getNorthEast().lat ]);
- const sw = this.layer.scene.project([ lnglatBound.getSouthEast().lng, lnglatBound.getSouthWest().lat ]);
+ const ne = this.layer.scene.project([ lnglatBound.getNorthEast().lng, lnglatBound.getNorthEast().lat ]);
+ const sw = this.layer.scene.project([ lnglatBound.getSouthWest().lng, lnglatBound.getSouthWest().lat ]);
return toBounds(sw, ne);
}
getMesh() {
- return this.Object3D;
+ return this._object3D;
}
@@ -60,31 +202,30 @@ export default class Tile {
const n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
}
- destroy() {
- if (this._object3D && this._object3D.children) {
- let child;
- for (let i = 0; i < this._object3D.children.length; i++) {
- child = this._object3D.children[i];
- if (!child) {
- continue;
- }
- this.remove(child);
- if (child.geometry) {
- // child.geometry.dispose();
- child.geometry = null;
- }
- if (child.material) {
- if (child.material.map) {
- child.material.map.dispose();
- child.material.map = null;
- }
+ _retainParent(x, y, z, minZoom = 5) {
+ const x2 = Math.floor(x / 2),
+ y2 = Math.floor(y / 2),
+ z2 = z - 1,
+ coords2 = [ +x2, +y2, +z2 ];
+ const tile = this._tiles[coords2]; // 计算保留
+ if (tile && tile.active) {
+ tile.retain = true;
+ return true;
- child.material.dispose();
- child.material = null;
- }
- child = null;
- }
+ } else if (tile && tile.loaded) {
+ tile.retain = true;
+ }
+
+ if (z2 > minZoom) {
+ return this._retainParent(x2, y2, z2, minZoom);
}
- this._object3D = null;
+
+ return false;
+ }
+ _preRender() {
+ }
+ destroy() {
+ super.destroy();
+ destoryObject(this._object3D);
}
}
diff --git a/src/layer/tile/tileLayer.js b/src/layer/tile/tileLayer.js
index a3bc44afc9..6cdcd01bc4 100644
--- a/src/layer/tile/tileLayer.js
+++ b/src/layer/tile/tileLayer.js
@@ -1,126 +1,325 @@
import Layer from '../../core/layer';
+import source from '../../core/source';
import * as THREE from '../../core/three';
+import Global from '../../global';
+const { pointShape } = Global;
import TileCache from './tileCache';
-import { throttle } from '@antv/util';
-import { toLngLat } from '@antv/geo-coord';
+import pickingFragmentShader from '../../core/engine/picking/picking_frag.glsl';
+import { throttle, deepMix } from '@antv/util';
+import { toLngLat, Bounds, Point } from '@antv/geo-coord';
+import { wrapNum } from '@antv/geo-coord/lib/util/index';
import { epsg3857 } from '@antv/geo-coord/lib/geo/crs/crs-epsg3857';
export default class TileLayer extends Layer {
constructor(scene, cfg) {
- super(scene, cfg);
- this._tileCache = new TileCache(50, this._destroyTile);
+ super(scene, {
+ ...cfg,
+ keepBuffer: 2
+ });
+ this._tileCache = new TileCache(100, this._destroyTile);
this._crs = epsg3857;
this._tiles = new THREE.Object3D();
+ this._pickTiles = new THREE.Object3D();
+ this._pickTiles.name = this.layerId;
+ this.scene._engine._picking.add(this._pickTiles);
+ this._tiles.frustumCulled = false;
this._tileKeys = [];
- this.tileList = [];
-
-
+ this.tileList = {};
}
- source(url) {
+ shape(field, values) {
+ const layerType = this.get('layerType');
+ if (layerType === 'point') {
+ return super.shape(field, values);
+ }
+ this.shape = field;
+ return this;
+ }
+ source(url, cfg = {}) {
this.url = url;
+ this.sourceCfg = cfg;
+ this.sourceCfg.mapType = this.scene.mapType;
return this;
}
+ tileSource(data, cfg) {
+ if (data instanceof source) {
+ return data;
+ }
+ const tileSourceCfg = {
+ data,
+ zoom: this.scene.getZoom()
+ };
+ deepMix(tileSourceCfg, this.sourceCfg, cfg);
+ return new source(tileSourceCfg);
+ }
render() {
+ // this._initControllers();
this._initMapEvent();
+ // this._initAttrs();
+ this._initInteraction();
this.draw();
+ return this;
}
draw() {
this._object3D.add(this._tiles);
this._calculateLOD();
}
+
drawTile() {
}
+
zoomchange(ev) {
super.zoomchange(ev);
throttle(this._calculateLOD, 200);
this._calculateLOD();
}
+
dragend(ev) {
super.dragend(ev);
this._calculateLOD();
}
_calculateLOD() {
- const viewPort = this.scene.getBounds().toBounds();
- const SE = viewPort.getSouthEast();
- const NW = viewPort.getNorthWest();
+ /**
+ * 加载完成 active
+ * 需要显示 current
+ * 是否保留 retain
+ */
+ this.updateTileList = [];
const zoom = Math.round(this.scene.getZoom()) - 1;
- const tileCount = Math.pow(2, zoom);
const center = this.scene.getCenter();
- const NWPoint = this._crs.lngLatToPoint(toLngLat(NW.lng, NW.lat), zoom);
- const SEPoint = this._crs.lngLatToPoint(toLngLat(SE.lng, SE.lat), zoom);
const centerPoint = this._crs.lngLatToPoint(toLngLat(center.lng, center.lat), zoom);
const centerXY = centerPoint.divideBy(256).round();
- const minXY = NWPoint.divideBy(256).round();
- const maxXY = SEPoint.divideBy(256).round();
- // console.log(NW.lng, NW.lat, SE.lng, SE.lat, NWPonint, SEPonint);
- let updateTileList = [];
- this.tileList = [];
- const halfx = Math.floor((maxXY.x - minXY.x) / 2) + 1;
- const halfy = Math.floor((maxXY.y - minXY.y) / 2) + 1;
- if (!(centerPoint.x > NWPoint.x && centerPoint.x < SEPoint.x)) { // 地图循环的问题
- for (let i = 0; i < minXY.x; i++) {
- for (let j = Math.min(0, minXY.y - halfy); j < Math.max(maxXY.y + halfy, tileCount); j++) {
- this._updateTileList(updateTileList, i, j, zoom);
+ const pixelBounds = this._getPixelBounds();
+ const tileRange = this._pxBoundsToTileRange(pixelBounds);
+ const margin = this.get('keepBuffer');
+ this.noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([ margin, -margin ]),
+ tileRange.getTopRight().add([ margin, -margin ]));
+ if (!(isFinite(tileRange.min.x) &&
+ isFinite(tileRange.min.y) &&
+ isFinite(tileRange.max.x) &&
+ isFinite(tileRange.max.y))) { throw new Error('Attempted to load an infinite number of tiles'); }
+ for (let j = tileRange.min.y; j <= tileRange.max.y; j++) {
+ for (let i = tileRange.min.x; i <= tileRange.max.x; i++) {
+ const coords = [ i, j, zoom ];
+ const tile = this.tileList[coords.join('_')];
+ if (tile) {
+ tile.current = true;
+ } else {
+ this.tileList[coords.join('_')] = {
+ current: true,
+ coords
+ };
+ this.updateTileList.push(coords);
}
}
- for (let i = maxXY.x; i < tileCount; i++) {
- for (let j = Math.min(0, minXY.y - halfy); j < Math.max(maxXY.y + halfy, tileCount); j++) {
- this._updateTileList(updateTileList, i, j, zoom);
- }
- }
- }
- for (let i = Math.max(0, minXY.x - halfx); i < Math.min(maxXY.x + halfx, tileCount); i++) {
- for (let j = Math.max(0, minXY.y - halfy); j < Math.min(maxXY.y + halfy, tileCount); j++) {
- this._updateTileList(updateTileList, i, j, zoom);
- }
}
- // 过滤掉已经存在的
- // tileList = tileList.filter(tile => {
- // })
- updateTileList = updateTileList.sort((a, b) => {
- const tile1 = a.split('_');
- const tile2 = b.split('_');
+ this.updateTileList.sort((a, b) => {
+ const tile1 = a;
+ const tile2 = b;
const d1 = Math.pow((tile1[0] * 1 - centerXY.x), 2) + Math.pow((tile1[1] * 1 - centerXY.y), 2);
const d2 = Math.pow((tile2[0] * 1 - centerXY.x), 2) + Math.pow((tile2[1] * 1 - centerXY.y), 2);
return d1 - d2;
});
- updateTileList.forEach(key => {
- this._requestTile(key, this);
+ this._pruneTiles();
+ // 更新瓦片数据
+ this.updateTileList.forEach(coords => {
+ const key = coords.join('_');
+ if (this.tileList[key].current) {
+ this._requestTile(key, this);
+ }
});
- this._removeOutTiles();
}
- _updateTileList(updateTileList, x, y, z) {
+ _getShape(layerData) {
+ let shape = null;
+ if (!layerData[0].hasOwnProperty('shape')) {
+ return 'normal';
+ }
+ for (let i = 0; i < layerData.length; i++) {
+ shape = layerData[i].shape;
+ if (shape !== undefined) {
+ break;
+ }
+ }
+ if (
+ pointShape['2d'].indexOf(shape) !== -1 ||
+ pointShape['3d'].indexOf(shape) !== -1
+ ) {
+ return 'fill';
+ } else if (this.scene.image.imagesIds.indexOf(shape) !== -1) {
+ return 'image';
+ }
+ return 'text';
+ }
+ _updateTileList(x, y, z) {
const key = [ x, y, z ].join('_');
- this.tileList.push(key);
- if (this._tileKeys.indexOf(key) === -1) {
- updateTileList.push(key);
+ const tile = this.tileList[key];
+ if (tile) {
+ tile.current = true;
+ } else {
+ this.tileList[key] = {
+ current: true,
+ active: false,
+ coords: key.split('_')
+ };
+ this.updateTileList.push(key);
}
}
_requestTile(key, layer) {
+ const t = this.tileList[key];
+ if (!t) {
+ return;
+ }
let tile = this._tileCache.getTile(key);
if (!tile) {
tile = this._createTile(key, layer);
- const mesh = tile.getMesh();
- mesh.name = key;
- this._tileCache.setTile(tile, key);
+ tile.on('tileLoaded', () => {
+ t.active = true;
+ const mesh = tile.getMesh();
+ mesh.name = key;
+ this._tileCache.setTile(tile, key);
+ this._tileKeys.push(key);
+ if (mesh.type === 'composer') {
+ this.scene._engine.composerLayers.push(mesh);
+ this.scene._engine.update();
+ this._pruneTiles();
+ return;
+ }
+ if (mesh.children.length !== 0) {
+ this._tiles.add(tile.getMesh());
+ this._addPickTile(tile.getMesh());
+ }
+ this.scene._engine.update();
+ this._pruneTiles();
+ });
+ } else {
+ if (tile.getMesh().type === 'composer') {
+ this.scene._engine.composerLayers.push(tile.getMesh());
+ this.scene._engine.update();
+ this._pruneTiles();
+ return;
+ }
+ this._tiles.add(tile.getMesh());
+ t.active = true;
+ this._addPickTile(tile.getMesh());
this._tileKeys.push(key);
- // this.scene._engine.update();
+ this.scene._engine.update();
+ this._pruneTiles();
+ }
+ }
+ _addPickTile(meshobj) {
+ const mesh = meshobj.children[0];
+ const pickmaterial = mesh.material.clone();
+ pickmaterial.fragmentShader = pickingFragmentShader;
+ const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial);
+ pickingMesh.name = this.layerId;
+ pickingMesh.onBeforeRender = () => {
+ const zoom = this.scene.getZoom();
+ pickingMesh.material.setUniformsValue('u_zoom', zoom);
+ };
+ this._pickTiles.add(pickingMesh);
+
+ }
+ // 根据距离优先级查找
+ getSelectFeature(id, lnglat) {
+ const zoom = Math.round(this.scene.getZoom()) - 1;
+ const tilePoint = this._crs.lngLatToPoint(toLngLat(lnglat.lng, lnglat.lat), zoom);
+ const tileXY = tilePoint.divideBy(256).round();
+ const key = [ tileXY.x, tileXY.y, zoom ].join('_');
+ const tile = this._tileCache.getTile(key);
+ const feature = tile ? tile.getSelectFeature(id) : null;
+ return { feature };
+ }
+ _pruneTiles() {
+ let tile;
+ const zoom = Math.round(this.scene.getZoom()) - 1;
+ for (const key in this.tileList) {
+ const c = this.tileList[key].coords;
+ if (c[2] !== zoom || !this.noPruneRange.contains(new Point(c[0], c[1]))) {
+ this.tileList[key].current = false;
+ }
+ }
+
+ for (const key in this.tileList) {
+ tile = this.tileList[key];
+ tile.retain = tile.current;
+ }
+ for (const key in this.tileList) {
+ tile = this.tileList[key];
+ if (tile.current && !tile.active) {
+ const [ x, y, z ] = key.split('_').map(v => v * 1);
+ if (!this._retainParent(x, y, z, z - 5)) {
+ this._retainChildren(x, y, z, z + 2);
+ }
+ }
+
+ }
+ this._removeOutTiles();
+ }
+ _retainParent(x, y, z, minZoom) {
+ const x2 = Math.floor(x / 2);
+ const y2 = Math.floor(y / 2);
+ const z2 = z - 1;
+ const tile = this.tileList[[ x2, y2, z2 ].join('_')];
+ if (tile && tile.active) {
+ tile.retain = true;
+ return true;
+ } else if (tile && tile.loaded) {
+ tile.retain = true;
+ }
+ if (z2 > minZoom) {
+ return this._retainParent(x2, y2, z2, minZoom);
+ }
+
+ return false;
+
+ }
+ _retainChildren(x, y, z, maxZoom) {
+ for (let i = 2 * x; i < 2 * x + 2; i++) {
+ for (let j = 2 * y; j < 2 * y + 2; j++) {
+ const key = [ i, j, z + 1 ].join('_');
+ const tile = this.tileList[key];
+ if (tile && tile.active) {
+ tile.retain = true;
+ continue;
+ } else if (tile && tile.loaded) {
+ tile.retain = true;
+ }
+
+ if (z + 1 < maxZoom) {
+ this._retainChildren(i, j, z + 1, maxZoom);
+ }
+ }
}
- this._tiles.add(tile.getMesh());
- this._tileKeys.push(key);
}
// 移除视野外的tile
_removeOutTiles() {
- for (let i = this._tiles.children.length - 1; i >= 0; i--) {
- const tile = this._tiles.children[i];
- const key = tile.name;
- if (this.tileList.indexOf(key) === -1) {
- this._tiles.remove(tile);
+ for (const key in this.tileList) {
+ if (!this.tileList[key].retain) {
+ const tileObj = this._tileCache.getTile(key);
+ if (tileObj) {
+ tileObj._abortRequest();
+ this._tiles.remove(tileObj.getMesh());
+ }
+ if (tileObj && tileObj.getMesh().type === 'composer') {
+ this.scene._engine.composerLayers = this.scene._engine.composerLayers.filter(obj => {
+ return obj.name !== tileObj.getMesh().name;
+ });
+ }
+ delete this.tileList[key];
}
- this._tileKeys = [].concat(this.tileList);
}
+ if (this._tiles.children.length > Object.keys(this.tileList).length) {
+ this._tiles.children.forEach(tile => {
+ const key = tile.name;
+ if (!this.tileList[key]) {
+ this._tiles.remove(tile);
+ }
+ });
+ } // 移除 空的geom
+ this.scene._engine.update();
}
+
+
_removeTiles() {
if (!this._tiles || !this._tiles.children) {
return;
@@ -130,9 +329,51 @@ export default class TileLayer extends Layer {
this._tiles.remove(this._tiles.children[i]);
}
}
+ _getPixelBounds() {
+ const viewPort = this.scene.getBounds().toBounds();
+ const NE = viewPort.getNorthEast();
+ const SW = viewPort.getSouthWest();
+ const zoom = Math.round(this.scene.getZoom()) - 1;
+ const center = this.scene.getCenter();
+ const NEPoint = this._crs.lngLatToPoint(toLngLat(NE.lng, NE.lat), zoom);
+ const SWPoint = this._crs.lngLatToPoint(toLngLat(SW.lng, SW.lat), zoom);
+ const centerPoint = this._crs.lngLatToPoint(toLngLat(center.lng, center.lat), zoom);
+ const topHeight = centerPoint.y - NEPoint.y;
+ const bottomHeight = SWPoint.y - centerPoint.y;
+ // 跨日界线的情况
+ let leftWidth;
+ let rightWidth;
+ if (center.lng - NE.lng > 0 || center.lng - SW.lng < 0) {
+ const width = Math.pow(2, zoom) * 256 / 360 * (180 - NE.lng) + Math.pow(2, zoom) * 256 / 360 * (SW.lng + 180);
+ if (center.lng - NE.lng > 0) { // 日界线在右侧
+ leftWidth = Math.pow(2, zoom) * 256 / 360 * (center.lng - NE.lng);
+ rightWidth = width - leftWidth;
+ } else {
+ rightWidth = Math.pow(2, zoom) * 256 / 360 * (SW.lng - center.lng);
+ leftWidth = width - rightWidth;
+ }
+ } else { // 不跨日界线
+ leftWidth = Math.pow(2, zoom) * 256 / 360 * (center.lng - SW.lng);
+ rightWidth = Math.pow(2, zoom) * 256 / 360 * (NE.lng - center.lng);
+ }
+ const pixelBounds = new Bounds(centerPoint.subtract(leftWidth, topHeight), centerPoint.add(rightWidth, bottomHeight));
+ return pixelBounds;
+ }
+ _pxBoundsToTileRange(pixelBounds) {
+ return new Bounds(
+ pixelBounds.min.divideBy(256).floor(),
+ pixelBounds.max.divideBy(256).ceil().subtract([ 1, 1 ])
+ );
+ }
+ _wrapCoords(coords) {
+ const wrapX = [ 0, Math.pow(2, coords[2]) ];
+ const newX = wrapNum(coords[0], wrapX);
+ return [ newX, coords[1], coords[2] ];
+ }
_destroyTile(tile) {
tile.destroy();
+ tile = null;
}
- desttroy() {
+ destroy() {
}
}
diff --git a/src/layer/tile/vectorTile.js b/src/layer/tile/vectorTile.js
new file mode 100644
index 0000000000..b87fac4998
--- /dev/null
+++ b/src/layer/tile/vectorTile.js
@@ -0,0 +1,132 @@
+import Tile from './tile';
+import { getArrayBuffer } from '../../util/ajax';
+import { destoryObject, updateObjecteUniform } from '../../util/object3d-util';
+import * as THREE from '../../core/three';
+import MaskMaterial from '../../geom/material/tile/maskMaterial';
+import { getRender } from '../render/index';
+export default class VectorTile extends Tile {
+ requestTileAsync(done) {
+ // Making this asynchronous really speeds up the LOD framerate
+ setTimeout(() => {
+ if (!this._mesh) {
+ // this._mesh = this._createMesh();
+ this._requestTile(done);
+ }
+ }, 0);
+ }
+ _requestTile(done) {
+ const urlParams = {
+ x: this._tile[0],
+ y: this._tile[1],
+ z: this._tile[2]
+ };
+
+ const url = this._getTileURL(urlParams);
+ this.xhrRequest = getArrayBuffer({ url }, (err, data) => {
+ if (err) {
+ this._noData = true;
+ return;
+ }
+ this._isLoaded = true;
+ done(data.data);
+ });
+ }
+ _creatSource(data) {
+ this.source = this.layer.tileSource(data, {
+ parser: {
+ tile: this._tile
+ }
+ });
+ }
+ _createMesh() {
+ if (this.layer.get('layerType') === 'point') {
+ this.layer.shape = this.layer._getShape(this.layerData);
+ }
+ this.mesh = getRender(this.layer.get('layerType'), this.layer.shape)(this.layerData, this.layer);
+ if (this.mesh.type !== 'composer') { // 热力图的情况
+ this.mesh.onBeforeRender = renderer => {
+ this._renderMask(renderer);
+ };
+ this.mesh.onAfterRender = renderer => {
+ const context = renderer.context;
+ context.disable(context.STENCIL_TEST);
+ };
+ this._object3D.add(this.mesh);
+ } else {
+ this._object3D = this.mesh;
+ }
+
+ this.emit('tileLoaded');
+ return this._object3D;
+ }
+ _renderMask(renderer) {
+ const zoom = this.layer.scene.getZoom();
+ updateObjecteUniform(this.mesh, {
+ u_time: this.layer.scene._engine.clock.getElapsedTime(),
+ u_zoom: zoom
+ });
+ if (this.layer.get('layerType') === 'point') { // 点图层目前不需要mask
+ return;
+ }
+ const maskScene = new THREE.Scene();
+ this.maskScene = maskScene;
+ const tileMesh = this._tileMaskMesh();
+ maskScene.add(tileMesh);
+ const context = renderer.context;
+ renderer.autoClear = false;
+ renderer.clearDepth();
+ context.enable(context.STENCIL_TEST);
+ context.stencilOp(context.REPLACE, context.REPLACE, context.REPLACE);
+ context.stencilFunc(context.ALWAYS, 1, 0xffffffff);
+ context.clearStencil(0);
+ context.clear(context.STENCIL_BUFFER_BIT);
+ context.colorMask(false, false, false, false);
+
+ // config the stencil buffer to collect data for testing
+ this.layer.scene._engine.renderScene(maskScene);
+ context.colorMask(true, true, true, true);
+ context.depthMask(true);
+ renderer.clearDepth();
+
+ // only render where stencil is set to 1
+
+ context.stencilFunc(context.EQUAL, 1, 0xffffffff); // draw if == 1
+ context.stencilOp(context.KEEP, context.KEEP, context.KEEP);
+ }
+ _tileMaskMesh() {
+ const tilebound = this._tileBounds;
+ const bl = [ tilebound.getBottomLeft().x, tilebound.getBottomLeft().y, 0 ];
+ const br = [ tilebound.getBottomRight().x, tilebound.getBottomRight().y, 0 ];
+ const tl = [ tilebound.getTopLeft().x, tilebound.getTopLeft().y, 0 ];
+ const tr = [ tilebound.getTopRight().x, tilebound.getTopRight().y, 0 ];
+ const positions = [ ...bl, ...tr, ...br, ...bl, ...tl, ...tr ];
+ const geometry = new THREE.BufferGeometry();
+ geometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
+ const maskMaterial = new MaskMaterial();
+ const maskMesh = new THREE.Mesh(geometry, maskMaterial);
+ return maskMesh;
+ }
+ _abortRequest() {
+ if (!this.xhrRequest) {
+ return;
+ }
+
+ this.xhrRequest.abort();
+ }
+ getSelectFeature(id) {
+ const featureIndex = this.source.originData.featureKeys[id];
+ if (featureIndex) {
+ return this.source.originData.dataArray[featureIndex];
+ }
+ return null;
+ }
+ destroy() {
+ super.destroy();
+ destoryObject(this.maskScene);
+ this._object3D = null;
+ this.maskScene = null;
+ this.layerData = null;
+ this.source.destroy();
+ this.source = null;
+ }
+}
diff --git a/src/source/index.js b/src/source/index.js
index 1d7fe62ba4..b1d1819c64 100644
--- a/src/source/index.js
+++ b/src/source/index.js
@@ -5,6 +5,7 @@ import image from './parser/image';
import csv from './parser/csv';
import json from './parser/json';
import raster from './parser/raster';
+import mvt from './parser/mvt';
import { registerTransform, registerParser } from './factory';
import { aggregatorToGrid } from './transform/grid';
@@ -16,6 +17,7 @@ registerParser('image', image);
registerParser('csv', csv);
registerParser('json', json);
registerParser('raster', raster);
+registerParser('mvt', mvt);
// 注册transform
registerTransform('grid', aggregatorToGrid);
diff --git a/src/source/parser/geojson.js b/src/source/parser/geojson.js
index 0e7d4de3f1..79e49bd68d 100644
--- a/src/source/parser/geojson.js
+++ b/src/source/parser/geojson.js
@@ -1,23 +1,35 @@
import * as turfMeta from '@turf/meta';
import { getCoords } from '@turf/invariant';
-
-export default function geoJSON(data) {
+import { BKDRHash } from '../../util/bkdr-hash';
+export default function geoJSON(data, cfg) {
const resultData = [];
+ const featureKeys = {};
data.features = data.features.filter(item => {
return item != null && item.geometry && item.geometry.type && item.geometry.coordinates && item.geometry.coordinates.length > 0;
});
-
// 数据为空时处理
turfMeta.flattenEach(data, (currentFeature, featureIndex) => { // 多个polygon 拆成一个
const coord = getCoords(currentFeature);
+ let id = featureIndex + 1;
+ if (cfg.idField && currentFeature.properties[cfg.idField]) {
+ const value = currentFeature.properties[cfg.idField];
+ // id = value;
+ id = BKDRHash(value) % 1000019;
+ // if (featureKeys[id] && featureIndex !== featureKeys[id]) {
+ // // TODO 哈希冲突解决方法
+ // console.log('哈希冲突', value);
+ // }
+ }
+ featureKeys[id] = featureIndex;
const dataItem = {
...currentFeature.properties,
coordinates: coord,
- _id: featureIndex + 1
+ _id: id
};
resultData.push(dataItem);
});
return {
- dataArray: resultData
+ dataArray: resultData,
+ featureKeys
};
}
diff --git a/src/source/parser/mvt.js b/src/source/parser/mvt.js
new file mode 100644
index 0000000000..7e5165488b
--- /dev/null
+++ b/src/source/parser/mvt.js
@@ -0,0 +1,19 @@
+import PBF from 'pbf';
+import * as VectorParser from '@mapbox/vector-tile';
+import geojson from './geojson';
+export default function mvt(data, cfg) {
+ const tile = new VectorParser.VectorTile(new PBF(data));
+ // CHN_Cities_L CHN_Cities CHN_L
+ const layerName = cfg.sourceLayer;
+ const features = [];
+ const vectorLayer = tile.layers[layerName];
+ for (let i = 0; i < vectorLayer.length; i++) {
+ const feature = vectorLayer.feature(i);
+ features.push(feature.toGeoJSON(cfg.tile[0], cfg.tile[1], cfg.tile[2]));
+ }
+ const geodata = {
+ type: 'FeatureCollection',
+ features
+ };
+ return geojson(geodata, cfg);
+}
diff --git a/src/util/bkdr-hash.js b/src/util/bkdr-hash.js
new file mode 100644
index 0000000000..12848786a1
--- /dev/null
+++ b/src/util/bkdr-hash.js
@@ -0,0 +1,16 @@
+export function BKDRHash(str) {
+ const seed = 131;
+ const seed2 = 137;
+ let hash = 0;
+ // make hash more sensitive for short string like 'a', 'b', 'c'
+ str += 'x';
+ // Note: Number.MAX_SAFE_INTEGER equals 9007199254740991
+ const MAX_SAFE_INTEGER = parseInt(9007199254740991 / seed2);
+ for (let i = 0; i < str.length; i++) {
+ if (hash > MAX_SAFE_INTEGER) {
+ hash = parseInt(hash / seed2);
+ }
+ hash = hash * seed + str.charCodeAt(i);
+ }
+ return hash;
+}
diff --git a/src/util/lru-cache.js b/src/util/lru-cache.js
index ab7a78339b..d44c2626dc 100644
--- a/src/util/lru-cache.js
+++ b/src/util/lru-cache.js
@@ -48,10 +48,10 @@ export default class LRUCache {
delete(key) {
const value = this._cache[key];
- this.destroy(value);
if (value) {
this._deleteCache(key);
this._deleteOrder(key);
+ this.destroy(value);
}
}
diff --git a/src/util/object3d-util.js b/src/util/object3d-util.js
new file mode 100644
index 0000000000..17100fccb3
--- /dev/null
+++ b/src/util/object3d-util.js
@@ -0,0 +1,58 @@
+import pickingFragmentShader from '../core/engine/picking/picking_frag.glsl';
+import * as THREE from '../core/three';
+export function destoryObject(obj) {
+ if (!obj) {
+ return;
+ }
+ if (obj.children) {
+ for (let i = 0; i < obj.children.length; i++) {
+ const child = obj.children[i];
+ destoryObject(child);
+ }
+ }
+ if (obj.geometry) {
+ obj.geometry.dispose();
+ obj.geometry = null;
+ }
+ if (obj.material) {
+ if (obj.material.map) {
+ obj.material.map.dispose();
+ obj.material.map = null;
+ }
+
+ obj.material.dispose();
+ obj.material = null;
+ }
+}
+export function updateObjecteUniform(obj, newOption) {
+ if (!obj) {
+ return;
+ }
+ if (obj.children) {
+ for (let i = 0; i < obj.children.length; i++) {
+ const child = obj.children[i];
+ updateObjecteUniform(child, newOption);
+ }
+ }
+ if (obj.material) {
+ obj.material.updateUninform(newOption);
+ }
+}
+export function getPickObject(obj, newbj) {
+ if (!obj) {
+ return;
+ }
+ if (obj.isMesh) {
+ const pickmaterial = obj.material.clone();
+ pickmaterial.fragmentShader = pickingFragmentShader;
+ const pickMesh = new THREE[obj.type](obj.geometry, pickmaterial);
+ newbj.add(pickMesh);
+ }
+ if (obj.children) {
+ const newObj = new THREE.Object3D();
+ for (let i = 0; i < obj.children.length; i++) {
+ const child = obj.children[i];
+ newObj.add(getPickObject(child, newbj));
+ }
+ }
+}