From 5e494fe7529252a256d147014257cafcc1c1bd78 Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Wed, 17 Apr 2019 15:41:26 +0800 Subject: [PATCH 1/6] feat(tile): add tile --- demos/01_point_circle.html | 4 +- package.json | 1 + src/core/engine/picking/picking.js | 12 +- src/core/source.js | 2 +- src/geo/{buffer.js => lnglat.js} | 0 src/geo/point.js | 0 src/geom/buffer/image.js | 2 +- src/geom/extrude.js | 10 +- src/geom/shader/index.js | 5 + src/geom/shader/polygon_frag.glsl | 13 +- src/geom/shader/polygon_vert.glsl | 3 +- src/geom/shape/path.js | 6 +- src/layer/render/image/drawImage.js | 13 ++ src/layer/render/polygon/drawFill.js | 12 +- src/layer/tile/imageTile.js | 190 +++++++----------- src/layer/tile/tile.js | 99 ++++----- .../tile/{tile-cache.js => tileCache.js} | 0 src/layer/tile/tileLayer.js | 8 + 18 files changed, 183 insertions(+), 197 deletions(-) rename src/geo/{buffer.js => lnglat.js} (100%) create mode 100644 src/geo/point.js create mode 100644 src/layer/render/image/drawImage.js rename src/layer/tile/{tile-cache.js => tileCache.js} (100%) create mode 100644 src/layer/tile/tileLayer.js diff --git a/demos/01_point_circle.html b/demos/01_point_circle.html index 57c8ef8dc7..f63a295ae3 100644 --- a/demos/01_point_circle.html +++ b/demos/01_point_circle.html @@ -59,11 +59,11 @@ scene.on('loaded', () => { .source(data,{ isCluster:true }) - .shape('hexagon') + .shape('circle') .size('point_count', [ 5, 40]) // default 1 //.size('value', [ 10, 300]) // default 1 .active(true) - .color('point_count',colorObj.blue) + .color('point_count',["#002466","#105CB3","#2894E0","#CFF6FF","#FFF5B8","#FFAB5C","#F27049","#730D1C"]) .style({ stroke: 'rgb(255,255,255)', strokeWidth: 1, diff --git a/package.json b/package.json index 529672e824..125dcb8168 100755 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ }, "dependencies": { "@antv/g": "^3.1.3", + "@antv/geo-coord": "^1.0.8", "@antv/util": "~2.0.1", "@mapbox/tiny-sdf": "^1.1.0", "@turf/bbox": "^6.0.1", diff --git a/src/core/engine/picking/picking.js b/src/core/engine/picking/picking.js index 6d6ba60de1..3d61d86427 100755 --- a/src/core/engine/picking/picking.js +++ b/src/core/engine/picking/picking.js @@ -87,21 +87,11 @@ class Picking { id = -999; // return; } - this._raycaster.setFromCamera(normalisedPoint, this._camera); - - const intersects = this._raycaster.intersectObjects(this._pickingScene.children, true); const _point2d = { x: point.x, y: point.y }; - - let _point3d; - if (intersects.length > 0) { - _point3d = intersects[0].point; - } const item = { layerId, featureId: id, - point2d: _point2d, - point3d: _point3d, - intersects + point2d: _point2d }; return item; diff --git a/src/core/source.js b/src/core/source.js index 765636ea5d..60f667c755 100644 --- a/src/core/source.js +++ b/src/core/source.js @@ -33,7 +33,7 @@ export default class Source extends Base { // 数据转换 统计,聚合,分类 this._executeTrans(); // 坐标转换 - this._projectCoords(); + // this._projectCoords(); } setData(data, cfg = {}) { Object.assign(this._attrs, cfg); diff --git a/src/geo/buffer.js b/src/geo/lnglat.js similarity index 100% rename from src/geo/buffer.js rename to src/geo/lnglat.js diff --git a/src/geo/point.js b/src/geo/point.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/geom/buffer/image.js b/src/geom/buffer/image.js index 262151b149..5c69a4abf5 100644 --- a/src/geom/buffer/image.js +++ b/src/geom/buffer/image.js @@ -23,7 +23,7 @@ export default class ImageBuffer extends BufferBase { const uv = [ 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ]; const texture = new THREE.Texture(image); texture.magFilter = THREE.LinearFilter; - texture.minFilter = THREE.LinearFilter; + texture.minFilter = THREE.LinearMipMapLinearFilter; texture.needsUpdate = true; const attributes = { vertices: new Float32Array(positions), diff --git a/src/geom/extrude.js b/src/geom/extrude.js index 3b3375b798..8ae4aef5c1 100644 --- a/src/geom/extrude.js +++ b/src/geom/extrude.js @@ -19,18 +19,18 @@ export default function extrudePolygon(points, extrude) { const flattengeo = earcut.flatten(points); const positions = []; let cells = []; - + const { dimensions } = flattengeo; const triangles = earcut(flattengeo.vertices, flattengeo.holes, flattengeo.dimensions); cells = triangles; - const pointCount = flattengeo.vertices.length / 3; + const pointCount = flattengeo.vertices.length / dimensions; const { vertices } = flattengeo; extrude ? full() : flat(); function flat() { for (let i = 0; i < pointCount; i++) { - positions.push([ vertices[ i * 3 ], vertices[i * 3 + 1 ], 0 ]); + positions.push([ vertices[ i * dimensions ], vertices[i * dimensions + 1 ], 0 ]); } } function full() { @@ -41,10 +41,10 @@ export default function extrudePolygon(points, extrude) { // 顶部坐标 for (let i = 0; i < pointCount; i++) { - positions.push([ vertices[ i * 3 ], vertices[i * 3 + 1 ], 1 ]); + positions.push([ vertices[ i * dimensions ], vertices[i * dimensions + 1 ], 1 ]); } for (let i = 0; i < pointCount; i++) { - positions.push([ vertices[ i * 3 ], vertices[i * 3 + 1 ], 0 ]); + positions.push([ vertices[ i * dimensions ], vertices[i * dimensions + 1 ], 0 ]); } for (let i = 0; i < n; i++) { if (i === (n - 1)) { diff --git a/src/geom/shader/index.js b/src/geom/shader/index.js index c884b87690..0962214754 100644 --- a/src/geom/shader/index.js +++ b/src/geom/shader/index.js @@ -41,6 +41,10 @@ import image_frag from '../shader/image_frag.glsl'; import raster_vert from '../shader/raster_vert.glsl'; import raster_frag from '../shader/raster_frag.glsl'; +// tile +import tile_polygon_vert from '../shader/tile/polygon_vert.glsl'; +import tile_polygon_frag from '../shader/tile/polygon_frag.glsl'; + import common from './common.glsl'; import { registerModule } from '../../util/shaderModule'; import pick_color from './shaderChunks/pick_color.glsl'; @@ -60,5 +64,6 @@ export function compileBuiltinModules() { registerModule('text', { vs: text_vert, fs: text_frag }); 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 }); } diff --git a/src/geom/shader/polygon_frag.glsl b/src/geom/shader/polygon_frag.glsl index bad3913f6b..545721cd04 100644 --- a/src/geom/shader/polygon_frag.glsl +++ b/src/geom/shader/polygon_frag.glsl @@ -41,7 +41,12 @@ float sdRect(vec2 p, vec2 sz) { float inside = min(max(d.x, d.y), 0.); return outside + inside; } - +float circle(in vec2 _st, in float _radius){ + vec2 dist = _st-vec2(0.5); + return 1.-smoothstep(_radius-(_radius*0.01), + _radius+(_radius*0.01), + dot(dist,dist)*4.0); +} void main() { if(v_color.w == 0.0) { @@ -106,6 +111,12 @@ void main() { gl_FragColor = vec4(foggedColor,1.0); } #else + // #ifdef SHAPE + // vec2 st = gl_FragCoord.xy / v_size ; + // vec3 color = vec3(circle(st,0.5)); + // gl_FragColor = vec4(color, 1.0 ); + // return; + // #endif gl_FragColor = vec4(v_color.xyz , v_color.w); #endif diff --git a/src/geom/shader/polygon_vert.glsl b/src/geom/shader/polygon_vert.glsl index 2015bee5f5..815244fb97 100644 --- a/src/geom/shader/polygon_vert.glsl +++ b/src/geom/shader/polygon_vert.glsl @@ -30,6 +30,7 @@ void main() { if(pickingId == u_activeId) { v_color = u_activeColor; } + v_size = a_size.x * scale; gl_Position = matModelViewProjection * vec4(newposition, 1.0); return; } @@ -49,7 +50,7 @@ void main() { float lightWeight = ambientRatio + diffuseRatio * lambert + specularRatio * specular; v_texCoord = faceUv; v_lightWeight = lightWeight; - // v_size = a_size; + v_color =vec4(a_color.rgb*lightWeight, a_color.w); if(pickingId == u_activeId) { v_color = u_activeColor; diff --git a/src/geom/shape/path.js b/src/geom/shape/path.js index a693484d9c..82bd51d68e 100644 --- a/src/geom/shape/path.js +++ b/src/geom/shape/path.js @@ -16,7 +16,7 @@ function triangle() { return polygonPath(3); } function hexagon() { - return polygonPath(6); + return polygonPath(6, 1); } export { circle, @@ -29,11 +29,11 @@ export { square as squareColumn }; -export function polygonPath(pointCount) { +export function polygonPath(pointCount, start = 0) { const step = Math.PI * 2 / pointCount; const line = []; for (let i = 0; i < pointCount; i++) { - line.push(step * i - Math.PI / 12); + line.push(step * i - start * Math.PI / 12); } const path = line.map(t => { const x = Math.sin(t + Math.PI / 4), diff --git a/src/layer/render/image/drawImage.js b/src/layer/render/image/drawImage.js new file mode 100644 index 0000000000..54a49d75a3 --- /dev/null +++ b/src/layer/render/image/drawImage.js @@ -0,0 +1,13 @@ +import * as THREE from '../../../core/three'; +import ImageMaterial from '../../../geom/material/imageMaterial'; +export default function DrawImage(attributes, style) { + this.geometry = new THREE.BufferGeometry(); + this.geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); + this.geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.uvs, 2)); + const { opacity } = style; + const material = new ImageMaterial({ + u_texture: attributes.texture, + u_opacity: opacity + }); + return new THREE.Mesh(this.geometry, material); +} diff --git a/src/layer/render/polygon/drawFill.js b/src/layer/render/polygon/drawFill.js index 8c5e5beb65..b273686929 100644 --- a/src/layer/render/polygon/drawFill.js +++ b/src/layer/render/polygon/drawFill.js @@ -1,5 +1,7 @@ import * as THREE from '../../../core/three'; -import PolygonMaterial from '../../../geom/material/polygonMaterial'; +// import PolygonMaterial from '../../../geom/material/polygonMaterial'; +import TileMaterial from '../../../geom/material/tile/polygon'; + export default function DrawPolygonFill(attributes, style) { const { opacity, activeColor } = style; const geometry = new THREE.BufferGeometry(); @@ -7,7 +9,13 @@ export default function DrawPolygonFill(attributes, style) { 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({ + // const material = new PolygonMaterial({ + // u_opacity: opacity, + // u_activeColor: activeColor + // }, { + // SHAPE: false + // }); + const material = new TileMaterial({ u_opacity: opacity, u_activeColor: activeColor }, { diff --git a/src/layer/tile/imageTile.js b/src/layer/tile/imageTile.js index c14a052e01..3a3a8f6b46 100644 --- a/src/layer/tile/imageTile.js +++ b/src/layer/tile/imageTile.js @@ -1,137 +1,83 @@ -// 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] -// }; +import Tile from './tile'; +import ImageBuffer from '../../geom/buffer/image'; +import DrawImage from '../render/image/drawImage'; +export default class ImageTile extends Tile { + 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 url = this._getTileURL(urlParams); -// const image = document.createElement('img'); + const image = document.createElement('img'); -// image.addEventListener('load', event => { -// const texture = new THREE.Texture(); + image.addEventListener('load', () => { -// texture.image = image; -// texture.needsUpdate = true; + this._createMesh(image); + this._ready = true; + }, false); -// // Silky smooth images when tilted -// texture.magFilter = THREE.LinearFilter; -// texture.minFilter = THREE.LinearMipMapLinearFilter; + // image.addEventListener('progress', event => {}, false); + // image.addEventListener('error', event => {}, false); -// // TODO: Set this to renderer.getMaxAnisotropy() / 4 -// texture.anisotropy = 4; + image.crossOrigin = ''; -// texture.needsUpdate = true; + // Load image + image.src = url; -// // 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._image = image; + } + _getBufferData(images) { + const NW = this._tileBounds.getTopLeft().to; + const SE = this._tileBounds.getBottomRight(); + const coordinate = [[ NW.x, NW.y ], [ SE.x, SE.y ]]; + return [{ + coordinate, + images + }]; + } + _createMesh(image) { + if (!this._center) { + return; + } + this._layerData = this._getBufferData(image); + const buffer = new ImageBuffer({ + layerData: this._layerData + }); -// this._mesh.children[0].material.map = texture; -// this._mesh.children[0].material.needsUpdate = true; + const style = this.get('styleOptions'); + const mesh = DrawImage(buffer.attributes, style); + this.Object3D.push(mesh); + return this.Object3D; + } + _abortRequest() { + if (!this._image) { + return; + } -// this._texture = texture; -// this._ready = true; -// }, false); + this._image.src = ''; + } -// // image.addEventListener('progress', event => {}, false); -// // image.addEventListener('error', event => {}, false); + destroy() { + // Cancel any pending requests + this._abortRequest(); -// image.crossOrigin = ''; + // Clear image reference + this._image = null; -// // Load image -// image.src = url; + super.destroy(); + } -// 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 map–can 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(); -// } - -// } +} diff --git a/src/layer/tile/tile.js b/src/layer/tile/tile.js index 8ca5d10b48..4502a5bb70 100644 --- a/src/layer/tile/tile.js +++ b/src/layer/tile/tile.js @@ -1,59 +1,62 @@ -// 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 ]; +import * as THREE from '../../core/three'; +import { toLngLatBounds, toBounds } from '@antv/geo-coord'; +import { sphericalMercator } from '@antv/geo-coord/lib/geo/projection/spherical-mercator'; +const r2d = 180 / Math.PI; +const tileURLRegex = /\{([zxy])\}/g; -// } -// _createMesh() {} -// _createDebugMesh() {} +export class Tile { + constructor(layer, z, x, y) { + this.layer = layer; + this._tile = [ x, y, z ]; + this._tileLnglatBounds = this._tileLnglatBounds(this._tile); -// _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)); -// } + this._tileBounds = this._tileBounds(this._tileLnglatBounds); -// tileURLRegex.lastIndex = 0; -// return this._path.replace(tileURLRegex, function(value, key) { -// // Replace with paramter, otherwise keep existing value -// return urlParams[key]; -// }); -// } + this._center = this._tileBounds.getCenter(); -// _tileBoundsFromWGS84(boundsWGS84) { -// const sw = this._layer._world.latLonToPoint(LatLon(boundsWGS84[1], boundsWGS84[0])); -// const ne = this._layer._world.latLonToPoint(LatLon(boundsWGS84[3], boundsWGS84[2])); + this._centerLnglat = this._tileLnglatBounds.getCenter(); + this.Object3D = new THREE.Object3D(); -// 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 ]; -// } + } + _createMesh() {} + _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)); + } -// _tile2lon(x, z) { -// return x / Math.pow(2, z) * 360 - 180; -// } + tileURLRegex.lastIndex = 0; + return this._path.replace(tileURLRegex, function(value, key) { + return urlParams[key]; + }); + } + // 经纬度范围转瓦片范围 + _tileBounds(lnglatBound) { + const nw = sphericalMercator.project(lnglatBound.getTopLeft()); + const se = sphericalMercator.project(lnglatBound.getBottomRight()); -// _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))); -// } + return toBounds(nw, se); + } -// _boundsToCenter(bounds) { -// const x = bounds[0] + (bounds[2] - bounds[0]) / 2; -// const y = bounds[1] + (bounds[3] - bounds[1]) / 2; + // Get tile bounds in WGS84 coordinates + _tileLnglatBounds(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 toLngLatBounds([ w, n ], [ e, s ]); + } -// return [ x, y ]; -// } -// destory() { + _tile2lng(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))); + } + destory() { + + } +} diff --git a/src/layer/tile/tile-cache.js b/src/layer/tile/tileCache.js similarity index 100% rename from src/layer/tile/tile-cache.js rename to src/layer/tile/tileCache.js diff --git a/src/layer/tile/tileLayer.js b/src/layer/tile/tileLayer.js new file mode 100644 index 0000000000..c3a6732ce1 --- /dev/null +++ b/src/layer/tile/tileLayer.js @@ -0,0 +1,8 @@ +import Layer from '../core/layer'; +export class TileLayer extends Layer { + draw() { + } + drawTile() { + + } +} From f4f63c48b1f8cc15d502bf1cda8ce12012b995bc Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Thu, 18 Apr 2019 22:28:17 +0800 Subject: [PATCH 2/6] feat(tile): add image tile layer --- demos/tile.html | 50 ++++------- package.json | 2 +- src/core/scene.js | 3 +- src/core/source.js | 2 +- src/geom/material/imageMaterial.js | 3 +- src/layer/index.js | 4 + src/layer/render/image/drawImage.js | 8 +- src/layer/render/polygon/drawFill.js | 6 +- src/layer/tile/imageTile.js | 15 ++-- src/layer/tile/imageTileLayer.js | 9 ++ src/layer/tile/tile.js | 24 ++--- src/layer/tile/tileCache.js | 11 +-- src/layer/tile/tileLayer.js | 113 +++++++++++++++++++++++- src/map/AMap.js | 1 + test/unit/layer/tile/tile-layer-spec.js | 25 ++++++ 15 files changed, 204 insertions(+), 72 deletions(-) create mode 100644 src/layer/tile/imageTileLayer.js create mode 100644 test/unit/layer/tile/tile-layer-spec.js diff --git a/demos/tile.html b/demos/tile.html index f0867c42a7..bfc4552833 100644 --- a/demos/tile.html +++ b/demos/tile.html @@ -25,50 +25,34 @@ const scene = new L7.Scene({ id: 'map', - mapStyle: 'dark', // 样式URL + mapStyle: 'light', // 样式URL center: [104.838088,34.075889 ], pitch: 0, - zoom: 4.5, + hash:true, + zoom: 3, }); window.scene = scene; scene.on('loaded', () => { - // https://gw.alipayobjects.com/os/basement_prod/24883cde-3352-4e53-af52-f6e59d4fe2c8.json - //tile https://gw.alipayobjects.com/os/basement_prod/c400bd4e-5b46-4769-b969-c1f09feaf908.json - $.getJSON('https://gw.alipayobjects.com/os/basement_prod/c400bd4e-5b46-4769-b969-c1f09feaf908.json', city => { - city.type = "FeatureCollection"; - city.features = city.features.map((item)=>{ - return { - type: "Feature", - properties:item.tags, - "geometry":{ - "type": "Polygon", - "coordinates":item.geometry - } - } - }) - - console.log(city.features[0]); - const citylayer = scene.PolygonLayer() + scene.ImageTileLayer() + .source('http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}') + .render(); + + $.getJSON('https://gw.alipayobjects.com/os/rmsportal/JToMOWvicvJOISZFCkEI.json', city => { + const citylayer = scene.PolygonLayer( + { + zIndex:4 + } + ) .source(city) - .color('Code',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"]) + .color('pm2_5_24h',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"]) .shape('fill') - .active(true) .style({ - opacity: 1 + opacity: 0.2 }) .render(); - console.log(citylayer); - /** - const citylayer2 = scene.PolygonLayer() - .source(city) - .shape('line') - .color('#fff') - .style({ - opacity: 1.0 - }) - .render(); - **/ + + }); }); diff --git a/package.json b/package.json index 125dcb8168..ae5f234a50 100755 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "prepublishOnly": "npm run build-lib && npm run dist", "screenshot": "node ./bin/screenshot.js", "start": "npm run dev", - "test": "torch --compile-opts ./.torch.compile.opts.js --compile --renderer --recursive test/unit", + "test": "torch --compile-opts ./.torch.compile.opts.js --compile --renderer --recursive test/unit", "test-all": "npm run test && npm run test-bugs", "test-bugs": "torch --compile --renderer --recursive test/bugs", "test-bugs-live": "torch --compile --interactive --watch --recursive test/bugs", diff --git a/src/core/scene.js b/src/core/scene.js index 0789516806..637cf59690 100644 --- a/src/core/scene.js +++ b/src/core/scene.js @@ -25,9 +25,10 @@ export default class Scene extends Base { _initEngine(mapContainer) { this._engine = new Engine(mapContainer, this); - this.registerMapEvent(); + // this.registerMapEvent(); // this.workerPool = new WorkerPool(); compileBuiltinModules(); + this._engine.run(); } // 为pickup场景添加 object 对象 addPickMesh(object) { diff --git a/src/core/source.js b/src/core/source.js index 60f667c755..765636ea5d 100644 --- a/src/core/source.js +++ b/src/core/source.js @@ -33,7 +33,7 @@ export default class Source extends Base { // 数据转换 统计,聚合,分类 this._executeTrans(); // 坐标转换 - // this._projectCoords(); + this._projectCoords(); } setData(data, cfg = {}) { Object.assign(this._attrs, cfg); diff --git a/src/geom/material/imageMaterial.js b/src/geom/material/imageMaterial.js index d193576d7b..ecf950f498 100644 --- a/src/geom/material/imageMaterial.js +++ b/src/geom/material/imageMaterial.js @@ -9,7 +9,8 @@ export default function ImageMaterial(options) { }, vertexShader: vs, fragmentShader: fs, - transparent: true + transparent: true, + depthTest: false }); return material; } diff --git a/src/layer/index.js b/src/layer/index.js index 02e72edceb..8b33d8534e 100644 --- a/src/layer/index.js +++ b/src/layer/index.js @@ -5,6 +5,8 @@ import LineLayer from './lineLayer'; import ImageLayer from './imageLayer'; import RasterLayer from './rasterLayer'; import HeatmapLayer from './heatmapLayer'; +import TileLayer from './tile/tileLayer'; +import ImageTileLayer from './tile/imageTileLayer'; registerLayer('PolygonLayer', PolygonLayer); registerLayer('PointLayer', PointLayer); @@ -12,6 +14,8 @@ registerLayer('LineLayer', LineLayer); registerLayer('ImageLayer', ImageLayer); registerLayer('RasterLayer', RasterLayer); registerLayer('HeatmapLayer', HeatmapLayer); +registerLayer('TileLayer', TileLayer); +registerLayer('ImageTileLayer', ImageTileLayer); export { LAYER_MAP } from './factory'; export { registerLayer }; diff --git a/src/layer/render/image/drawImage.js b/src/layer/render/image/drawImage.js index 54a49d75a3..93330df82f 100644 --- a/src/layer/render/image/drawImage.js +++ b/src/layer/render/image/drawImage.js @@ -1,13 +1,13 @@ import * as THREE from '../../../core/three'; import ImageMaterial from '../../../geom/material/imageMaterial'; export default function DrawImage(attributes, style) { - this.geometry = new THREE.BufferGeometry(); - this.geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); - this.geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.uvs, 2)); + const geometry = new THREE.BufferGeometry(); + geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); + geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.uvs, 2)); const { opacity } = style; const material = new ImageMaterial({ u_texture: attributes.texture, u_opacity: opacity }); - return new THREE.Mesh(this.geometry, material); + return new THREE.Mesh(geometry, material); } diff --git a/src/layer/render/polygon/drawFill.js b/src/layer/render/polygon/drawFill.js index b273686929..d9981cbdbb 100644 --- a/src/layer/render/polygon/drawFill.js +++ b/src/layer/render/polygon/drawFill.js @@ -1,6 +1,6 @@ import * as THREE from '../../../core/three'; -// import PolygonMaterial from '../../../geom/material/polygonMaterial'; -import TileMaterial from '../../../geom/material/tile/polygon'; +import PolygonMaterial from '../../../geom/material/polygonMaterial'; +// import TileMaterial from '../../../geom/material/tile/polygon'; export default function DrawPolygonFill(attributes, style) { const { opacity, activeColor } = style; @@ -15,7 +15,7 @@ export default function DrawPolygonFill(attributes, style) { // }, { // SHAPE: false // }); - const material = new TileMaterial({ + const material = new PolygonMaterial({ u_opacity: opacity, u_activeColor: activeColor }, { diff --git a/src/layer/tile/imageTile.js b/src/layer/tile/imageTile.js index 3a3a8f6b46..d30e336385 100644 --- a/src/layer/tile/imageTile.js +++ b/src/layer/tile/imageTile.js @@ -7,7 +7,7 @@ export default class ImageTile extends Tile { // Making this asynchronous really speeds up the LOD framerate setTimeout(() => { if (!this._mesh) { - this._mesh = this._createMesh(); + // this._mesh = this._createMesh(); this._requestTile(); } }, 0); @@ -20,7 +20,6 @@ export default class ImageTile extends Tile { }; const url = this._getTileURL(urlParams); - const image = document.createElement('img'); image.addEventListener('load', () => { @@ -40,11 +39,11 @@ export default class ImageTile extends Tile { this._image = image; } _getBufferData(images) { - const NW = this._tileBounds.getTopLeft().to; + const NW = this._tileBounds.getTopLeft(); const SE = this._tileBounds.getBottomRight(); - const coordinate = [[ NW.x, NW.y ], [ SE.x, SE.y ]]; + const coordinates = [[ NW.x, NW.y, 0 ], [ SE.x, SE.y, 0 ]]; return [{ - coordinate, + coordinates, images }]; } @@ -56,10 +55,10 @@ export default class ImageTile extends Tile { const buffer = new ImageBuffer({ layerData: this._layerData }); - - const style = this.get('styleOptions'); + buffer.attributes.texture = buffer.texture; + const style = this.layer.get('styleOptions'); const mesh = DrawImage(buffer.attributes, style); - this.Object3D.push(mesh); + this.Object3D.add(mesh); return this.Object3D; } _abortRequest() { diff --git a/src/layer/tile/imageTileLayer.js b/src/layer/tile/imageTileLayer.js new file mode 100644 index 0000000000..5f39e39bf7 --- /dev/null +++ b/src/layer/tile/imageTileLayer.js @@ -0,0 +1,9 @@ +import TileLayer from './tileLayer'; +import ImageTile from './imageTile'; + +export default class ImageTileLayer extends TileLayer { + _createTile(key, layer) { + return new ImageTile(key, this.url, layer); + } + +} diff --git a/src/layer/tile/tile.js b/src/layer/tile/tile.js index 4502a5bb70..d96c8a69bf 100644 --- a/src/layer/tile/tile.js +++ b/src/layer/tile/tile.js @@ -1,13 +1,13 @@ import * as THREE from '../../core/three'; import { toLngLatBounds, toBounds } from '@antv/geo-coord'; -import { sphericalMercator } from '@antv/geo-coord/lib/geo/projection/spherical-mercator'; const r2d = 180 / Math.PI; const tileURLRegex = /\{([zxy])\}/g; -export class Tile { - constructor(layer, z, x, y) { +export default class Tile { + constructor(key, url, layer) { this.layer = layer; - this._tile = [ x, y, z ]; + this._tile = key.split('_').map(v => v * 1); + this._path = url; this._tileLnglatBounds = this._tileLnglatBounds(this._tile); this._tileBounds = this._tileBounds(this._tileLnglatBounds); @@ -16,6 +16,7 @@ export class Tile { this._centerLnglat = this._tileLnglatBounds.getCenter(); this.Object3D = new THREE.Object3D(); + this.requestTileAsync(); } @@ -33,16 +34,19 @@ export class Tile { } // 经纬度范围转瓦片范围 _tileBounds(lnglatBound) { - const nw = sphericalMercator.project(lnglatBound.getTopLeft()); - const se = sphericalMercator.project(lnglatBound.getBottomRight()); - - return toBounds(nw, se); + const ne = this.layer.scene.project([ lnglatBound.getNorthWest().lng, lnglatBound.getNorthEast().lat ]); + const sw = this.layer.scene.project([ lnglatBound.getSouthEast().lng, lnglatBound.getSouthWest().lat ]); + return toBounds(sw, ne); } + getMesh() { + return this.Object3D; + } + // Get tile bounds in WGS84 coordinates _tileLnglatBounds(tile) { - const e = this._tile2lon(tile[0] + 1, tile[2]); - const w = this._tile2lon(tile[0], tile[2]); + const e = this._tile2lng(tile[0] + 1, tile[2]); + const w = this._tile2lng(tile[0], tile[2]); const s = this._tile2lat(tile[1] + 1, tile[2]); const n = this._tile2lat(tile[1], tile[2]); return toLngLatBounds([ w, n ], [ e, s ]); diff --git a/src/layer/tile/tileCache.js b/src/layer/tile/tileCache.js index cd42e03cd1..a96260d16d 100644 --- a/src/layer/tile/tileCache.js +++ b/src/layer/tile/tileCache.js @@ -1,21 +1,16 @@ import LRUCache from '../../util/lru-cache'; export default class TileCache { - constructor(limit = 50) { + constructor(limit = 500) { this._cache = new LRUCache(limit); } - getTile(z, x, y) { - const key = this._generateKey(z, x, y); + getTile(key) { return this._cache.get(key); } - setTile(tile, z, x, y) { - const key = this._generateKey(z, x, y); + setTile(tile, key) { this._cache.set(key, tile); } - _generateKey(z, x, y) { - return [ z, x, y ].join('_'); - } destory() { this._cache.clear(); } diff --git a/src/layer/tile/tileLayer.js b/src/layer/tile/tileLayer.js index c3a6732ce1..dde0de7787 100644 --- a/src/layer/tile/tileLayer.js +++ b/src/layer/tile/tileLayer.js @@ -1,8 +1,117 @@ -import Layer from '../core/layer'; -export class TileLayer extends Layer { +import Layer from '../../core/layer'; +import * as THREE from '../../core/three'; +import TileCache from './tileCache'; +import { toLngLat } from '@antv/geo-coord'; +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(); + this._crs = epsg3857; + this._tiles = new THREE.Object3D(); + this._tileKeys = []; + this.tileList = []; + + + } + source(url) { + this.url = url; + return this; + } + render() { + this._initMapEvent(); + this.draw(); + } draw() { + this._object3D.add(this._tiles); + this._calculateLOD(); } drawTile() { } + zoomchange(ev) { + super.zoomchange(ev); + this._calculateLOD(); + } + dragend(ev) { + super.dragend(ev); + this._calculateLOD(); + + } + _calculateLOD() { + const viewPort = this.scene.getBounds().toBounds(); + const SE = viewPort.getSouthEast(); + const NW = viewPort.getNorthWest(); + const zoom = Math.round(this.scene.getZoom()) - 1; + const NWPonint = this._crs.lngLatToPoint(toLngLat(NW.lng, NW.lat), zoom); + const SEPonint = this._crs.lngLatToPoint(toLngLat(SE.lng, SE.lat), zoom); + const minXY = NWPonint.divideBy(256).round(); + const maxXY = SEPonint.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; + for (let i = minXY.x - halfx; i < maxXY.x + halfx; i++) { + for (let j = minXY.y - halfy; j < maxXY.y + halfy; j++) { + const key = [ i, j, zoom ].join('_'); + this.tileList.push(key); + if (this._tileKeys.indexOf(key) === -1) { + updateTileList.push(key); + } + } + } + // 过滤掉已经存在的 + // tileList = tileList.filter(tile => { + // }) + updateTileList = updateTileList.sort((a, b) => { + const tile1 = a.split('_'); + const tile2 = b.split('_'); + const d1 = Math.pow((tile1[0] - halfx), 2) + Math.pow((tile1[1] - halfy)); + const d2 = Math.pow((tile2[0] - halfy), 2) + Math.pow((tile2[1] - halfy)); + return d1 - d2; + }); + updateTileList.forEach(key => { + this._requestTile(key, this); + }); + this._removeOutTiles(); + } + _requestTile(key, layer) { + 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); + this._tileKeys.push(key); + // this.scene._engine.update(); + } + 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); + } + this._tileKeys = [].concat(this.tileList); + } + } + _removeTiles() { + if (!this._tiles || !this._tiles.children) { + return; + } + + for (let i = this._tiles.children.length - 1; i >= 0; i--) { + this._tiles.remove(this._tiles.children[i]); + } + } + _destroyTile() { + + } + desttroy() { + } } diff --git a/src/map/AMap.js b/src/map/AMap.js index 8ac662f838..d5bf7aae89 100644 --- a/src/map/AMap.js +++ b/src/map/AMap.js @@ -103,6 +103,7 @@ export default class GaodeMap extends Base { } mixMap(scene) { const map = this.map; + scene.project = GaodeMap.project; scene.getZoom = () => { return map.getZoom(); }; diff --git a/test/unit/layer/tile/tile-layer-spec.js b/test/unit/layer/tile/tile-layer-spec.js new file mode 100644 index 0000000000..b492aa577f --- /dev/null +++ b/test/unit/layer/tile/tile-layer-spec.js @@ -0,0 +1,25 @@ +import { expect } from 'chai'; +import {Scene} from '../../../../src/core/scene'; +import TileLayer from '../../../../src/layer/tile/tileLayer'; + +describe('tile layer', function() { + + const amapscript = document.createElement('script'); + amapscript.type = 'text/javascript'; + amapscript.src = 'https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D'; + document.body.appendChild(amapscript); + const div = document.createElement('div'); + div.id = 'map'; + div.style.cssText = 'width:500px;height:500px;position:absolute'; + document.body.appendChild(div); + const scene = new Scene({ + id: 'map', + mapStyle: 'light', // 样式URL + center: [ 120.19382669582967, 30.258134 ], + pitch: 0, + zoom: 2, + maxZoom: 20, + minZoom: 0 + }); + // const TileLayer = new TileLayer(null, {}); +}); From 3ce76c93c1381bc22cbcf77fe72f11634582c053 Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Fri, 19 Apr 2019 11:51:22 +0800 Subject: [PATCH 3/6] fix test --- test/unit/layer/tile/tile-layer-spec.js | 46 ++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/test/unit/layer/tile/tile-layer-spec.js b/test/unit/layer/tile/tile-layer-spec.js index b492aa577f..060127bb11 100644 --- a/test/unit/layer/tile/tile-layer-spec.js +++ b/test/unit/layer/tile/tile-layer-spec.js @@ -1,25 +1,25 @@ -import { expect } from 'chai'; -import {Scene} from '../../../../src/core/scene'; -import TileLayer from '../../../../src/layer/tile/tileLayer'; +// import { expect } from 'chai'; +// import {Scene} from '../../../../src/core/scene'; +// import TileLayer from '../../../../src/layer/tile/tileLayer'; -describe('tile layer', function() { +// describe('tile layer', function() { - const amapscript = document.createElement('script'); - amapscript.type = 'text/javascript'; - amapscript.src = 'https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D'; - document.body.appendChild(amapscript); - const div = document.createElement('div'); - div.id = 'map'; - div.style.cssText = 'width:500px;height:500px;position:absolute'; - document.body.appendChild(div); - const scene = new Scene({ - id: 'map', - mapStyle: 'light', // 样式URL - center: [ 120.19382669582967, 30.258134 ], - pitch: 0, - zoom: 2, - maxZoom: 20, - minZoom: 0 - }); - // const TileLayer = new TileLayer(null, {}); -}); +// const amapscript = document.createElement('script'); +// amapscript.type = 'text/javascript'; +// amapscript.src = 'https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D'; +// document.body.appendChild(amapscript); +// const div = document.createElement('div'); +// div.id = 'map'; +// div.style.cssText = 'width:500px;height:500px;position:absolute'; +// document.body.appendChild(div); +// const scene = new Scene({ +// id: 'map', +// mapStyle: 'light', // 样式URL +// center: [ 120.19382669582967, 30.258134 ], +// pitch: 0, +// zoom: 2, +// maxZoom: 20, +// minZoom: 0 +// }); +// // const TileLayer = new TileLayer(null, {}); +// }); From d5465275a05f85f401d80a48f6fda26844c550e6 Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Wed, 24 Apr 2019 09:44:03 +0800 Subject: [PATCH 4/6] fix(source): geojson parser filter invalid --- src/source/parser/geojson.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/source/parser/geojson.js b/src/source/parser/geojson.js index 791dd2de0d..0e7d4de3f1 100644 --- a/src/source/parser/geojson.js +++ b/src/source/parser/geojson.js @@ -3,6 +3,10 @@ import { getCoords } from '@turf/invariant'; export default function geoJSON(data) { const resultData = []; + 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); From 9c14140314efba28d2f3778250c73d5aad65535c Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Mon, 6 May 2019 11:54:32 +0800 Subject: [PATCH 5/6] fix tile layer caculate tile lod --- demos/tile.html | 6 ++-- src/core/layer.js | 2 ++ src/layer/tile/imageTileLayer.js | 1 - src/layer/tile/tile.js | 26 +++++++++++++++- src/layer/tile/tileCache.js | 4 +-- src/layer/tile/tileLayer.js | 51 ++++++++++++++++++++++---------- src/util/lru-cache.js | 5 ++-- 7 files changed, 72 insertions(+), 23 deletions(-) diff --git a/demos/tile.html b/demos/tile.html index bfc4552833..b3ac0aaae2 100644 --- a/demos/tile.html +++ b/demos/tile.html @@ -34,7 +34,9 @@ const scene = new L7.Scene({ }); window.scene = scene; scene.on('loaded', () => { - scene.ImageTileLayer() + scene.ImageTileLayer({ + zIndex:0 + }) .source('http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}') .render(); @@ -48,7 +50,7 @@ scene.on('loaded', () => { .color('pm2_5_24h',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"]) .shape('fill') .style({ - opacity: 0.2 + opacity: 1.0 }) .render(); diff --git a/src/core/layer.js b/src/core/layer.js index 507729b617..9523aa21eb 100644 --- a/src/core/layer.js +++ b/src/core/layer.js @@ -679,6 +679,8 @@ export default class Layer extends Base { } else if (this.type === 'polyline') { offset = 2; + } else if (this.type === 'polygon') { + offset = 1; } this._object3D.position && (this._object3D.position.z = offset * Math.pow(2, 20 - zoom)); if (zoom < minZoom || zoom > maxZoom) { diff --git a/src/layer/tile/imageTileLayer.js b/src/layer/tile/imageTileLayer.js index 5f39e39bf7..5417854b73 100644 --- a/src/layer/tile/imageTileLayer.js +++ b/src/layer/tile/imageTileLayer.js @@ -5,5 +5,4 @@ export default class ImageTileLayer extends TileLayer { _createTile(key, layer) { return new ImageTile(key, this.url, layer); } - } diff --git a/src/layer/tile/tile.js b/src/layer/tile/tile.js index d96c8a69bf..261800150c 100644 --- a/src/layer/tile/tile.js +++ b/src/layer/tile/tile.js @@ -60,7 +60,31 @@ 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))); } - destory() { + 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; + } + child.material.dispose(); + child.material = null; + } + child = null; + } + } + this._object3D = null; } } diff --git a/src/layer/tile/tileCache.js b/src/layer/tile/tileCache.js index a96260d16d..9681b739f5 100644 --- a/src/layer/tile/tileCache.js +++ b/src/layer/tile/tileCache.js @@ -1,7 +1,7 @@ import LRUCache from '../../util/lru-cache'; export default class TileCache { - constructor(limit = 500) { - this._cache = new LRUCache(limit); + constructor(limit = 50, tileDestroy) { + this._cache = new LRUCache(limit, tileDestroy); } getTile(key) { diff --git a/src/layer/tile/tileLayer.js b/src/layer/tile/tileLayer.js index dde0de7787..a3bc44afc9 100644 --- a/src/layer/tile/tileLayer.js +++ b/src/layer/tile/tileLayer.js @@ -1,12 +1,13 @@ import Layer from '../../core/layer'; import * as THREE from '../../core/three'; import TileCache from './tileCache'; +import { throttle } from '@antv/util'; import { toLngLat } from '@antv/geo-coord'; 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(); + this._tileCache = new TileCache(50, this._destroyTile); this._crs = epsg3857; this._tiles = new THREE.Object3D(); this._tileKeys = []; @@ -31,6 +32,7 @@ export default class TileLayer extends Layer { } zoomchange(ev) { super.zoomchange(ev); + throttle(this._calculateLOD, 200); this._calculateLOD(); } dragend(ev) { @@ -43,23 +45,35 @@ export default class TileLayer extends Layer { const SE = viewPort.getSouthEast(); const NW = viewPort.getNorthWest(); const zoom = Math.round(this.scene.getZoom()) - 1; - const NWPonint = this._crs.lngLatToPoint(toLngLat(NW.lng, NW.lat), zoom); - const SEPonint = this._crs.lngLatToPoint(toLngLat(SE.lng, SE.lat), zoom); - const minXY = NWPonint.divideBy(256).round(); - const maxXY = SEPonint.divideBy(256).round(); + 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; - for (let i = minXY.x - halfx; i < maxXY.x + halfx; i++) { - for (let j = minXY.y - halfy; j < maxXY.y + halfy; j++) { - const key = [ i, j, zoom ].join('_'); - this.tileList.push(key); - if (this._tileKeys.indexOf(key) === -1) { - updateTileList.push(key); + 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); } } + 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 => { @@ -67,8 +81,8 @@ export default class TileLayer extends Layer { updateTileList = updateTileList.sort((a, b) => { const tile1 = a.split('_'); const tile2 = b.split('_'); - const d1 = Math.pow((tile1[0] - halfx), 2) + Math.pow((tile1[1] - halfy)); - const d2 = Math.pow((tile2[0] - halfy), 2) + Math.pow((tile2[1] - halfy)); + 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 => { @@ -76,6 +90,13 @@ export default class TileLayer extends Layer { }); this._removeOutTiles(); } + _updateTileList(updateTileList, x, y, z) { + const key = [ x, y, z ].join('_'); + this.tileList.push(key); + if (this._tileKeys.indexOf(key) === -1) { + updateTileList.push(key); + } + } _requestTile(key, layer) { let tile = this._tileCache.getTile(key); if (!tile) { @@ -109,8 +130,8 @@ export default class TileLayer extends Layer { this._tiles.remove(this._tiles.children[i]); } } - _destroyTile() { - + _destroyTile(tile) { + tile.destroy(); } desttroy() { } diff --git a/src/util/lru-cache.js b/src/util/lru-cache.js index 8b417e53e2..ab7a78339b 100644 --- a/src/util/lru-cache.js +++ b/src/util/lru-cache.js @@ -6,9 +6,9 @@ */ export default class LRUCache { - constructor(limit = 5) { + constructor(limit = 50, destroy = () => {}) { this.limit = limit; - + this.destroy = destroy; this.clear(); } @@ -48,6 +48,7 @@ export default class LRUCache { delete(key) { const value = this._cache[key]; + this.destroy(value); if (value) { this._deleteCache(key); this._deleteOrder(key); From 6ba7f07c7d1d0f11d280dc5a049dca6e75f31ea2 Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Mon, 6 May 2019 13:57:09 +0800 Subject: [PATCH 6/6] fix(scene): render --- src/core/scene.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/scene.js b/src/core/scene.js index 637cf59690..0789516806 100644 --- a/src/core/scene.js +++ b/src/core/scene.js @@ -25,10 +25,9 @@ export default class Scene extends Base { _initEngine(mapContainer) { this._engine = new Engine(mapContainer, this); - // this.registerMapEvent(); + this.registerMapEvent(); // this.workerPool = new WorkerPool(); compileBuiltinModules(); - this._engine.run(); } // 为pickup场景添加 object 对象 addPickMesh(object) {