diff --git a/demos/01_point_circle.html b/demos/01_point_circle.html index 62f8e26010..f062d98a56 100644 --- a/demos/01_point_circle.html +++ b/demos/01_point_circle.html @@ -91,6 +91,9 @@ scene.on('loaded', () => { }) .render(); + setTimeout(()=>{ + scene.setMapStyle('grey'); + },2000) }); }); diff --git a/demos/assets/bezier.js b/demos/assets/bezier.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/demos/line.html b/demos/line.html index 8583dbfc0d..c851668170 100644 --- a/demos/line.html +++ b/demos/line.html @@ -31,59 +31,47 @@ var buildLayer =null; const scene = new L7.Scene({ id: 'map', - mapStyle: 'amap://styles/c9f1d10cae34f8ab05e425462c5a58d7', // 样式URL - center: [120.102915,30.261396], + mapStyle: 'normal', // 样式URL + center: [120.1998700000, 30.2638300000], pitch: 0, - zoom: 12, + zoom: 14, minZoom: 5, maxZoom: 18 }); scene.on('loaded', () => { - $.get('https://gw.alipayobjects.com/os/basement_prod/a0f3363f-4f95-4145-9161-cca6b9134277.json',(data)=>{ - let startTime = 3600 * 6; - const interval = 3600; - const mapData = { - "type": "FeatureCollection", - "features": [] - }; - mapData.features = data.features.filter((feature)=>{ - const time = feature.properties.time; - const type = feature.properties.type - return time >= startTime && time <= (startTime + interval) - - }) - const linelayer = scene.LineLayer({ - zIndex: 2 - }) - .shape('line') - .size([2,0]) - .source(mapData) - .color('type',function(type){ - return type ==='pjc_end' ? '#2b83ba' :'#d7191c' - }) - .animate({ - enable:true, - interval:0.8, - duration:2, - trailLength:0.2, - }) - .render(); - setInterval(()=>{ - startTime += interval - document.getElementById('timepannel').innerHTML=`时间:${startTime / 3600}时` - mapData.features = data.features.filter((feature)=>{ - const time = feature.properties.time; - const type = feature.properties.type - return time >= startTime && time <= (startTime + interval) - }) - if(startTime == interval * 24) { - startTime = 3600 * 6; - } - //if( mapData.features.length ==0) return; - linelayer.setData(mapData); - - },2000) - }); + const layer = scene.LineLayer({ + zIndex: 3 + }).source([{ + 'x': 120.1998700000, + 'y': 30.2638300000, + 'x1': 119.575328, + 'y1': 30.106775 + }],{ + parser: { + type: 'json', + x: 'x', + y: 'y', + x1: 'x1', + y1: 'y1' + } + }).shape('greatCircle').size(2).color('rgb(13,64,140)').animate({ + enable: false, + interval: 1, + duration: 2, + trailLength: 0.8 + }).style({ + opacity: 1 + }).render() + console.log(layer); + new L7.Marker({ + color: 'red' + }).setLnglat([120.1998700000, 30.2638300000]).addTo(scene); + scene.map.add(new AMap.Marker({ + position: new AMap.LngLat(120.1998700000, 30.2638300000), + // icon: icon, // 添加 Icon 实例 + zoom: 13, + //offset: new AMap.Pixel(-0.2 * this.rem, -0.4 * this.rem) + })) }) diff --git a/demos/marker.html b/demos/marker.html index 0cd4187f5e..6735978198 100644 --- a/demos/marker.html +++ b/demos/marker.html @@ -48,7 +48,17 @@ .render(); }); $.getJSON('https://gw.alipayobjects.com/os/basement_prod/0b96cca4-7e83-449a-93d0-2a77053e74ab.json', function(data) { - console.log(data); + scene.PointLayer() + .source(data.nodes,{ + parser:{ + type:'json', + coordinates:'coordinates', + } + }) + .shape('circle') + .color('#f00') + .size(8) + .render(); data.nodes.forEach(item=>{ const el = document.createElement('div'); const total = item.gdp.Agriculture + item.gdp.Industry + item.gdp.Service; diff --git a/demos/world.html b/demos/world.html new file mode 100644 index 0000000000..4baccf9adb --- /dev/null +++ b/demos/world.html @@ -0,0 +1,162 @@ + + + + + + + + + + + hexagon demo + + + + +
+ + + + + + + + + diff --git a/package.json b/package.json index 0b12b2ad36..017a9f20b8 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@antv/l7", - "version": "1.3.4", + "version": "1.3.5-beta.1", "description": "Large-scale WebGL-powered Geospatial Data Visualization", "main": "build/L7.js", "homepage": "https://github.com/antvis/l7", diff --git a/src/component/control/attribution.js b/src/component/control/attribution.js index 8a24e5485c..10d0268271 100644 --- a/src/component/control/attribution.js +++ b/src/component/control/attribution.js @@ -10,7 +10,6 @@ export default class Attribution extends Control { this._attributions = {}; } onAdd(scene) { - scene.attributionControl = this; this._container = DOM.create('div', 'l7-control-attribution'); const layers = scene.getLayers(); for (const i in layers) { diff --git a/src/component/css/l7.css b/src/component/css/l7.css index 3ec20e6494..3a9235ef55 100644 --- a/src/component/css/l7.css +++ b/src/component/css/l7.css @@ -1,5 +1,5 @@ .l7-marker { - position: absolute; + position: absolute !important; top: 0; left: 0; z-index: 5; diff --git a/src/component/marker.js b/src/component/marker.js index 753f09c702..4f8ad16001 100644 --- a/src/component/marker.js +++ b/src/component/marker.js @@ -6,7 +6,7 @@ export default class Marker extends Base { constructor(cfg) { super({ element: '', // DOM element - anchor: 'center', + anchor: 'bottom', offset: [ 0, 0 ], color: '#2f54eb', draggable: false, diff --git a/src/component/popup.js b/src/component/popup.js index 1de80ff6f4..7066821ddd 100644 --- a/src/component/popup.js +++ b/src/component/popup.js @@ -23,6 +23,7 @@ export default class Popup extends Base { this._scene.on('click', this._onClickClose); }, 30); } + return this; } setLnglat(lngLat) { this.lngLat = lngLat; diff --git a/src/core/engine/composer.js b/src/core/engine/composer.js index 0575cfe3f2..168550839a 100755 --- a/src/core/engine/composer.js +++ b/src/core/engine/composer.js @@ -5,6 +5,7 @@ import * as THREE from '../three'; import CopyShader from './copy-shader'; import ShaderPass from './shader-pass'; import MaskPass, {ClearMaskPass} from './mask-pass'; +import { destoryObject } from '../../util/object3d-util'; /** * @author alteredq / http://alteredqualia.com/ @@ -142,6 +143,10 @@ EffectComposer.prototype = { this.renderTarget1.setSize( width, height ); this.renderTarget2.setSize( width, height ); + }, + destory: function () { + this.renderTarget1.dispose(); + this.renderTarget2.dispose(); } }; diff --git a/src/core/engine/index.js b/src/core/engine/index.js index 5a379e0778..19bf7f77dd 100644 --- a/src/core/engine/index.js +++ b/src/core/engine/index.js @@ -4,6 +4,7 @@ import Scene from './scene'; import Camera from './camera'; import Renderer from './renderer'; import Picking from './picking/picking'; +import { destoryObject } from '../../util/object3d-util'; export default class Engine extends EventEmitter { constructor(container, world) { super(); @@ -29,6 +30,18 @@ export default class Engine extends EventEmitter { this._initPostProcessing(); } destroy() { + destoryObject(this._scene); + this.composerLayers.forEach(layer => { + layer.distory(); + }); + destoryObject(this.composerLayers); + + this._picking.destroy(); + this._picking = null; + this._world = null; + this.clock = null; + this._camera = null; + this._renderer = null; } // 渲染第三方Scene对象 renderScene(scene) { diff --git a/src/core/engine/picking/picking.js b/src/core/engine/picking/picking.js index 0abebbf4cf..141839a2d3 100755 --- a/src/core/engine/picking/picking.js +++ b/src/core/engine/picking/picking.js @@ -1,5 +1,6 @@ import PickingScene from './pickingScene'; import * as THREE from '../../three'; +import { destoryObject } from '../../../util/object3d-util'; let nextId = 1; class Picking { @@ -136,32 +137,7 @@ class Picking { // TODO: Find a way to properly remove these listeners as they stay // active at the moment window.removeEventListener('resize', this._resizeHandler, false); - this._envents.forEach(event => { - this._world._container.removeEventListener(event[0], event[1], false); - }); - - if (this._pickingScene.children) { - // Remove everything else in the layer - let child; - for (let i = this._pickingScene.children.length - 1; i >= 0; i--) { - child = this._pickingScene.children[i]; - - if (!child) { - continue; - } - - this._pickingScene.remove(child); - if (child.material) { - if (child.material.map) { - child.material.map.dispose(); - child.material.map = null; - } - - child.material.dispose(); - child.material = null; - } - } - } + destoryObject(this._pickingScene); this._pickingScene = null; this._pickingTexture = null; diff --git a/src/core/scene.js b/src/core/scene.js index 09dee07f13..f93186b937 100644 --- a/src/core/scene.js +++ b/src/core/scene.js @@ -11,6 +11,7 @@ import Style from './style'; import Controller from './controller/control'; import * as Control from '../component/control'; import { epsg3857 } from '@antv/geo-coord/lib/geo/crs/crs-epsg3857'; +const EventNames = [ 'mouseout', 'mouseover', 'mousemove', 'mousedown', 'mouseleave', 'mouseleave', 'mouseleave', 'touchstart', 'touchmove', 'touchend', 'mouseup', 'rightclick', 'click', 'dblclick' ]; export default class Scene extends Base { getDefaultCfg() { return Global.scene; @@ -22,7 +23,6 @@ export default class Scene extends Base { this.fontAtlasManager = new FontAtlasManager(); this._layers = []; this.animateCount = 0; - this.inited = false; } _initEngine(mapContainer) { @@ -142,26 +142,17 @@ export default class Scene extends Base { } _registEvents() { - const events = [ - 'mouseout', - 'mouseover', - 'mousemove', - 'mousedown', - 'mouseleave', - 'touchstart', - 'touchmove', - 'touchend', - 'mouseup', - 'rightclick', - 'click', - 'dblclick' - ]; - events.forEach(event => { - this._container.addEventListener(event, e => { - // 要素拾取 - if (e.target.nodeName !== 'CANVAS') return; - this._engine._picking.pickdata(e); - }, true); + this._eventHander = e => { + if (e.target.nodeName !== 'CANVAS') return; + this._engine._picking.pickdata(e); + }; + EventNames.forEach(event => { + this._container.addEventListener(event, this._eventHander, true); + }); + } + _unRegistEvents() { + EventNames.forEach(event => { + this._container.removeEventListener(event, this._eventHander, true); }); } @@ -172,6 +163,7 @@ export default class Scene extends Base { } layer.destroy(); layer = null; + this._engine.update(); } startAnimate() { if (this.animateCount === 0) { @@ -194,12 +186,14 @@ export default class Scene extends Base { // this.map.on('mousemove', this._updateRender); this.map.on('mapmove', this._updateRender); this.map.on('camerachange', this._updateRender); + window.addEventListener('onresize', this._updateRender); } unRegsterMapEvent() { // this.map.off('mousemove', this._updateRender); this.map.off('mapmove', this._updateRender); this.map.off('camerachange', this._updateRender); + window.removeEventListener('onresize', this._updateRender); } // control @@ -211,4 +205,25 @@ export default class Scene extends Base { removeControl(ctr) { this.get('controlController').removeControl(ctr); } + render() { + this._engine.update(); + } + destroy() { + super.destroy(); + this._layers.forEach(layer => { + layer.destroy(); + }); + this._layers.length = 0; + this.image = null; + this.fontAtlasManager = null; + this.style.destroy(); + this.style = null; + this._engine.destroy(); + this._engine = null; + this.map.destroy(); + this.unRegsterMapEvent(); + this._unRegistEvents(); + + + } } diff --git a/src/core/style.js b/src/core/style.js index 79db3db3b3..eb60abe620 100644 --- a/src/core/style.js +++ b/src/core/style.js @@ -87,6 +87,10 @@ export default class Style extends Base { this.scene.map.off('zoomchange', this.mapEventHander); this.scene.map.off('dragend', this.mapEventHander); } + destroy() { + this.WorkerController.remove(); + + } // 计算视野内的瓦片坐标 } diff --git a/src/geom/material/lineMaterial.js b/src/geom/material/lineMaterial.js index b4f891ecba..ccf5584764 100644 --- a/src/geom/material/lineMaterial.js +++ b/src/geom/material/lineMaterial.js @@ -2,7 +2,6 @@ import * as THREE from '../../core/three'; import Material from './material'; import { getModule, wrapUniforms } from '../../util/shaderModule'; import merge from '@antv/util/lib/deep-mix'; - export function LineMaterial(options) { const { vs, fs } = getModule('line'); const material = new Material({ @@ -15,11 +14,12 @@ export function LineMaterial(options) { }, vertexShader: vs, fragmentShader: fs, - transparent: true - // blending: THREE.AdditiveBlending + transparent: true, + blending: THREE[Material.blendingEnum[options.blending]] }); return material; } +// 弧线绘制 大圆航线 3D弧线 export function ArcLineMaterial(options) { let moduleName = 'arcline'; if (options.shapeType === 'greatCircle') { @@ -29,7 +29,7 @@ export function ArcLineMaterial(options) { const material = new Material({ uniforms: wrapUniforms(merge(uniforms, { u_opacity: options.u_opacity, - segmentNumber: 29, + segmentNumber: 30, u_time: 0, u_zoom: options.u_zoom, u_activeId: options.activeId, @@ -38,8 +38,8 @@ export function ArcLineMaterial(options) { vertexShader: vs, fragmentShader: fs, transparent: true, - blending: THREE.AdditiveBlending, - side: THREE.DoubleSide + side: THREE.DoubleSide, + blending: THREE[Material.blendingEnum[options.blending]] }); return material; } @@ -55,7 +55,6 @@ export function MeshLineMaterial(options, defines) { vertexShader: vs, fragmentShader: fs, transparent: true - // blending: THREE.AdditiveBlending }); return material; } diff --git a/src/geom/material/material.js b/src/geom/material/material.js index 11b1b0dccd..e82331cf88 100644 --- a/src/geom/material/material.js +++ b/src/geom/material/material.js @@ -1,11 +1,13 @@ import * as THREE from '../../core/three'; -const blendingEnum = { - normal: 'NormalBlending', - additive: 'AdditiveBlending', - subtractive: 'SubtractiveBlending' -}; + + export default class Material extends THREE.ShaderMaterial { + static blendingEnum = { + normal: 'NormalBlending', + additive: 'AdditiveBlending', + subtractive: 'SubtractiveBlending' + } setUniformsValue(name, value) { if (!this.uniforms[name]) { return; } this.uniforms[name].value = value; @@ -32,6 +34,6 @@ export default class Material extends THREE.ShaderMaterial { } } setBending(type) { - this.blending = THREE[blendingEnum[type]] || THREE.NormalBlending; + this.blending = THREE[this.blendingEnum[type]] || THREE.NormalBlending; } } diff --git a/src/geom/material/pointMaterial.js b/src/geom/material/pointMaterial.js index 8c12415268..7627a82c1a 100644 --- a/src/geom/material/pointMaterial.js +++ b/src/geom/material/pointMaterial.js @@ -27,7 +27,6 @@ export default class PointMaterial extends Material { this.vertexShader = vs; this.fragmentShader = fs; this.transparent = true; - if (!this.uniforms.shape) { this.blending = THREE.AdditiveBlending; } if (this.uniforms.u_texture) { this.defines.TEXCOORD_0 = true; diff --git a/src/geom/shader/great_circle_line_vert.glsl b/src/geom/shader/great_circle_line_vert.glsl index 4043db6263..97ee35a476 100644 --- a/src/geom/shader/great_circle_line_vert.glsl +++ b/src/geom/shader/great_circle_line_vert.glsl @@ -19,7 +19,7 @@ float maps (float value, float start1, float stop1, float start2, float stop2) { } float getSegmentRatio(float index) { - return smoothstep(0.0, 1.0, index / (segmentNumber - 1.0)); + return smoothstep(0.0, 1.0, index / (segmentNumber - 1.)); } float paraboloid(vec2 source, vec2 target, float ratio) { diff --git a/src/layer/render/line/drawArc.js b/src/layer/render/line/drawArc.js index 739882fe3a..8ab9ba2ae4 100644 --- a/src/layer/render/line/drawArc.js +++ b/src/layer/render/line/drawArc.js @@ -1,6 +1,7 @@ import * as THREE from '../../../core/three'; import { ArcLineMaterial } from '../../../geom/material/lineMaterial'; import { getBuffer } from '../../../geom/buffer/'; + export default function DrawArcLine(layerData, layer, buffer) { const style = layer.get('styleOptions'); const activeOption = layer.get('activedOptions'); @@ -47,7 +48,6 @@ export default function DrawArcLine(layerData, layer, buffer) { u_trailLength: trailLength }); lineMaterial.setDefinesvalue('ANIMATE', true); - // lineMaterial.setDefinesvalue('DASHLINE', true); } const arcMesh = new THREE.Mesh(geometry, lineMaterial); arcMesh.frustumCulled = false; diff --git a/src/layer/render/text/drawText.js b/src/layer/render/text/drawText.js index 05283d5e4d..ecd555602d 100644 --- a/src/layer/render/text/drawText.js +++ b/src/layer/render/text/drawText.js @@ -1,7 +1,6 @@ import * as THREE from '../../../core/three'; import TextMaterial from '../../../geom/material/textMaterial'; import TextBuffer from '../../../geom/buffer/point/text'; -import ColorUtil from '../../../attr/color-util'; import CollisionIndex from '../../../util/collision-index'; const defaultTextStyle = { fontWeight: 500, @@ -21,7 +20,6 @@ export default function DrawText(layerData, layer) { layer.set('styleOptions', style); const activeOption = layer.get('activedOptions'); const { strokeWidth, stroke, opacity } = style; - const { width, height } = layer.scene.getSize(); const { geometry, texture, fontAtlas } = _updateGeometry(layerData, layer); layer.scene.on('camerachange', () => { @@ -34,7 +32,7 @@ export default function DrawText(layerData, layer) { const material = new TextMaterial({ name: layer.layerId, u_sdf_map: texture, - u_stroke: ColorUtil.toRGB(stroke).map(e => e / 255), + u_stroke: stroke, u_strokeWidth: strokeWidth, u_halo_blur: 0.5, u_opacity: opacity, @@ -43,7 +41,6 @@ export default function DrawText(layerData, layer) { u_activeColor: activeOption.fill }); const mesh = new THREE.Mesh(geometry, material); - // 更新 viewport window.addEventListener('resize', () => { const { width, height } = layer.scene.getSize(); diff --git a/src/map/AMap.js b/src/map/AMap.js index 9be11dff5d..f1fb6c9d8a 100644 --- a/src/map/AMap.js +++ b/src/map/AMap.js @@ -35,21 +35,21 @@ export default class GaodeMap extends Base { initMap() { const mapStyle = this.get('mapStyle'); - // if (mapStyle) { - // switch (mapStyle) { - // case 'dark': - // this.set('mapStyle', Theme.DarkTheme.mapStyle); - // break; - // case 'light': - // this.set('mapStyle', Theme.LightTheme.mapStyle); - // break; - // case 'blank': - // this.set('mapStyle', 'blank'); - // break; - // default: - // this.set('mapStyle', mapStyle); - // } - // } + if (mapStyle) { + switch (mapStyle) { + case 'dark': + this.set('mapStyle', Theme.darkTheme.mapStyle); + break; + case 'light': + this.set('mapStyle', Theme.lightTheme.mapStyle); + break; + case 'blank': + this.set('mapStyle', Theme.blankTheme.mapStyle); + break; + default: + this.set('mapStyle', mapStyle); + } + } this.set('zooms', [ this.get('minZoom'), this.get('maxZoom') ]); const map = this.get('map'); if (map instanceof AMap.Map) { @@ -110,7 +110,7 @@ export default class GaodeMap extends Base { this.amapContainer = this.map.getContainer().getElementsByClassName('amap-maps')[0]; this.renderDom = document.createElement('div'); this.renderDom.style.cssText += - 'position: absolute;top: 0; z-index:1;height: 100%;width: 100%;pointer-events: none;'; + 'position: absolute;top: 0;height: 100%;width: 100%;pointer-events: none;'; this.renderDom.id = 'l7_canvaslayer'; this.amapContainer.appendChild(this.renderDom); @@ -122,10 +122,13 @@ export default class GaodeMap extends Base { const map = this.map; switch (style) { case 'dark': - this.set('mapStyle', Theme.DarkTheme.mapStyle); + this.set('mapStyle', Theme.darkTheme.mapStyle); break; case 'light': - this.set('mapStyle', Theme.LightTheme.mapStyle); + this.set('mapStyle', Theme.lightTheme.mapStyle); + break; + case 'blank': + this.set('mapStyle', Theme.blankTheme.mapStyle); break; default: this.set('mapStyle', style); @@ -134,7 +137,8 @@ export default class GaodeMap extends Base { map.setMapStyle(this.get('mapStyle')); if (style === 'blank') { map.setFeatures([]); - } else { + } else + if (map.getFeatures().length === 0) { map.setFeatures(defaultMapFeatures); } return; diff --git a/src/theme/blank.js b/src/theme/blank.js new file mode 100644 index 0000000000..307b79c0bf --- /dev/null +++ b/src/theme/blank.js @@ -0,0 +1,4 @@ +const BlankTheme = { + mapStyle: 'amap://styles/07c17002b38775b32a7a76c66cf90e99?isPublic=true' +}; +export default BlankTheme; diff --git a/src/theme/index.js b/src/theme/index.js index 7b4cd3a988..46b7c454e1 100644 --- a/src/theme/index.js +++ b/src/theme/index.js @@ -1,3 +1,4 @@ -import DarkTheme from './dark'; -import LightTheme from './light'; -export { DarkTheme, LightTheme }; +import darkTheme from './dark'; +import lightTheme from './light'; +import blankTheme from './blank'; +export { darkTheme, lightTheme, blankTheme }; diff --git a/src/worker/actor.js b/src/worker/actor.js index 14a2923f91..6b82fab7a0 100644 --- a/src/worker/actor.js +++ b/src/worker/actor.js @@ -72,4 +72,7 @@ export default class Actor { } } + remove() { + this.target.removeEventListener('message', this.receive, false); + } }