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, {});
+});