feat(layer): add tile

This commit is contained in:
thinkinggis 2019-04-02 11:59:43 +08:00
parent ee284d81cc
commit 181d7bc42f
16 changed files with 399 additions and 58 deletions

View File

@ -24,7 +24,7 @@
<script src="../build/L7.js"></script>
<script>
const colorObj ={
blue: ["#E8FCFF", "#CFF6FF", "#A1E9ff", "#65CEF7", "#3CB1F0", "#2894E0", "#1772c2", "#105CB3", "#0D408C", "#002466"].reverse(),
blue: ["#E8FCFF", "#CFF6FF", "#A1E9ff", "#65CEF7", "#3CB1F0", "#2894E0", "#1772c2", "#105CB3", "#0D408C", "#002466"],
red: ["#FFF4F2", "#FFDFDB", "#FAADAA", "#F77472", "#F04850", "#D63147", "#BD223E", "#A81642", "#820C37", "#5C0023"].reverse(),
orange:["#FFF7EB", "#FFECD4", "#FAD09D", "#F7B16A", "#F08D41", "#DB6C2C", "#C2491D", "#AD2B11", "#871D0C", "#610800"].reverse(),
green:["#FAFFF0", "#EBF7D2", "#C8E695", "#A5D660", "#7DC238", "#59A616", "#3F8C0B", "#237804", "#125200", "#082B00"].reverse(),
@ -35,7 +35,7 @@ const colorObj ={
const scene = new L7.Scene({
id: 'map',
mapStyle: 'light', // 样式URL
mapStyle: 'dark', // 样式URL
center: [ 120.19382669582967, 30.258134 ],
pitch: 0,
zoom: 12,
@ -52,14 +52,14 @@ scene.on('loaded', () => {
isCluster:true
})
.shape('hexagon')
.size('point_count', [ 2, 30]) // default 1
.size('point_count', [ 5, 40]) // default 1
//.size('value', [ 10, 300]) // default 1
.active(true)
.color('#2894E0')
.color('point_count',colorObj.blue)
.style({
stroke: 'rgb(255,255,255)',
strokeWidth: 1,
opacity: 0.8
opacity: 1
})
.render();
window.circleLayer = circleLayer;
@ -69,8 +69,11 @@ scene.on('loaded', () => {
.source(circleLayer.layerSource)
.shape('point_count', 'text')
.active(true)
.size('point_count', [ 0, 16]) // default 1
.color('#f00')
.filter('point_count',(p)=>{
return p > 50
})
.size('point_count', [ 5, 20]) // default 1
.color('#fff')
.style({
stroke: '#999',
strokeWidth: 0,

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{
"name": "@antv/l7",
"version": "1.1.7",
"version": "1.1.8",
"description": "Large-scale WebGL-powered Geospatial Data Visualization",
"main": "build/l7.js",
"browser": "build/l7.js",

View File

@ -557,7 +557,6 @@ export default class Layer extends Base {
let { featureId, point2d, type } = e;
if (featureId < 0 && this._activeIds !== null) {
type = 'mouseleave';
// featureId = this._activeIds;
}
this._activeIds = featureId;
const feature = this.layerSource.getSelectFeature(featureId);
@ -579,7 +578,7 @@ export default class Layer extends Base {
}
/**
* 用于过滤数据
* @param {*} object 需要过滤的mesh
* @param {*} object 更新颜色和数据过滤
*/
_updateFilter(object) {
this._updateMaping();
@ -629,6 +628,7 @@ export default class Layer extends Base {
this._object3D.visible = true;
}
}
// 重新构建mesh
redraw() {
this._object3D.children.forEach(child => {

View File

@ -1,21 +1,38 @@
import Base from '../core/base';
export class GeomBase extends Base {
export const GeomBase = {
color: 'updateDraw',
size: 'repaint',
filter: 'updateDraw',
layer: '',
pickable: true,
setLayer(layer) {
this.layer = layer;
this.style = layer.get('styleOption');
},
getShape(type) {
return type;
},
draw() {
const shape = this.getShape();
this.Mesh = shape.Mesh();
},
// 更新geometry buffer;
updateDraw() {
},
repaint() {
}
};
export const shapeBae = {
geometryBuffer() {
},
geometry() {},
material() {},
mesh() {
}
geometry() {
}
material() {
}
drawMesh() {
}
}
export default GeomBase;
};

View File

@ -55,7 +55,8 @@ export function MeshLineMaterial(options) {
},
vertexShader: vs,
fragmentShader: fs,
transparent: true
transparent: true,
blending: THREE.AdditiveBlending
});
return material;
}

View File

@ -16,7 +16,8 @@ void main() {
}
#ifdef ANIMATE
vTime = 1.0- (mod(u_time*50.,3600.)- position.z) / 100.;
// vTime = 1.0- (28800. + mod(u_time* 10.,28800.)- position.z / 1000.) / 100.;
#endif
gl_Position = matModelViewProjection * vec4(position.xy,0., 1.0);
gl_Position = matModelViewProjection * vec4(position.xy, 0., 1.0);
worldId = id_toPickColor(pickingId);
}

View File

@ -20,7 +20,7 @@ uniform float u_trailLength;
void main() {
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
vec3 pointPos = position.xyz + vec3(normal * a_size * pow(2.0,20.0-u_zoom) / 2.0 * a_miter);
vec3 pointPos = vec3(position.xy,0.) + vec3(normal * a_size * pow(2.0,20.0-u_zoom) / 2.0 * a_miter);
v_color = a_color;
if(pickingId == u_activeId) {
v_color = u_activeColor;
@ -30,8 +30,9 @@ void main() {
float alpa =1.0 - fract( mod(1.0- a_distance,u_interval)* (1.0/u_interval) + u_time / u_duration);
alpa = (alpa + u_trailLength -1.0) / u_trailLength;
vTime = clamp(alpa,0.,1.);
// vTime = (28800. + mod(u_time* 1000.,28800.)- position.z) / 100.;
#endif
worldId = id_toPickColor(pickingId);
gl_Position = matModelViewProjection * vec4(pointPos, 1.0);
gl_Position = matModelViewProjection * vec4(pointPos.xy, 0., 1.0);
}

View File

@ -94,7 +94,7 @@ export function Line(path, props, positionsIndex) {
indexArray[c++] = i + 2;
indexArray[c++] = i + 3;
}
point[2] = size[1];
// point[2] = size[1];
positions.push(...point);
positions.push(...point);

View File

@ -135,9 +135,9 @@ export default class PointLayer extends Layer {
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)) {
(Math.abs(zoom - preZoom)) < 0.5)) {
const newbbox = [ SW.lng - step, SW.lat - step, NE.lng + step, NE.lat + step ];
this.layerSource.updateCusterData(Math.floor(zoom), newbbox);
this.layerSource.updateCusterData(Math.floor(zoom - 1), newbbox);
this.repaint();
}
}

137
src/layer/tile/imageTile.js Normal file
View File

@ -0,0 +1,137 @@
// import * as THREE from '../../core/three';
// import Tile from './tile';
// export default class ImageTile extends Tile {
// constructor(layer, z, x, y) {
// }
// requestTileAsync() {
// // Making this asynchronous really speeds up the LOD framerate
// setTimeout(() => {
// if (!this._mesh) {
// this._mesh = this._createMesh();
// this._requestTile();
// }
// }, 0);
// }
// _requestTile() {
// const urlParams = {
// x: this._tile[0],
// y: this._tile[1],
// z: this._tile[2]
// };
// const url = this._getTileURL(urlParams);
// const image = document.createElement('img');
// image.addEventListener('load', event => {
// const texture = new THREE.Texture();
// texture.image = image;
// texture.needsUpdate = true;
// // Silky smooth images when tilted
// texture.magFilter = THREE.LinearFilter;
// texture.minFilter = THREE.LinearMipMapLinearFilter;
// // TODO: Set this to renderer.getMaxAnisotropy() / 4
// texture.anisotropy = 4;
// texture.needsUpdate = true;
// // Something went wrong and the tile or its material is missing
// //
// // Possibly removed by the cache before the image loaded
// if (!this._mesh || !this._mesh.children[0] || !this._mesh.children[0].material) {
// return;
// }
// this._mesh.children[0].material.map = texture;
// this._mesh.children[0].material.needsUpdate = true;
// this._texture = texture;
// this._ready = true;
// }, false);
// // image.addEventListener('progress', event => {}, false);
// // image.addEventListener('error', event => {}, false);
// image.crossOrigin = '';
// // Load image
// image.src = url;
// this._image = image;
// }
// _createMesh() {
// // Something went wrong and the tile
// //
// // Possibly removed by the cache before loaded
// if (!this._center) {
// return;
// }
// const mesh = new THREE.Object3D();
// const geom = new THREE.PlaneBufferGeometry(this._side, this._side, 1);
// let material;
// if (!this._world._environment._skybox) {
// material = new THREE.MeshBasicMaterial({
// depthWrite: false
// });
// // const material = new THREE.MeshPhongMaterial({
// // depthWrite: false
// // });
// } else {
// // Other MeshStandardMaterial settings
// //
// // material.envMapIntensity will change the amount of colour reflected(?)
// // from the environment mapcan be greater than 1 for more intensity
// material = new THREE.MeshStandardMaterial({
// depthWrite: false
// });
// material.roughness = 1;
// material.metalness = 0.1;
// material.envMap = this._world._environment._skybox.getRenderTarget();
// }
// const localMesh = new THREE.Mesh(geom, material);
// localMesh.rotation.x = -90 * Math.PI / 180;
// localMesh.receiveShadow = true;
// mesh.add(localMesh);
// mesh.renderOrder = 0.1;
// mesh.position.x = this._center[0];
// mesh.position.z = this._center[1];
// // const box = new BoxHelper(localMesh);
// // mesh.add(box);
// //
// // mesh.add(this._createDebugMesh());
// return mesh;
// }
// _abortRequest() {
// if (!this._image) {
// return;
// }
// this._image.src = '';
// }
// destroy() {
// // Cancel any pending requests
// this._abortRequest();
// // Clear image reference
// this._image = null;
// super.destroy();
// }
// }

View File

@ -0,0 +1,22 @@
import LRUCache from '../../util/lru-cache';
export default class TileCache {
constructor(limit = 50) {
this._cache = new LRUCache(limit);
}
getTile(z, x, y) {
const key = this._generateKey(z, x, y);
return this._cache.get(key);
}
setTile(tile, z, x, y) {
const key = this._generateKey(z, x, y);
this._cache.set(key, tile);
}
_generateKey(z, x, y) {
return [ z, x, y ].join('_');
}
destory() {
this._cache.clear();
}
}

59
src/layer/tile/tile.js Normal file
View File

@ -0,0 +1,59 @@
// const r2d = 180 / Math.PI;
// const tileURLRegex = /\{([zxy])\}/g;
// export class Tile {
// constructor(layer, z, x, y) {
// this.layer = layer;
// this._tile = [ z, x, y ];
// }
// _createMesh() {}
// _createDebugMesh() {}
// _getTileURL(urlParams) {
// if (!urlParams.s) {
// // Default to a random choice of a, b or c
// urlParams.s = String.fromCharCode(97 + Math.floor(Math.random() * 3));
// }
// tileURLRegex.lastIndex = 0;
// return this._path.replace(tileURLRegex, function(value, key) {
// // Replace with paramter, otherwise keep existing value
// return urlParams[key];
// });
// }
// _tileBoundsFromWGS84(boundsWGS84) {
// const sw = this._layer._world.latLonToPoint(LatLon(boundsWGS84[1], boundsWGS84[0]));
// const ne = this._layer._world.latLonToPoint(LatLon(boundsWGS84[3], boundsWGS84[2]));
// return [sw.x, sw.y, ne.x, ne.y];
// }
// // Get tile bounds in WGS84 coordinates
// _tileBoundsWGS84(tile) {
// const e = this._tile2lon(tile[0] + 1, tile[2]);
// const w = this._tile2lon(tile[0], tile[2]);
// const s = this._tile2lat(tile[1] + 1, tile[2]);
// const n = this._tile2lat(tile[1], tile[2]);
// return [ w, s, e, n ];
// }
// _tile2lon(x, z) {
// return x / Math.pow(2, z) * 360 - 180;
// }
// _tile2lat(y, z) {
// const n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
// return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
// }
// _boundsToCenter(bounds) {
// const x = bounds[0] + (bounds[2] - bounds[0]) / 2;
// const y = bounds[1] + (bounds[3] - bounds[1]) / 2;
// return [ x, y ];
// }
// destory() {
// }
// }

View File

@ -1,11 +1,10 @@
import * as turfMeta from '@turf/meta';
import { default as cleanCoords } from '@turf/clean-coords';
import { getCoords } from '@turf/invariant';
export default function geoJSON(data) {
const resultData = [];
turfMeta.flattenEach(data, (currentFeature, featureIndex) => { // 多个polygon 拆成一个
const coord = getCoords(cleanCoords(currentFeature));
const coord = getCoords(currentFeature);
const dataItem = {
...currentFeature.properties,
coordinates: coord,

View File

@ -1,6 +1,6 @@
import Supercluster from 'supercluster';
export function cluster(data, option) {
const { radius = 40, maxZoom = 16, minZoom = 0, field, zoom = 2 } = option;
const { radius = 80, maxZoom = 18, minZoom = 0, field, zoom = 2 } = option;
if (data.pointIndex) {
const clusterPoint = data.pointIndex.getClusters(data.extent, zoom);
data.dataArray = formatData(clusterPoint);

71
src/util/lru-cache.js Normal file
View File

@ -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);
}
}