diff --git a/demos/01_point_circle.html b/demos/01_point_circle.html index 2b66ddd6a2..bb80671de8 100644 --- a/demos/01_point_circle.html +++ b/demos/01_point_circle.html @@ -35,7 +35,9 @@ const scene = new L7.Scene({ mapStyle: 'light', // 样式URL center: [ 120.19382669582967, 30.258134 ], pitch: 0, - zoom: 12 + zoom: 12, + maxZoom:14, + minZoom:11, }); window.scene = scene; scene.on('loaded', () => { @@ -53,7 +55,7 @@ scene.on('loaded', () => { .shape('2d:circle') .size('value', [ 2, 80]) // default 1 //.size('value', [ 10, 300]) // default 1 - .active(true) + .active(false) .filter('value', field_8 => { return field_8 * 1 > 500; }) @@ -65,7 +67,9 @@ scene.on('loaded', () => { }) .render(); - + circleLayer.on('click',(e)=>{ + console.log(e); + }) }); }); diff --git a/demos/01_point_column.html b/demos/01_point_column.html index 354c58a316..8e1abda83c 100644 --- a/demos/01_point_column.html +++ b/demos/01_point_column.html @@ -38,7 +38,7 @@ scene.on('loaded', () => { x: 'j', y: 'w', }) - .shape('3d:circle') + .shape('cylinder') .size('t',(level)=> { return [2,2,(level*3+20)]; }) diff --git a/demos/02_oneBletoneRoad.html b/demos/02_oneBletoneRoad.html index c7a5f17796..ab9528f2a5 100644 --- a/demos/02_oneBletoneRoad.html +++ b/demos/02_oneBletoneRoad.html @@ -29,8 +29,6 @@ const scene = new L7.Scene({ scene.on('loaded', () => { scene.image.addImage('local', 'https://gw.alipayobjects.com/zos/rmsportal/xZXhTxbglnuTmZEwqQrE.png'); - - $.getJSON('https://gw.alipayobjects.com/os/rmsportal/UpapMomPYUeiBjbHNAma.json', region => { const color = [ 'rgb(22,32,101)', 'rgb(28,43,127)', 'rgb(36,68,142)', 'rgb(45,94,158)', 'rgb(53,119,174)', 'rgb(61,145,190)', 'rgb(70,170,206)', 'rgb(98,190,210)', 'rgb(138,205,206)', 'rgb(179,221,204)', 'rgb(220,236,201)' ]; var points = region.features.map((feature)=>{ @@ -70,7 +68,7 @@ $.getJSON('https://gw.alipayobjects.com/os/rmsportal/dzpMOiLYBKxpdmsgBLoE.json', .size([ 1.5, 0 ]) .shape('line') .style({ - // 'lineType':'solid' + 'lineType':'dash' }) .render(); }); diff --git a/demos/03_choropleths_polygon.html b/demos/03_choropleths_polygon.html index 130c79ac28..832066b226 100644 --- a/demos/03_choropleths_polygon.html +++ b/demos/03_choropleths_polygon.html @@ -86,6 +86,7 @@ scene.on('loaded', () => { opacity: 1 }) .render(); + /** const citylayer2 = scene.PolygonLayer() .source(city) .shape('line') @@ -93,7 +94,8 @@ scene.on('loaded', () => { .style({ opacity: 0.1 }) - .render(); + // .render(); + **/ citylayer.on('click',(e)=>{ $("#info").css({'left': e.pixel.x,'top':e.pixel.y, display:'block'}); diff --git a/demos/06_text.html b/demos/06_text.html index 37a66ba9d1..52c44ea774 100644 --- a/demos/06_text.html +++ b/demos/06_text.html @@ -35,7 +35,7 @@ scene.on('loaded', () => { }) .source(data) .shape('name', 'text') - .size(10) // default 1 + .size(12) // default 1 .color('#fff') .style({ stroke: '#999', diff --git a/demos/07_city.html b/demos/07_city.html index 70dd134c51..032dfe9bcc 100644 --- a/demos/07_city.html +++ b/demos/07_city.html @@ -38,6 +38,7 @@ scene.on('loaded', () => { }) .source(data) .shape('fill') + .active({fill:'blue'}) .color('rgb(79,174,234)') .render(); }); @@ -71,10 +72,12 @@ scene.on('loaded', () => { .size('floor',[10,2000]) .color('rgba(242,246,250,0.96)') .render(); + /** citylayer.on('click',(e)=>{ $("#info").css({'left': e.pixel.x,'top':e.pixel.y, display:'block'}); $("#info").html(`

楼高${e.feature.properties.floor || 0}

`); }) + **/ }); }); diff --git a/demos/line.html b/demos/line.html new file mode 100644 index 0000000000..6f7f23c30b --- /dev/null +++ b/demos/line.html @@ -0,0 +1,85 @@ + + + + + + + + + city demo + + + + +
+
+ + + + + + + + diff --git a/demos/point.html b/demos/point.html new file mode 100644 index 0000000000..9769b40f3c --- /dev/null +++ b/demos/point.html @@ -0,0 +1,57 @@ + + + + + + + + + point_circle + + + + +
+ + + + + + + + diff --git a/demos/taxi.html b/demos/taxi.html index a7e8f0fc40..d8ea264443 100644 --- a/demos/taxi.html +++ b/demos/taxi.html @@ -41,7 +41,7 @@ scene.on('loaded', () => { .animate({enable:true}) .render(); }); - $.get('./data/2.geojson', data => { + $.get('https://gw.alipayobjects.com/os/rmsportal/vmvAxgsEwbpoSWbSYvix.json', data => { buildLayer = scene.PolygonLayer({ zIndex: 2 }) diff --git a/package.json b/package.json index 816c18fbbc..6b9922ad1a 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@antv/l7", - "version": "1.0.0", + "version": "1.0.1", "description": "Large-scale WebGL-powered Geospatial Data Visualization", "main": "build/l7.js", "browser": "build/l7.js", diff --git a/src/core/engine/picking/picking.js b/src/core/engine/picking/picking.js index 1759a2c367..30832c81da 100755 --- a/src/core/engine/picking/picking.js +++ b/src/core/engine/picking/picking.js @@ -48,12 +48,12 @@ class Picking { // return; // } - const point = { x: event.clientX, y: event.clientY }; + const point = { x: event.clientX, y: event.clientY,type:event.type}; const normalisedPoint = { x: 0, y: 0 }; normalisedPoint.x = (point.x / this._width) * 2 - 1; normalisedPoint.y = -(point.y / this._height) * 2 + 1; - - this._pick(point, normalisedPoint); + this._pickAllObject(point, normalisedPoint); + // this._pick(point, normalisedPoint); } _onWorldMove() { @@ -76,10 +76,10 @@ class Picking { _update(point) { const texture = this._pickingTexture; - if (this._needUpdate) { - this._renderer.render(this._pickingScene, this._camera, this._pickingTexture); - this._needUpdate = false; - } + // if (this._needUpdate) { + this._renderer.render(this._pickingScene, this._camera, this._pickingTexture); + // this._needUpdate = false; + // } this.pixelBuffer = new Uint8Array(4); this._renderer.readRenderTargetPixels(texture, point.x, this._height - point.y, 1, 1, this.pixelBuffer); @@ -99,17 +99,33 @@ class Picking { }); } + _filterObject(id) { + this._pickingScene.children.forEach((object, index) => { + index === id ? object.visible = true : object.visible = false; + }); + } + _pickAllObject(point, normalisedPoint) { + this._pickingScene.children.forEach((object, index) => { + this._filterObject(index); + const item = this._pick(point, normalisedPoint, object.name); + item.type = point.type; + this._world.emit('pick', item); + this._world.emit('pick-' + object.name, item); + + }); + } _updateRender() { this._renderer.render(this._pickingScene, this._camera, this._pickingTexture); } - _pick(point, normalisedPoint) { + _pick(point, normalisedPoint, layerId) { this._update(point); // Interpret the pixel as an ID - const id = (this.pixelBuffer[2] * 255 * 255) + (this.pixelBuffer[1] * 255) + (this.pixelBuffer[0]); + let id = (this.pixelBuffer[2] * 255 * 255) + (this.pixelBuffer[1] * 255) + (this.pixelBuffer[0]); // Skip if ID is 16646655 (white) as the background returns this if (id === 16646655 || this.pixelBuffer[3] === 0) { - return; + id = -999; + // return; } this._raycaster.setFromCamera(normalisedPoint, this._camera); @@ -118,7 +134,6 @@ class Picking { // // TODO: Only perform intersection test on the relevant picking mesh const intersects = this._raycaster.intersectObjects(this._pickingScene.children, true); - const _point2d = { x: point.x, y: point.y }; let _point3d; @@ -131,13 +146,14 @@ class Picking { // // TODO: Look into the leak potential for passing so much by reference here const item = { + layerId, featureId: id - 1, point2d: _point2d, point3d: _point3d, intersects }; - this._world.emit('pick', item); - // this._world.emit('pick-' + id, _point2d, _point3d, intersects); + return item + } // Add mesh to picking scene diff --git a/src/core/image.js b/src/core/image.js index 60482885c0..845053d977 100644 --- a/src/core/image.js +++ b/src/core/image.js @@ -5,30 +5,32 @@ import { getImage } from '../util/ajax'; export default class LoadImage extends EventEmitter { constructor() { super(); - this.imageWidth = 64; + const pixelRatio = window.devicePixelRatio || 1; + this.imageWidth = 64 * pixelRatio; this.canvas = document.createElement('canvas'); this.canvas.style.cssText += 'height: 512px;width: 512px;'; this.canvas.width = this.imageWidth * 8; this.canvas.height = this.imageWidth * 8; this.ctx = this.canvas.getContext('2d'); - - this.images = []; this.imagesCount = 0; this.imagePos = {}; + this.imagesIds = []; } addImage(id, opt) { this.imagesCount ++; + this.imagesIds.push(id); const imageCount = this.imagesCount; - const x = imageCount % 8 * 64; - const y = parseInt(imageCount / 8) * 64; - this.imagePos[id] = { x: x / 512, y: y / 512 }; + const x = imageCount % 8 * this.imageWidth; + const y = parseInt(imageCount / 8) * this.imageWidth; + this.imagePos[id] = { x: x / this.canvas.width, y: y / this.canvas.height }; this.texture = new THREE.Texture(this.canvas); if (typeof opt === 'string') { getImage({ url: opt }, (err, img) => { img.id = id; + this.images.push(img); - this.ctx.drawImage(img, x, y, 64, 64); + this.ctx.drawImage(img, x, y, this.imageWidth, this.imageWidth); this.texture.magFilter = THREE.LinearFilter; this.texture.minFilter = THREE.LinearFilter; @@ -47,7 +49,7 @@ export default class LoadImage extends EventEmitter { image.data = data; image.id = id; this.images.push(image); - this.ctx.drawImage(image, x, y, 64, 64); + this.ctx.drawImage(image, x, y, this.imageWidth, this.imageWidth); this.texture = new THREE.CanvasTexture(this.canvas); this.imagePos[id] = { x: x >> 9, y: y >> 9 }; if (this.images.length === this.imagesCount) { diff --git a/src/core/layer.js b/src/core/layer.js index a6b25b56bc..8d43b53735 100644 --- a/src/core/layer.js +++ b/src/core/layer.js @@ -36,9 +36,10 @@ export default class Layer extends Base { attrs: {}, // 样式配置项 styleOptions: { - stroke: [ 1.0, 1.0, 1.0, 1.0 ], + stroke: 'none', strokeWidth: 1.0, opacity: 1.0, + strokeOpacity: 1.0, texture: false }, // 选中时的配置项 @@ -63,31 +64,35 @@ export default class Layer extends Base { this._activeIds = null; scene._engine._scene.add(this._object3D); this.layerMesh = null; + this.layerLineMesh = null; } /** * 将图层添加加到 Object * @param {*} object three 物体 + * @param {*} type mesh类型是区别是填充还是边线 */ - add(object) { - this.layerMesh = object; + add(object, type = 'fill') { + type === 'fill' ? this.layerMesh = object : this.layerLineMesh = object; + this._visibleWithZoom(); this.scene.on('zoomchange', () => { this._visibleWithZoom(); }); - this.layerMesh.onBeforeRender = () => { + object.onBeforeRender = () => { const zoom = this.scene.getZoom(); - this.layerMesh.material.setUniformsValue('u_time', this.scene._engine.clock.getElapsedTime()); - this.layerMesh.material.setUniformsValue('u_zoom', zoom); + object.material.setUniformsValue('u_time', this.scene._engine.clock.getElapsedTime()); + object.material.setUniformsValue('u_zoom', zoom); + this._preRender(); }; // 更新 if (this._needUpdateFilter) { - this._updateFilter(); + this._updateFilter(object); } this._object3D.add(object); - this._addPickMesh(object); + if (type === 'fill') { this._addPickMesh(object); } } remove(object) { this._object3D.remove(object); @@ -131,7 +136,7 @@ export default class Layer extends Base { } values === 'text' ? this.shapeType = values : null; - this._createAttrOption('shape', field, values, Global.sizes); + this._createAttrOption('shape', field, values, Global.shape); return this; } /** @@ -171,7 +176,7 @@ export default class Layer extends Base { styleOptions.fields = fields; Util.assign(styleOptions, cfg); for (const item in cfg) { - if (colorItem.indexOf(item) !== -1) { + if (colorItem.indexOf(item) !== -1 && styleOptions[item] !== 'none') { styleOptions[item] = ColorUtil.color2RGBA(styleOptions[item]); } styleOptions[item] = styleOptions[item]; @@ -252,20 +257,24 @@ export default class Layer extends Base { this._mapping(); const activeHander = this._addActiveFeature.bind(this); + const resetHander = this._resetStyle.bind(this); if (this.get('allowActive')) { - this.scene.on('pick', activeHander); + this.on('active', activeHander); + this.on('mouseleave', resetHander); } else { - this.scene.off('pick', activeHander); + this.off('active', activeHander); + this.off('mouseleave', resetHander); } } _addActiveFeature(e) { const { featureId } = e; - + if (featureId < 0) return; const activeStyle = this.get('activedOptions'); const selectFeatureIds = this.layerSource.getSelectFeatureId(featureId); + // 如果数据不显示状态则不进行高亮 if (this.StyleData[selectFeatureIds[0]].hasOwnProperty('filter') && this.StyleData[selectFeatureIds[0]].filter === false) { return; } const style = Util.assign({}, this.StyleData[featureId]); style.color = ColorUtil.toRGB(activeStyle.fill).map(e => e / 255); @@ -434,6 +443,7 @@ export default class Layer extends Base { } _addPickMesh(mesh) { this._pickingMesh = new THREE.Object3D(); + this._pickingMesh.name = this.layerId; this._visibleWithZoom(); this.scene.on('zoomchange', () => { this._visibleWithZoom(); @@ -445,6 +455,7 @@ export default class Layer extends Base { }); const pickingMesh = new THREE[mesh.type](mesh.geometry, pickmaterial); + pickingMesh.name = this.layerId; pickmaterial.setDefinesvalue(this.type, true); pickingMesh.onBeforeRender = () => { const zoom = this.scene.getZoom(); @@ -457,20 +468,40 @@ export default class Layer extends Base { } _addPickingEvents() { // TODO: Find a way to properly remove this listener on destroy - this.scene.on('pick', e => { - // Re-emit click event from the layer - const { featureId, point2d, intersects } = e; - if (intersects.length === 0) { return; } - const source = this.layerSource.get('data'); - const feature = source.features[featureId]; + this.scene.on('pick-' + this.layerId, e => { + const { featureId, point2d,type} = e; + + if (featureId < -100 && this._activeIds !== null) { + this.emit('mouseleave'); + return; + } + // if (intersects.length === 0) { return; } + const feature = this.layerSource.getSelectFeature(featureId); const lnglat = this.scene.containerToLngLat(point2d); const target = { + featureId, feature, pixel: point2d, lnglat: { lng: lnglat.lng, lat: lnglat.lat } }; - this.emit('click', target); - // this.emit('move', target); + if(featureId>=0) { + + switch(type) { + case 'mouseup': + this.emit('click', target); + break; + case 'mousemove': + this.emit('mousemove', target); + this.emit('active', target); + break; + default: + //this.emit('click', target); + + } + } + + + }); } /** @@ -480,7 +511,7 @@ export default class Layer extends Base { */ updateStyle(featureStyleId, style) { if (this._activeIds) { - this.resetStyle(); + this._resetStyle(); } this._activeIds = featureStyleId; const pickingId = this.layerMesh.geometry.attributes.pickingId.array; @@ -507,15 +538,15 @@ export default class Layer extends Base { } /** - * 用于过滤数据 - * @param {*} filterData 数据过滤标识符 + * 用于过滤数据 + * @param {*} object 需要过滤的mesh */ - _updateFilter() { + _updateFilter(object) { this._updateMaping(); const filterData = this.StyleData; this._activeIds = null; // 清空选中元素 - const colorAttr = this.layerMesh.geometry.attributes.a_color; - const pickAttr = this.layerMesh.geometry.attributes.pickingId; + const colorAttr = object.geometry.attributes.a_color; + const pickAttr = object.geometry.attributes.pickingId; pickAttr.array.forEach((id, index) => { id = Math.abs(id); const color = [ ...this.StyleData[id - 1].color ]; @@ -526,7 +557,7 @@ export default class Layer extends Base { colorAttr.array[index * 4 + 1] = 0; colorAttr.array[index * 4 + 2] = 0; colorAttr.array[index * 4 + 3] = 0; - pickAttr.array[index] = -id; + pickAttr.array[index] = -id; // 通过Id数据过滤 id<0 不显示 } else { colorAttr.array[index * 4 + 0] = color[0]; colorAttr.array[index * 4 + 1] = color[1]; @@ -537,8 +568,8 @@ export default class Layer extends Base { }); colorAttr.needsUpdate = true; pickAttr.needsUpdate = true; - this._needUpdateFilter = false; - this._needUpdateColor = false; + // this._needUpdateFilter = false; + // this._needUpdateColor = false; } _visibleWithZoom() { const zoom = this.scene.getZoom(); @@ -561,7 +592,8 @@ export default class Layer extends Base { /** * 重置高亮要素 */ - resetStyle() { + _resetStyle() { + const pickingId = this.layerMesh.geometry.attributes.pickingId.array; const colorAttr = this.layerMesh.geometry.attributes.a_color; this._activeIds.forEach(index => { @@ -577,6 +609,7 @@ export default class Layer extends Base { } }); colorAttr.needsUpdate = true; + this._activeIds = null; } /** * 销毁Layer对象 @@ -609,5 +642,8 @@ export default class Layer extends Base { this._object3D = null; this.scene = null; } + _preRender(){ + + } } diff --git a/src/core/scene.js b/src/core/scene.js index 295c8d562a..f1e09140df 100644 --- a/src/core/scene.js +++ b/src/core/scene.js @@ -1,5 +1,4 @@ import Engine from './engine'; -import * as THREE from './three'; import * as layers from '../layer'; import Base from './base'; import LoadImage from './image'; @@ -19,6 +18,7 @@ export default class Scene extends Base { } _initEngine(mapContainer) { + this._el = mapContainer; this._engine = new Engine(mapContainer, this); this._engine.run(); } @@ -77,16 +77,34 @@ export default class Scene extends Base { return this._layers; } _addLight() { - const scene = this._engine._scene; - const ambientLight = new THREE.AmbientLight(0xaaaaaa); - scene.add(ambientLight); + // const scene = this._engine._scene; + // //const ambientLight = new THREE.AmbientLight(0xaaaaaa); + // scene.add(ambientLight); - const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); - scene.add(directionalLight); + // const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); + // scene.add(directionalLight); } _addLayer() { } + _registEvents(){ + const events = [ + 'mouseout', + 'mouseover', + 'mousemove', + 'mousedown', + 'mouseleave', + 'mouseup', + 'click', + 'dblclick' + ]; + events.forEach((event)=>{ + this._el.addEventListener(event, e => { + + }, false); + }) + } + // 代理map事件 removeLayer(layer) { const layerIndex = this._layers.indexOf(layer); if (layerIndex > -1) { diff --git a/src/core/three.js b/src/core/three.js index 6b60d4909e..19202f3e2d 100644 --- a/src/core/three.js +++ b/src/core/three.js @@ -9,8 +9,8 @@ export { Points } from 'three/src/objects/Points.js'; export { LineSegments } from 'three/src/objects/LineSegments.js'; export { Mesh } from 'three/src/objects/Mesh.js'; export { Texture } from 'three/src/textures/Texture.js'; -export { DirectionalLight } from 'three/src/lights/DirectionalLight.js'; -export { AmbientLight } from 'three/src/lights/AmbientLight.js'; +//export { DirectionalLight } from 'three/src/lights/DirectionalLight.js'; +//export { AmbientLight } from 'three/src/lights/AmbientLight.js'; export { WebGLRenderTarget } from 'three/src/renderers/WebGLRenderTarget.js'; export { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera.js'; export { BufferGeometry } from 'three/src/core/BufferGeometry.js'; @@ -18,15 +18,15 @@ export { Raycaster } from 'three/src/core/Raycaster.js'; export { Matrix4 } from 'three/src/math/Matrix4.js'; export { Matrix3 } from 'three/src/math/Matrix3.js'; export { Line } from 'three/src/objects/Line.js'; -export { LineLoop } from 'three/src/objects/LineLoop.js'; +// export { LineLoop } from 'three/src/objects/LineLoop.js'; export { Vector4 } from 'three/src/math/Vector4.js'; export { Vector3 } from 'three/src/math/Vector3.js'; export { Vector2 } from 'three/src/math/Vector2.js'; -export { TextureLoader } from 'three/src/loaders/TextureLoader.js'; -export { LineDashedMaterial } from 'three/src/materials/LineDashedMaterial.js'; +// export { TextureLoader } from 'three/src/loaders/TextureLoader.js'; +// export { LineDashedMaterial } from 'three/src/materials/LineDashedMaterial.js'; export { ShaderMaterial } from 'three/src/materials/ShaderMaterial.js'; -export { PointsMaterial } from 'three/src/materials/PointsMaterial.js'; -export { VideoTexture } from 'three/src/textures/VideoTexture.js'; +// export { PointsMaterial } from 'three/src/materials/PointsMaterial.js'; +// export { VideoTexture } from 'three/src/textures/VideoTexture.js'; export { DataTexture } from 'three/src/textures/DataTexture.js'; export { Float64BufferAttribute, diff --git a/src/geo/bound.js b/src/geo/bound.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/geo/lngLat.js b/src/geo/lngLat.js new file mode 100644 index 0000000000..edc7b59576 --- /dev/null +++ b/src/geo/lngLat.js @@ -0,0 +1,20 @@ +export class LatLng { + constructor(lat, lng, alt) { + if (isNaN(lat) || isNaN(lng)) { + throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); + } + this.lat = +lat; + this.lng = +lng; + if (alt !== undefined) { + this.alt = +alt; + } + + } + equal() { + + } + distanceTo() { + + } + +} diff --git a/src/geom/buffer/point.js b/src/geom/buffer/point.js index 7de8e3536e..fe7d961999 100644 --- a/src/geom/buffer/point.js +++ b/src/geom/buffer/point.js @@ -1,5 +1,9 @@ import BufferBase from './bufferBase'; import { regularShape } from '../shape/index'; +import * as polygonPath from '../shape/path'; +import * as polygonShape from '../shape/polygon'; +import * as lineShape from '../shape/line'; +import { pointShape } from '../../global'; import Util from '../../util'; export default class PointBuffer extends BufferBase { geometryBuffer() { @@ -43,8 +47,17 @@ export default class PointBuffer extends BufferBase { this.attributes = this._toPointsAttributes(this.bufferStruct); } _3dRegularBuffer() { + const lineAttribute = { + shapes: [], + normal: [], + miter: [], + indexArray: [], + sizes: [], + positions: [] + }; const coordinates = this.get('coordinates'); const properties = this.get('properties'); + const style = this.get('style'); const type = this.get('type'); const positions = []; const shapes = []; @@ -55,7 +68,7 @@ export default class PointBuffer extends BufferBase { this.bufferStruct.style = properties; coordinates.forEach((geo, index) => { let { size, shape } = properties[index]; - let shapeType = 'extrude'; + let shapeType = ''; if (type === '2d' || (type === '3d' && size[2] === 0)) { shapeType = 'fill'; @@ -67,7 +80,20 @@ export default class PointBuffer extends BufferBase { uvs.push(0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0); shape = 'square'; } - const vert = regularShape[shape](shapeType); + // const vert = regularShape[shape](shapeType); + properties[index].size = size; + + const [ vert, polygonLine ] = this._getShape(properties[index], style, lineAttribute.miter.length); + polygonLine.miter.forEach(() => { + lineAttribute.positions.push(...geo); + lineAttribute.sizes.push(...size); + }); + + lineAttribute.shapes.push(...polygonLine.positions); + lineAttribute.normal.push(...polygonLine.normal); + lineAttribute.miter.push(...polygonLine.miter); + lineAttribute.indexArray.push(...polygonLine.indexArray); + shapes.push(vert.positions); positions.push(geo); sizes.push(size); @@ -81,6 +107,21 @@ export default class PointBuffer extends BufferBase { this.bufferStruct.sizes = sizes; this.bufferStruct.faceUv = uvs; this.attributes = this._toPointShapeAttributes(this.bufferStruct); + this.lineAttribute = lineAttribute; + } + _getShape(props, style, positionsIndex) { + const { shape } = props; + const { stroke, strokeWidth } = style; + const path = polygonPath[shape](); + let polygon = null; + let polygonLine = null; + if (pointShape['3d'].indexOf(shape) === -1) { + polygon = polygonShape.fill([ path ]); + polygonLine = lineShape.Line(path, { size: [ strokeWidth, 0 ], color: stroke }, positionsIndex); + } else { + polygon = polygonShape.extrude([ path ]); + } + return [ polygon, polygonLine ]; } } diff --git a/src/geom/buffer/point/fillBuffer.js b/src/geom/buffer/point/fillBuffer.js new file mode 100644 index 0000000000..84d257c3ee --- /dev/null +++ b/src/geom/buffer/point/fillBuffer.js @@ -0,0 +1,81 @@ +import { pointShape } from '../../../global'; +import * as THREE from '../../../core/three'; +import * as polygonShape from '../../shape/polygon'; +import * as polygonPath from '../../shape/path'; +import Util from '../../../util'; +export default function fillBuffer(coordinates, properties) { + const attribute = { + vertices: [], + normals: [], + colors: [], + pickingIds: [], + shapePositions: [], + a_size: [], + faceUv: [] + + }; + coordinates.forEach((geo, index) => { + let { size, shape, color, id } = properties[index]; + let polygon = null; + const path = polygonPath[shape](); + if (pointShape['2d'].indexOf(shape) !== -1) { + Util.isArray(size) || (size = [ size, size, 0 ]); + polygon = polygonShape.fill([ path ]); + } else if (pointShape['3d'].indexOf(shape) !== -1) { + Util.isArray(size) || (size = [ size, size, size ]); + polygon = polygonShape.extrude([ path ]); + } else { + throw new Error('Invalid shape type: ' + shape); + } + toPointShapeAttributes(polygon, geo, { size, shape, color, id }, attribute); + + }); + return attribute; + +} +function toPointShapeAttributes(polygon, geo, style, attribute) { + const { positionsIndex, positions } = polygon; + const pA = new THREE.Vector3(); + const pB = new THREE.Vector3(); + const pC = new THREE.Vector3(); + + const cb = new THREE.Vector3(); + const ab = new THREE.Vector3(); + for (let i = 0; i < positionsIndex.length / 3; i++) { + let index = positionsIndex[i * 3]; + const { color, size, id } = style; + const ax = positions[index][0]; + const ay = positions[index][1]; + const az = positions[index][2]; + index = positionsIndex[i * 3 + 1]; + const bx = positions[index][0]; + const by = positions[index][1]; + const bz = positions[index][2]; + index = positionsIndex[i * 3 + 2]; + const cx = positions[index][0]; + const cy = positions[index][1]; + const cz = positions[index][2]; + + pA.set(ax, ay, az); + pB.set(bx, by, bz); + pC.set(cx, cy, cz); + + cb.subVectors(pC, pB); + ab.subVectors(pA, pB); + cb.cross(ab); + + cb.normalize(); + + const nx = cb.x; + const ny = cb.y; + const nz = cb.z; + + attribute.vertices.push(...geo, ...geo, ...geo); + attribute.shapePositions.push(ax, ay, az, bx, by, bz, cx, cy, cz); + attribute.a_size.push(...size, ...size, ...size); + attribute.normals.push(nx, ny, nz, nx, ny, nz, nx, ny, nz); + attribute.colors.push(...color, ...color, ...color); + attribute.pickingIds.push(id, id, id); + + } +} diff --git a/src/geom/buffer/point/imageBuffer.js b/src/geom/buffer/point/imageBuffer.js new file mode 100644 index 0000000000..6bc37b052a --- /dev/null +++ b/src/geom/buffer/point/imageBuffer.js @@ -0,0 +1,23 @@ +export default function ImageBuffer(coordinates, properties, opt) { + const attributes = { + vertices: [], + colors: [], + sizes: [], + shapes: [], + pickingIds: [], + uv: [] + }; + coordinates.forEach((pos, index) => { + const { color, size, id, shape } = properties[index]; + const { x, y } = opt.imagePos[shape]; + attributes.vertices.push(...pos); + attributes.colors.push(...color); + attributes.pickingIds.push(id); + attributes.sizes.push(size * window.devicePixelRatio); // + attributes.uv.push(x, y); + attributes.shapes.push(shape); + }); + + + return attributes; +} diff --git a/src/geom/buffer/point/index.js b/src/geom/buffer/point/index.js new file mode 100644 index 0000000000..80d52c5ff1 --- /dev/null +++ b/src/geom/buffer/point/index.js @@ -0,0 +1,4 @@ +export { default as FillBuffer } from './fillBuffer'; +export { default as StrokeBuffer } from './strokeBuffer'; +export { default as ImageBuffer } from './imageBuffer'; +export { default as NormalBuffer } from './normalBuffer'; diff --git a/src/geom/buffer/point/normalBuffer.js b/src/geom/buffer/point/normalBuffer.js new file mode 100644 index 0000000000..d35fd4217b --- /dev/null +++ b/src/geom/buffer/point/normalBuffer.js @@ -0,0 +1,19 @@ +export default function NormalBuffer(coordinates, properties) { + const attributes = { + vertices: [], + colors: [], + sizes: [], + pickingIds: [] + }; + coordinates.forEach((pos, index) => { + const { color, size, id } = properties[index]; + attributes.vertices.push(...pos); + attributes.colors.push(...color); + attributes.pickingIds.push(id); + attributes.sizes.push(size); + + }); + + + return attributes; +} diff --git a/src/geom/buffer/point/sdfCommonWords.js b/src/geom/buffer/point/sdfCommonWords.js new file mode 100644 index 0000000000..4631cc11cf --- /dev/null +++ b/src/geom/buffer/point/sdfCommonWords.js @@ -0,0 +1,246 @@ +const SDFCommonWordsKey = '_AMap_sdf_com_words'; + +/** + * SDF 常用字获取/存储/check + * + */ +const SDFCommonWords = { + + store() { + + }, + + /** + * 检查一个字符是否在常用字中 + * @param {*} charcode 汉字 + */ + check(charcode) { + const range = this.range || []; + const info = this.info || {}; + + if (typeof charcode !== 'number') { + + charcode = charcode.substr(0).charCodeAt(0); + } + + for (let i = 0; i < range.length; i++) { + const curRange = range[i]; + const [ rangeStart, rangeEnd ] = curRange.split('-'); + + if (charcode >= rangeStart && charcode <= rangeEnd) { + + const curInfo = info[curRange] && info[curRange].info || {}; + + if (curInfo[charcode]) { + + return true; + } + } + } + + return false; + }, + + /** + * 获取纹理和位置信息 + * @param list + * @param cb + */ + getImagesAndInfo(list, cb) { + const range = this.range; + + + }, + + loadCanvas(url, range, done) { + + try { + const xhr = new XMLHttpRequest(); + xhr.open('GET', url); + + // 直接用 blob 格式 load 图片文件,方便直接转换成 base64 + // 转成 base64 便于存储 + // 使用 canvas 转换 base64 容易有损 + xhr.responseType = 'blob'; + xhr.onerror = function() { + done({ code: 0 }); + }; + + xhr.onload = function() { + + if (xhr.status === 200) { + const reader = new FileReader(); + + reader.onload = () => { + + done(reader.result, range); + }; + + reader.readAsDataURL(xhr.response); + } else { + done({ code: 0 }); + } + }; + + xhr.send(); + } catch (err) { + + done({ code: 0 }); + } + }, + + loadImages(urls = []) { + const deferred = $.Deferred(); + const totalNumbers = urls.length; + const localInfo = this.info; + let loadPicNum = 0; + + for (let i = 0; i < urls.length; i++) { + const { url, range } = urls[i]; + + this.loadCanvas(url, range, (base64, range) => { + + // image to base64 + loadPicNum++; + + !localInfo[range] && (localInfo[range] = {}); + + localInfo[range].pic = base64; + + this.info = localInfo; + + // todo: temp 暂时用 localstorage 存储,因为数据比较大,最好使用 indexDB + localStorage.setItem(SDFCommonWordsKey, JSON.stringify(localInfo)); + + if (loadPicNum === totalNumbers) { + + deferred.resolve(); + } + }); + } + + return deferred; + }, + + loadInfo(urls) { + const deferred = $.Deferred(); + const totalNumbers = urls.length; + const localInfo = this.info; + let loadInfoNum = 0; + + for (let i = 0; i < urls.length; i++) { + const { url, range } = urls[i]; + + $.ajax({ + url, + dataType: 'json', + success: data => { + loadInfoNum++; + + !localInfo[range] && (localInfo[range] = {}); + + localInfo[range].info = data; + + this.info = localInfo; + + localStorage.setItem(SDFCommonWordsKey, JSON.stringify(localInfo)); + + if (loadInfoNum === totalNumbers) { + + deferred.resolve(); + } + }, + error: () => { + + } + }); + } + + return deferred; + + }, + + getTotalAssets(info, cb) { + const { range = [], urlPrefix } = info; + const picUrls = []; + const infoUrls = []; + + this.range = range; + + for (let i = 0; i < range.length; i++) { + const curRange = range[i]; + const baseUrl = urlPrefix + curRange; + const picUrl = baseUrl + '.png'; + const infoUrl = baseUrl + '.json'; + + picUrls.push({ range: curRange, url: picUrl }); + infoUrls.push({ range: curRange, url: infoUrl }); + } + + const imageDeferred = this.loadImages(picUrls); + const infoDeferred = this.loadInfo(infoUrls); + + $.when(imageDeferred, infoDeferred) + .then(() => { + + // all info load complete + // console.log("all info load complete", " -- ", 1); + cb && cb(this.info); + }, () => { + + // fail + }); + }, + // 获取数据 + getData(cb) { + + if (!_.isEmpty(this.info)) { + + cb && cb(this.info); + } else { + + this.getRemoteData(cb); + } + }, + + /** + * 从服务获取数据,什么时候强制去取一回数据?过期? + * @param cb + */ + getRemoteData(cb) { + const self = this; + + $.ajax({ + url: '/getcommonwords', + dataType: 'json', + success: data => { + + if (data.code == 1) { + + const info = data.data; + + self.getTotalAssets(info, cb); + } + } + }); + }, + + destroy() { + + }, + + init() { + let info = localStorage.getItem(SDFCommonWordsKey); + this.range = []; + this.info = {}; + + if (info) { + info = JSON.parse(info); + this.range = Object.keys(info); + this.info = info; + } + + this.info = info || {}; + } +}; +export default SDFCommonWords; diff --git a/src/geom/buffer/point/strokeBuffer.js b/src/geom/buffer/point/strokeBuffer.js new file mode 100644 index 0000000000..c71726cbd6 --- /dev/null +++ b/src/geom/buffer/point/strokeBuffer.js @@ -0,0 +1,53 @@ +import * as polygonPath from '../../shape/path'; +import * as polygonShape from '../../shape/polygon'; +import * as lineShape from '../../shape/line'; +import { pointShape } from '../../../global'; +import Util from '../../../util'; +export default function StrokeBuffer(coordinates, properties, style) { + const attribute = { + shapes: [], + normal: [], + miter: [], + indexArray: [], + sizes: [], + positions: [], + pickingIds: [], + colors: [] + }; + const { stroke, strokeWidth } = style; + coordinates.forEach((geo, index) => { + let { size, shape, id } = properties[index]; + const path = polygonPath[shape](); + const positionsIndex = attribute.miter.length; + let polygon = null; + if (pointShape['2d'].indexOf(shape) !== -1) { + Util.isArray(size) || (size = [ size, size, 0 ]); + polygon = lineShape.Line([ path ], { size: [ strokeWidth, 0 ], color: stroke, id }, positionsIndex); + } else if (pointShape['3d'].indexOf(shape) !== -1) { + Util.isArray(size) || (size = [ size, size, size ]); + const polygonExtrudePath = polygonShape.extrudeline([ path ]); + // TODO 3d line + polygon = lineShape.Line([ polygonExtrudePath ], { size: [ strokeWidth, 0 ], color: stroke, id }, positionsIndex); + + + } else { + throw new Error('Invalid shape type: ' + shape); + } + polygonLineBuffer(polygon, geo, size, attribute); + + }); + return attribute; +} +function polygonLineBuffer(polygon, geo, size, attribute) { + attribute.shapes.push(...polygon.positions); + attribute.normal.push(...polygon.normal); + attribute.miter.push(...polygon.miter); + attribute.pickingIds.push(...polygon.pickingIds); + attribute.indexArray.push(...polygon.indexArray); + attribute.colors.push(...polygon.colors); + polygon.miter.forEach(() => { + attribute.positions.push(...geo); // 多边形位置 + attribute.sizes.push(...size); // 多边形大小 + }); + +} diff --git a/src/geom/buffer/point/textBuffer.js b/src/geom/buffer/point/textBuffer.js new file mode 100644 index 0000000000..0f4801fb68 --- /dev/null +++ b/src/geom/buffer/point/textBuffer.js @@ -0,0 +1,9 @@ + + +import { getJSON } from '../../../util/ajax'; +import * as THREE from '../../../core/three'; +import Global from '../../../global'; +const Space = 1; +export default function TextBuffer(coordinates, properties, style) { + +} diff --git a/src/geom/buffer/text.js b/src/geom/buffer/text.js index 710dfd1bdc..0607ec5aaf 100644 --- a/src/geom/buffer/text.js +++ b/src/geom/buffer/text.js @@ -1,6 +1,8 @@ import BufferBase from './bufferBase'; import { getJSON } from '../../util/ajax'; import * as THREE from '../../core/three'; +import TinySDF from '@mapbox/tiny-sdf'; + import Global from '../../global'; const Space = 1; export default class TextBuffer extends BufferBase { @@ -15,16 +17,21 @@ export default class TextBuffer extends BufferBase { const properties = this.get('properties'); const { textOffset = [ 0, 0 ] } = this.get('style'); const chars = []; + const textChars = {}; properties.forEach(element => { let text = element.shape || ''; text = text.toString(); for (let j = 0; j < text.length; j++) { const code = text.charCodeAt(j); + textChars[text] = 0; if (chars.indexOf(code) === -1) { chars.push(text.charCodeAt(j)); } } }); + const sdfTexture = this._updateSdf(Object.keys(textChars).join('')); + this.sdfTexture = sdfTexture; + this._loadTextInfo(chars); this.on('SourceLoaded', () => { const textureElements = []; @@ -40,10 +47,10 @@ export default class TextBuffer extends BufferBase { let text = element.shape || ''; text = text.toString(); for (let i = 0; i < text.length; i++) { - const chr = text.charCodeAt(i); + const color = element.color; - this._drawGlyph(pos, chr, pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color); + this._drawGlyph(pos, text[i], pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color); } }); this.bufferStruct.style = properties; @@ -64,6 +71,7 @@ export default class TextBuffer extends BufferBase { url: `${Global.sdfHomeUrl}/getsdfdata?chars=${chars.join('|')}` }, (e, info) => { this.metrics.chars = info.info; + this._loadTextTexture(info.url); }); } @@ -73,8 +81,9 @@ export default class TextBuffer extends BufferBase { const img = new Image(); img.crossOrigin = 'anonymous'; + img.onload = () => { - this.bufferStruct.textTexture = this._creatTexture(img); + this.bufferStruct.textTexture = this._creatTexture(this.sdfTexture.texure); this.emit('SourceLoaded'); }; img.src = url; @@ -93,22 +102,26 @@ export default class TextBuffer extends BufferBase { * @param {*} textOffsets 字体偏移量数据 * @param {*} color 文字颜色 */ - _drawGlyph(pos, chr, pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color) { + _drawGlyph(pos, text, pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color) { const metrics = this.metrics; + const chr = text.charCodeAt(0); const metric = metrics.chars[chr]; if (!metric) return; - + const info = this.sdfTexture.info; + const { x, y } = info[text]; const scale = size / metrics.size; - let width = metric[0]; - let height = metric[1]; + let width = 24; // metric[0]; + let height = 24;// metric[1]; const horiBearingX = metric[2]; - const horiBearingY = metric[3]; + // const horiBearingY = metric[3]; const horiAdvance = metric[4]; - const posX = metric[5]; - const posY = metric[6]; + // const posX = metric[5]; + // const posY = metric[6]; + const posX = x; + const posY = y; const buffer = metrics.buffer; @@ -117,12 +130,17 @@ export default class TextBuffer extends BufferBase { height += buffer * 2; // Add a quad (= two triangles) per glyph. - const originX = (horiBearingX - buffer + width / 2) * scale; - const originY = -(height / 2 - horiBearingY) * scale; - // const originY = (height / 2 - horiBearingY) * scale; - // const originY = 0; - const offsetWidth = width / 2 * scale / (1.0 - horiBearingX * 1.5 / horiAdvance); - const offsetHeight = (horiAdvance / 2) * scale; + // const originX = (horiBearingX - buffer + width / 2) * scale; + // const originY = -(height - horiBearingY) * scale; + const originX = 0; + const originY = 0; + + // const offsetWidth = width / 2 * scale / (1.0 - horiBearingX * 1.5 / horiAdvance); + // const offsetHeight = (horiAdvance / 2) * scale; + + // const offsetWidth = width/2 * scale; + // const offsetHeight = height / 2 * scale; + // const offsetHeight = height * scale; const offsetX = pen.x; const offsetY = pen.y; @@ -135,14 +153,31 @@ export default class TextBuffer extends BufferBase { pos[0] + originX, pos[1] + originY, 0, ); + // textSizes.push( + // offsetWidth, offsetHeight, + // -offsetWidth, offsetHeight, + // -offsetWidth, -offsetHeight, + // offsetWidth, offsetHeight, + // -offsetWidth, -offsetHeight, + // offsetWidth, -offsetHeight, + // ); + const bx = 0; + const by = metrics.size / 2 + buffer; textSizes.push( - offsetWidth, offsetHeight, - -offsetWidth, offsetHeight, - -offsetWidth, -offsetHeight, - offsetWidth, offsetHeight, - -offsetWidth, -offsetHeight, - offsetWidth, -offsetHeight, + + + ((bx - buffer + width) * scale), (height - by) * scale, + ((bx - buffer) * scale), (height - by) * scale, + ((bx - buffer) * scale), -by * scale, + + ((bx - buffer + width) * scale), (height - by) * scale, + ((bx - buffer) * scale), -by * scale, + ((bx - buffer + width) * scale), -by * scale, + + ); + + textOffsets.push( offsetX, offsetY, offsetX, offsetY, @@ -172,7 +207,8 @@ export default class TextBuffer extends BufferBase { ); } - pen.x = pen.x + (horiAdvance + Space) * scale; + // pen.x = pen.x + (horiAdvance + Space) * scale; + pen.x = pen.x + size * 1.8; } @@ -196,8 +232,46 @@ export default class TextBuffer extends BufferBase { this.bufferStruct.textSize = [ image.width, image.height ]; const texture = new THREE.Texture(image); texture.minFilter = THREE.LinearFilter; - texture.magFilter = THREE.LinearFilter; + texture.magFilter = THREE.ClampToEdgeWrapping; texture.needsUpdate = true; return texture; } + _updateSdf(chars) { + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + const sdfs = {}; + + + const fontSize = 24; + const fontWeight = 100; + const buffer = fontSize / 8; + const radius = fontSize / 3; + const canvasSize = Math.floor(Math.pow(chars.length, 0.5)) * (fontSize + buffer + radius); + canvas.width = canvasSize; + canvas.height = canvasSize; + ctx.clearRect(0, 0, canvas.width, canvas.height); + const sdf = new TinySDF(fontSize, buffer, radius, null, null, fontWeight); + for (let y = 0, i = 0; y + sdf.size <= canvas.height && i < chars.length; y += sdf.size) { + for (let x = 0; x + sdf.size <= canvas.width && i < chars.length; x += sdf.size) { + ctx.putImageData(this._makeRGBAImageData(ctx, sdf.draw(chars[i]), sdf.size), x, y); + sdfs[chars[i]] = { x, y }; + i++; + } + } + return { + info: sdfs, + texure: canvas + }; + } + _makeRGBAImageData(ctx, alphaChannel, size) { + const imageData = ctx.createImageData(size, size); + const data = imageData.data; + for (let i = 0; i < alphaChannel.length; i++) { + data[4 * i + 0] = alphaChannel[i]; + data[4 * i + 1] = alphaChannel[i]; + data[4 * i + 2] = alphaChannel[i]; + data[4 * i + 3] = 255; + } + return imageData; + } } diff --git a/src/geom/material/lineMaterial.js b/src/geom/material/lineMaterial.js index 4af10d581a..a4b43c7eda 100644 --- a/src/geom/material/lineMaterial.js +++ b/src/geom/material/lineMaterial.js @@ -45,7 +45,10 @@ export function MeshLineMaterial(options) { uniforms: { u_opacity: { value: options.u_opacity || 1.0 }, u_time: { value: options.u_time || 0 }, - u_zoom: { value: options.u_zoom } + u_zoom: { value: options.u_zoom }, + u_duration: { value: options.u_duration || 2.0 }, + u_interval: { value: options.u_interval || 1.0 }, + u_trailLength: { value: options.u_trailLength || 0.2 } }, vertexShader: meshline_vert, fragmentShader: meshline_frag, diff --git a/src/geom/material/pointLineMaterial.js b/src/geom/material/pointLineMaterial.js new file mode 100644 index 0000000000..cf89204eeb --- /dev/null +++ b/src/geom/material/pointLineMaterial.js @@ -0,0 +1,29 @@ +import Material from './material'; +import point_frag from '../shader/point_meshLine_frag.glsl'; +import point_vert from '../shader/point_meshLine_vert.glsl'; + +export default class PointLineMaterial extends Material { + getDefaultParameters() { + return { + uniforms: { + u_strokeOpacity: { value: 1 }, + u_stroke: { value: [ 1.0, 1.0, 1.0, 1.0 ] }, + u_strokeWidth: { value: 1.0 }, + u_zoom: { value: 10 } + + } + }; + } + constructor(_uniforms, _defines, parameters) { + super(parameters); + const { uniforms } = this.getDefaultParameters(); + + this.uniforms = Object.assign(uniforms, this.setUniform(_uniforms)); + this.type = 'PointLineMaterial'; + this.vertexShader = point_vert; + this.fragmentShader = point_frag; + this.transparent = true; + } + + +} diff --git a/src/geom/shader/meshline_frag.glsl b/src/geom/shader/meshline_frag.glsl index 05adc838f1..3372d3c248 100644 --- a/src/geom/shader/meshline_frag.glsl +++ b/src/geom/shader/meshline_frag.glsl @@ -1,7 +1,11 @@ precision highp float; uniform float u_opacity; varying vec4 v_color; +varying float vTime; void main() { gl_FragColor = v_color; - gl_FragColor.a = v_color.a * u_opacity ; + gl_FragColor.a = v_color.a * u_opacity; + #ifdef ANIMATE + gl_FragColor.a *= vTime; + #endif } diff --git a/src/geom/shader/meshline_vert.glsl b/src/geom/shader/meshline_vert.glsl index 30cc7935b4..14c8edb7cc 100644 --- a/src/geom/shader/meshline_vert.glsl +++ b/src/geom/shader/meshline_vert.glsl @@ -2,12 +2,30 @@ precision highp float; attribute float a_miter; attribute vec4 a_color; attribute float a_size; +attribute float a_distance; uniform float u_zoom; varying vec4 v_color; +uniform float u_time; +varying float vTime; +// animate +#ifdef ANIMATE +uniform float u_duration; // 动画持续时间 +uniform float u_interval; +uniform float u_repeat; +uniform float u_trailLength; +#endif + + 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); v_color = a_color; + #ifdef ANIMATE + //mod(a_distance,0.2) * 5. + 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.); + #endif gl_Position = matModelViewProjection * vec4(pointPos, 1.0); } \ No newline at end of file diff --git a/src/geom/shader/point_meshLine_frag.glsl b/src/geom/shader/point_meshLine_frag.glsl new file mode 100644 index 0000000000..c291ef92a9 --- /dev/null +++ b/src/geom/shader/point_meshLine_frag.glsl @@ -0,0 +1,17 @@ +precision highp float; +uniform float u_strokeOpacity; +uniform vec4 u_stroke; +varying float v_pickingId; + +void main() { + if(v_pickingId < -0.1) { + discard; + } + #ifdef ANIMATE + if (vTime > 1.0 || vTime < 0.0) { + discard; + } + #endif + gl_FragColor = u_stroke; + gl_FragColor.a = u_stroke.a * u_strokeOpacity ; +} diff --git a/src/geom/shader/point_meshLine_vert.glsl b/src/geom/shader/point_meshLine_vert.glsl new file mode 100644 index 0000000000..3f8db3560b --- /dev/null +++ b/src/geom/shader/point_meshLine_vert.glsl @@ -0,0 +1,23 @@ +precision highp float; +attribute float a_miter; +attribute vec3 a_size; +attribute vec3 a_shape; +attribute float pickingId; +uniform float u_strokeWidth; +uniform float u_zoom; +varying float v_pickingId; +uniform float u_time; +varying float vTime; +void main() { + mat4 matModelViewProjection = projectionMatrix * modelViewMatrix; + float scale = pow(2.0,(20.0 - u_zoom)); + vec3 newposition = position + (a_size + vec3(u_strokeWidth/2.,u_strokeWidth/2.,0)) * scale* a_shape; + v_pickingId = pickingId; + #ifdef ANIMATE + vTime = 1.0- (mod(u_time*50.,3600.)- position.z) / 100.; + #endif + //vec3 pointPos = newposition.xyz + vec3(normal * u_strokeWidth * pow(2.0,20.0-u_zoom) / 2.0 * a_miter); + vec3 pointPos = newposition.xyz + vec3(normal * u_strokeWidth * scale / 2.0 * a_miter); + gl_Position = matModelViewProjection * vec4(pointPos, 1.0); + +} \ No newline at end of file diff --git a/src/geom/shader/text_frag.glsl b/src/geom/shader/text_frag.glsl index dc987b8de6..886403db72 100644 --- a/src/geom/shader/text_frag.glsl +++ b/src/geom/shader/text_frag.glsl @@ -10,20 +10,19 @@ varying vec2 v_texcoord; void main() { - float dist = texture2D(u_texture, vec2(v_texcoord.x,1.0-v_texcoord.y)).r; + float dist =texture2D(u_texture, vec2(v_texcoord.x,1.0-v_texcoord.y)).r; float alpha; if(u_strokeWidth == 0.0){ - alpha = smoothstep(u_buffer - u_gamma, u_buffer, dist); + alpha = smoothstep(u_buffer - u_gamma, u_buffer + u_gamma, dist); gl_FragColor = vec4(v_color.rgb, alpha * v_color.a); - }else{ if(dist <= u_buffer - u_gamma){ - alpha = smoothstep(u_strokeWidth - u_gamma, u_strokeWidth, dist); + alpha = smoothstep(u_strokeWidth - u_gamma, u_strokeWidth+ u_gamma, dist); gl_FragColor = vec4(u_stroke.rgb, alpha * u_stroke.a); }else if(dist < u_buffer){ - alpha = smoothstep(u_buffer - u_gamma, u_buffer, dist); + alpha = smoothstep(u_buffer - u_gamma, u_buffer+u_gamma, dist); gl_FragColor = vec4(alpha * v_color.rgb + (1.0 - alpha) * u_stroke.rgb, 1.0 * v_color.a * alpha + (1.0 - alpha) * u_stroke.a); }else{ alpha = 1.0; diff --git a/src/geom/shader/text_vert.glsl b/src/geom/shader/text_vert.glsl index c5c09f0a8e..c20c18f6a7 100644 --- a/src/geom/shader/text_vert.glsl +++ b/src/geom/shader/text_vert.glsl @@ -13,8 +13,14 @@ varying vec4 v_color; void main() { mat4 matModelViewProjection = projectionMatrix * modelViewMatrix; vec4 cur_position = matModelViewProjection * vec4(position.xy, 0, 1); - gl_Position = cur_position / cur_position.w + vec4((a_txtOffsets + a_txtsize)/ u_glSize * 2.0,0.0, 0.0) +vec4(abs(a_txtsize.x)/u_glSize.x *2.0, -abs(a_txtsize.y)/u_glSize.y* 2.0, 0.0, 0.0); + gl_Position = cur_position / cur_position.w + vec4((a_txtOffsets + a_txtsize)/ u_glSize * 2.0,0.0, 0.0) +vec4(abs(a_txtsize.x)/u_glSize.x *2.0, -abs(a_txtsize.y)/u_glSize.y* 2.0, 0.0, 0.0); + highp float camera_to_anchor_distance = gl_Position.w; + // highp float perspective_ratio = clamp( + // 0.5 + 0.5 * distance_ratio, + // 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles + // 4.0); v_color = a_color; + v_color.a = v_color.a * camera_to_anchor_distance; v_texcoord = uv / u_textSize; } diff --git a/src/geom/shape/line.js b/src/geom/shape/line.js index f9b7569b70..23145645ff 100644 --- a/src/geom/shape/line.js +++ b/src/geom/shape/line.js @@ -120,7 +120,7 @@ export function defaultLine(geo, index) { return { positions, indexes: indexArray }; } // mesh line -export function Line(path, props, positionsIndex, dash = false) { +export function Line(path, props, positionsIndex) { if (path.length === 1) path = path[0];// 面坐标转线坐标 const positions = []; const pickingIds = []; @@ -129,7 +129,7 @@ export function Line(path, props, positionsIndex, dash = false) { const colors = []; const indexArray = []; const normals = getNormal(path); - const attrDistance = []; + let attrDistance = []; const sizes = []; let c = 0; let index = positionsIndex; @@ -153,10 +153,14 @@ export function Line(path, props, positionsIndex, dash = false) { point[2] = size[1]; positions.push(...point); positions.push(...point); - if (dash) { - const d = pointIndex / (list.length - 1); - attrDistance.push(d, d); + + if(pointIndex===0){ + attrDistance.push(0, 0); + } else{ + const d = attrDistance[pointIndex * 2-1] + lineSegmentDistance(path[pointIndex-1],path[pointIndex]); + attrDistance.push(d,d); } + index += 2; }); normals.forEach(n => { @@ -167,6 +171,9 @@ export function Line(path, props, positionsIndex, dash = false) { miter.push(-m); miter.push(m); }); + attrDistance = attrDistance.map((d)=>{ + return d / attrDistance[attrDistance.length-1]; + }) return { positions, normal, @@ -179,3 +186,9 @@ export function Line(path, props, positionsIndex, dash = false) { }; } +function lineSegmentDistance(end,start) { + const dx = start[0] - end[0]; + const dy = start[1] - end[1]; + const dz = start[2] - end[2]; + return Math.sqrt(dx * dx + dy * dy + dz * dz); +} diff --git a/src/geom/shape/path.js b/src/geom/shape/path.js new file mode 100644 index 0000000000..6f9c269388 --- /dev/null +++ b/src/geom/shape/path.js @@ -0,0 +1,45 @@ +/** + * @author lzxue + * @email lzx199065@gmail.com + * @create date 2018-11-28 11:01:33 + * @modify date 2018-11-28 11:01:33 + * @desc 点,线,面 coordinates +*/ + +function circle() { + return polygonPath(30); +} +function square() { + return polygonPath(4); +} +function triangle() { + return polygonPath(3); +} +function hexagon() { + return polygonPath(6); +} +export { + circle, + square, + triangle, + hexagon, + circle as cylinder, + triangle as triangleColumn, + hexagon as hexagonColumn, + square as squareColumn +}; + +export function polygonPath(pointCount) { + const step = Math.PI * 2 / pointCount; + const line = []; + for (let i = 0; i < pointCount; i++) { + line.push(step * i); + } + const path = line.map(t => { + const x = Math.sin(t + Math.PI / 4), + y = Math.cos(t + Math.PI / 4); + return [ x, y, 0 ]; + }); + path.push(path[0]); + return path; +} diff --git a/src/geom/shape/point.js b/src/geom/shape/point.js index 2eda870006..7a5349d87b 100644 --- a/src/geom/shape/point.js +++ b/src/geom/shape/point.js @@ -1,12 +1,12 @@ - import * as polygonShape from './polygon'; +import { polygonPath } from './path'; /** * shape circle * @param {enum} type 渲染类型 * @return {object} 顶点坐标和索引坐标 */ export function circle(type) { - const points = polygonPoint(30); + const points = polygonPath(30); return polygonShape[type]([ points ]); } /** @@ -15,7 +15,7 @@ export function circle(type) { * @return {object} 顶点坐标和索引坐标 */ export function triangle(type) { - const points = polygonPoint(3); + const points = polygonPath(3); return polygonShape[type]([ points ]); } @@ -25,7 +25,7 @@ export function triangle(type) { * @return {object} 顶点坐标和索引坐标 */ export function diamond(type) { - const points = polygonPoint(4); + const points = polygonPath(4); return polygonShape[type]([ points ]); } @@ -39,26 +39,6 @@ export function square(type) { * @return {object} 顶点坐标和索引坐标 */ export function hexagon(type) { - const points = polygonPoint(6); + const points = polygonPath(6); return polygonShape[type]([ points ]); } -/** - * 规则多边形 - * @param {*} pointCount 顶点个数 - * @param {*} extrude 是否拔高 - * @return {Array} 顶点坐标 - */ -function polygonPoint(pointCount) { - const step = Math.PI * 2 / pointCount; - const line = []; - for (let i = 0; i < pointCount; i++) { - line.push(step * i); - } - // debugger - const points = line.map(t => { - const x = Math.sin(t + Math.PI / 4), - y = Math.cos(t + Math.PI / 4); - return [ x, y, 0 ]; - }); - return points; -} diff --git a/src/geom/shape/polygon.js b/src/geom/shape/polygon.js index 12a87dd1f1..289f7a45c4 100644 --- a/src/geom/shape/polygon.js +++ b/src/geom/shape/polygon.js @@ -55,8 +55,9 @@ export function extrudeline(points) { vertIndex.push(vertCount, 0); vertIndex.push(vertCount, vertCount + pointCount); vertIndex.push(vertCount + pointCount, pointCount); - return { - positions, - positionsIndex: vertIndex - }; + const newPositions = []; + vertIndex.forEach(index => { + newPositions.push(positions[index]); + }); + return newPositions; } diff --git a/src/global.js b/src/global.js index b537d8db38..be038b3e66 100644 --- a/src/global.js +++ b/src/global.js @@ -4,7 +4,7 @@ */ // const Global = {}; const Global = { - version: '____L7_VERSION____', + version: '1.0.0', scene: { mapType: 'AMAP', zoom: 5, @@ -22,6 +22,11 @@ const Global = { // 指定固定 tick 数的逼近值 snapCountArray: [ 0, 1, 1.2, 1.5, 1.6, 2, 2.2, 2.4, 2.5, 3, 4, 5, 6, 7.5, 8, 10 ], size: 10000, + shape: 'circle', + pointShape: { + '2d': [ 'circle', 'square', 'hexagon', 'triangle' ], + '3d': [ 'cylinder', 'triangleColumn', 'hexagonColumn', 'squareColumn' ] + }, sdfHomeUrl: 'https://sdf.amap.com', scales: { } diff --git a/src/index.js b/src/index.js index c884916f78..3117424cd7 100755 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,17 @@ // import Util from './util'; import Scene from './core/scene'; -const version = '0.0.1'; +import Global from './global'; + +const version = Global.version; +const track = function(enable) { + Global.trackable = enable; +}; +require('./track'); export { version, - Scene + Scene, + track + }; + diff --git a/src/layer/lineLayer.js b/src/layer/lineLayer.js index 49d2542cde..f201a69c9d 100644 --- a/src/layer/lineLayer.js +++ b/src/layer/lineLayer.js @@ -46,6 +46,7 @@ export default class LineLayer extends Layer { geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1)); geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normal, 3)); geometry.addAttribute('a_miter', new THREE.Float32BufferAttribute(attributes.miter, 1)); + geometry.addAttribute('a_distance', new THREE.Float32BufferAttribute(attributes.attrDistance, 1)); const lineType = style.lineType; let material; @@ -55,6 +56,20 @@ export default class LineLayer extends Layer { u_opacity: opacity, u_zoom: this.scene.getZoom() }); + + if (animateOptions.enable) { + + material.setDefinesvalue('ANIMATE', true); + const {duration,interval,trailLength,repeat = Infinity} = animateOptions; + this.animateDuration = this.scene._engine.clock.getElapsedTime() + duration * repeat; + material.upDateUninform({ + u_duration: duration, + u_interval: interval, + u_trailLength:trailLength, + }); + + + } } else { geometry.addAttribute('a_distance', new THREE.Float32BufferAttribute(attributes.attrDistance, 1)); material = new DashLineMaterial({ @@ -80,4 +95,11 @@ export default class LineLayer extends Layer { } return this; } + _preRender(){ + if(this.animateDuration>0 && this.animateDuration< this.scene._engine.clock.getElapsedTime()){ + this.layerMesh.material.setDefinesvalue('ANIMATE', false); + this.emit('animateEnd'); + this.animateDuration = Infinity; + } + } } diff --git a/src/layer/pointLayer.js b/src/layer/pointLayer.js index f589eec221..56ff49bcf7 100644 --- a/src/layer/pointLayer.js +++ b/src/layer/pointLayer.js @@ -1,12 +1,11 @@ import Layer from '../core/layer'; import * as THREE from '../core/three'; -import PointBuffer from '../geom/buffer/point'; -import PointMaterial from '../geom/material/pointMaterial'; -import PolygonMaterial from '../geom/material/polygonMaterial'; +import * as drawPoint from '../layer/render/point'; +import { pointShape } from '../global'; +// import PointBuffer from '../geom/buffer/point'; import TextBuffer from '../geom/buffer/text'; import TextMaterial from '../geom/material/textMaterial'; -import radar from '../geom/shader/radar_frag.glsl'; -import warn from '../geom/shader/warn_frag.glsl'; +import * as PointBuffer from '../geom/buffer/point/index'; /** @@ -33,83 +32,64 @@ export default class PointLayer extends Layer { return this; } _prepareRender() { + const { opacity, strokeWidth, stroke, strokeOpacity, shape, fill } = this.get('styleOptions'); if (this.shapeType === 'text') { // 绘制文本图层 this._textPoint(); return; } const source = this.layerSource; - const { opacity, strokeWidth, stroke, shape } = this.get('styleOptions'); - this._buffer = new PointBuffer({ - type: this.shapeType, - imagePos: this.scene.image.imagePos, - coordinates: source.geoData, - properties: this.StyleData - }); - const geometry = this.geometry = new THREE.BufferGeometry(); - let mtl; - if (this.shapeType === '2d' || this.shapeType === '3d') { - mtl = new PolygonMaterial({ - u_opacity: opacity, - u_zoom: this.scene.getZoom() - }); - // mtl= new pickingMaterial({ - // u_opacity: opacity, - // u_zoom: this.scene.getZoom() - // }) - // mtl.setDefinesvalue('point', true); - mtl.setDefinesvalue('SHAPE', true); - if (shape === 'radar') { - mtl.fragmentShader = radar; + const style = this.get('styleOptions'); + const pointShapeType = this._getShape(); - } - if (shape === 'warn') { - mtl.fragmentShader = warn; - } - - - } else { // sdf 绘制点 - mtl = new PointMaterial({ - u_opacity: opacity, - u_strokeWidth: strokeWidth, - u_stroke: stroke, - shape: this.shapeType || false, - u_texture: this.scene.image.texture - }, { - SHAPE: (this.shapeType !== 'image'), - TEXCOORD_0: (this.shapeType === 'image') - }); + switch (pointShapeType) { + case 'fill' :// 填充图形 + { + if (fill !== 'none') { // 是否填充 + const attributes = PointBuffer.FillBuffer(source.geoData, this.StyleData, style); + const meshfill = drawPoint.DrawFill(attributes, this.get('styleOptions')); + this.add(meshfill); + } + if (stroke !== 'none') { // 是否绘制边界 + const lineAttribute = PointBuffer.StrokeBuffer(source.geoData, this.StyleData, style); + const meshStroke = drawPoint.DrawStroke(lineAttribute, this.get('styleOptions')); + this.add(meshStroke, 'line'); + } + } + break; + case 'image':// 绘制图片标注 + const imageAttribute = PointBuffer.ImageBuffer(source.geoData, this.StyleData, { imagePos: this.scene.image.imagePos }); + const imageMesh = drawPoint.DrawImage(imageAttribute, { ...style, texture: this.scene.image.texture }); + this.add(imageMesh); + break; + case 'normal' : // 原生点 + const normalAttribute = PointBuffer.NormalBuffer(source.geoData, this.StyleData, style); + const normalPointMesh = drawPoint.DrawNormal(normalAttribute, style); + this.add(normalPointMesh); } - - const { attributes } = this._buffer; - geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); - geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4)); - geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1)); - if (this.shapeType === 'image') { - geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.uvs, 2)); - geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1)); - } else if (this.shapeType === undefined) { - geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1)); - } else { // 多边形面 - geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normals, 3)); - geometry.addAttribute('a_shape', new THREE.Float32BufferAttribute(attributes.shapePositions, 3)); - geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.a_size, 3)); - if (shape) { - geometry.addAttribute('faceUv', new THREE.Float32BufferAttribute(attributes.faceUv, 2)); + } + _getShape() { + let shape = null; + if (!this.StyleData[0].hasOwnProperty('shape')) { + return 'normal'; + } + for (let i = 0; i < this.StyleData.length; i++) { + shape = this.StyleData[i].shape; + if (shape !== undefined) { + break; } } - let mesh; - if (this.shapeType === 'image') { - mesh = new THREE.Points(geometry, mtl); - } else if (this.shapeType === undefined) { // 散点图 - mesh = new THREE.Points(geometry, mtl); - - } else { - mesh = new THREE.Mesh(geometry, mtl); + if (pointShape['2d'].indexOf(shape) !== -1 || pointShape['3d'].indexOf(shape) !== -1) { + return 'fill'; + } else if (shape == 'text') { + return 'text'; + } else if (this.scene.image.imagesIds.indexOf(shape) !== -1) { + return 'image'; } + return 'normal'; + - this.add(mesh); } _textPoint() { const source = this.layerSource; @@ -133,11 +113,11 @@ export default class PointLayer extends Layer { const material = new TextMaterial({ name: this.layerId, u_texture: buffer.bufferStruct.textTexture, - u_strokeWidth: 1, + u_strokeWidth: styleOptions.strokeWidth, u_stroke: stroke, u_textSize: buffer.bufferStruct.textSize, - u_gamma: 0.11, - u_buffer: 0.8, + u_gamma: 2 * 1.4142 / 64, + u_buffer: 0.65, u_color: color, u_glSize: [ width, height ] }); diff --git a/src/layer/render/point/drawFill.js b/src/layer/render/point/drawFill.js new file mode 100644 index 0000000000..5389855d35 --- /dev/null +++ b/src/layer/render/point/drawFill.js @@ -0,0 +1,28 @@ +/** + * @author lzxue + * @email lzx199065@gmail.com + * @create date 2018-11-29 16:07:24 + * @modify date 2018-11-29 16:07:24 + * @desc [description] 绘制点图层的面状填充,圆,三角形,六边形 +*/ +import * as THREE from '../../../core/three'; +import PolygonMaterial from '../../../geom/material/polygonMaterial'; +export default function DrawFill(attributes, style) { + const { opacity } = style; + const geometry = new THREE.BufferGeometry(); + geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); + geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4)); + geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1)); + geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normals, 3)); + geometry.addAttribute('a_shape', new THREE.Float32BufferAttribute(attributes.shapePositions, 3)); + geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.a_size, 3)); + const material = new PolygonMaterial({ + u_opacity: opacity + }, { + SHAPE: true + }); + material.setDefinesvalue('SHAPE', true); + const fillMesh = new THREE.Mesh(geometry, material); + return fillMesh; + +} diff --git a/src/layer/render/point/drawImage.js b/src/layer/render/point/drawImage.js new file mode 100644 index 0000000000..99fc430a09 --- /dev/null +++ b/src/layer/render/point/drawImage.js @@ -0,0 +1,23 @@ + +import * as THREE from '../../../core/three'; +import PointMaterial from '../../../geom/material/pointMaterial'; +export default function DrawImage(attributes, style) { + const geometry = new THREE.BufferGeometry(); + const { strokeWidth, stroke, opacity, texture } = style; + geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); + geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4)); + geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1)); + geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.uv, 2)); + geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1)); + const material = new PointMaterial({ + u_opacity: opacity, + u_strokeWidth: strokeWidth, + u_stroke: stroke, + u_texture: texture + }, { + SHAPE: false, + TEXCOORD_0: true + }); + const strokeMesh = new THREE.Points(geometry, material); + return strokeMesh; +} diff --git a/src/layer/render/point/drawNormal.js b/src/layer/render/point/drawNormal.js new file mode 100644 index 0000000000..c0c86e231b --- /dev/null +++ b/src/layer/render/point/drawNormal.js @@ -0,0 +1,19 @@ + +import * as THREE from '../../../core/three'; +import PointMaterial from '../../../geom/material/pointMaterial'; +export default function DrawNormal(attributes, style) { + const geometry = new THREE.BufferGeometry(); + const { opacity } = style; + geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); + geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4)); + geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1)); + geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1)); + const material = new PointMaterial({ + u_opacity: opacity + }, { + SHAPE: false, + TEXCOORD_0: false + }); + const strokeMesh = new THREE.Points(geometry, material); + return strokeMesh; +} diff --git a/src/layer/render/point/drawStroke.js b/src/layer/render/point/drawStroke.js new file mode 100644 index 0000000000..8b5c780e48 --- /dev/null +++ b/src/layer/render/point/drawStroke.js @@ -0,0 +1,29 @@ +/** + * @author lzxue + * @email lzx199065@gmail.com + * @create date 2018-11-29 16:35:34 + * @modify date 2018-11-29 16:35:34 + * @desc [description] 绘制图形的边框 +*/ + +import PointLineMaterial from '../../../geom/material/pointLineMaterial'; +import * as THREE from '../../../core/three'; +export default function DrawStroke(attributes, style) { + const { strokeWidth, stroke, strokeOpacity } = style; + const geometry = new THREE.BufferGeometry(); + geometry.setIndex(attributes.indexArray); + geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3)); + geometry.addAttribute('a_shape', new THREE.Float32BufferAttribute(attributes.shapes, 3)); + geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 3)); + geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normal, 3)); + geometry.addAttribute('a_miter', new THREE.Float32BufferAttribute(attributes.miter, 1)); + geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1)); + geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4)); + const material = new PointLineMaterial({ + u_strokeOpacity: strokeOpacity, + u_stroke: stroke, + u_strokeWidth: strokeWidth + }); + const strokeMesh = new THREE.Mesh(geometry, material); + return strokeMesh; +} diff --git a/src/layer/render/point/drawText.js b/src/layer/render/point/drawText.js new file mode 100644 index 0000000000..178f7c0960 --- /dev/null +++ b/src/layer/render/point/drawText.js @@ -0,0 +1,23 @@ +import * as THREE from '../../../core/three'; +import TextMaterial from '../../../geom/material/textMaterial'; +export default function DawText(attributes, style) { + const geometry = new THREE.BufferGeometry(); + const { strokeWidth, stroke, opacity } = style; + geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.originPoints, 3)); + geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.textureElements, 2)); + geometry.addAttribute('a_txtsize', new THREE.Float32BufferAttribute(attributes.textSizes, 2)); + geometry.addAttribute('a_txtOffsets', new THREE.Float32BufferAttribute(attributes.textOffsets, 2)); + geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4)); + const material = new TextMaterial({ + name: this.layerId, + u_texture: buffer.bufferStruct.textTexture, + u_strokeWidth: 1, + u_stroke: stroke, + u_textSize: buffer.bufferStruct.textSize, + u_gamma: 0.11, + u_buffer: 0.8, + u_color: color, + u_glSize: [ width, height ] + }); + const mesh = new THREE.Mesh(geometry, material); +} diff --git a/src/layer/render/point/index.js b/src/layer/render/point/index.js new file mode 100644 index 0000000000..ba399312ab --- /dev/null +++ b/src/layer/render/point/index.js @@ -0,0 +1,4 @@ +export { default as DrawFill } from './drawFill'; +export { default as DrawImage } from './drawImage'; +export { default as DrawStroke } from './drawStroke'; +export { default as DrawNormal } from './drawNormal'; diff --git a/src/map/provider.js b/src/map/provider.js index d341130ffe..19763e8f45 100644 --- a/src/map/provider.js +++ b/src/map/provider.js @@ -23,6 +23,7 @@ export class MapProvider extends Base { initMap() { const mapStyle = this.get('mapStyle'); + switch (mapStyle) { case 'dark' : this.set('mapStyle', Theme.DarkTheme.mapStyle); @@ -31,7 +32,7 @@ export class MapProvider extends Base { this.set('mapStyle', Theme.LightTheme.mapStyle); break; default: - this.set('mapStyle', Theme.LightTheme.mapStyle); + this.set('mapStyle', mapStyle); } this.set('zooms', [ this.get('minZoom'), this.get('maxZoom') ]); this.map = new AMap.Map(this.container, this._attrs); diff --git a/src/source/csvSource.js b/src/source/csvSource.js index 89dc55b1cc..8266d1604b 100644 --- a/src/source/csvSource.js +++ b/src/source/csvSource.js @@ -39,6 +39,10 @@ export default class CSVSource extends Source { getSelectFeatureId(featureId) { return [ featureId ]; } + getSelectFeature(featureId) { + return this.propertiesData[featureId]; + + } _getCoord(geo) { if (geo.geometry) { // GeoJSON feature diff --git a/src/source/geojsonSource.js b/src/source/geojsonSource.js index 0a611e8da9..df38e3fd13 100644 --- a/src/source/geojsonSource.js +++ b/src/source/geojsonSource.js @@ -39,5 +39,9 @@ export default class GeojsonSource extends Source { return selectFeatureIds; } + getSelectFeature(featureId){ + const data = this.get('data'); + return data.features[featureId]; + } } diff --git a/src/track.js b/src/track.js new file mode 100644 index 0000000000..8b75ab2c5a --- /dev/null +++ b/src/track.js @@ -0,0 +1,22 @@ +/** + * @fileOverview track g2 + * @author dxq613@gmail.com + */ +const Global = require('./global'); +const SERVER_URL = 'https://kcart.alipay.com/web/bi.do'; + +// 延迟发送请求 +setTimeout(function() { + if (Global.trackable) { + const image = new Image(); + const newObj = { + pg: document.URL, + r: new Date().getTime(), + l7: true, + version: Global.version, + page_type: 'syslog' + }; + const d = encodeURIComponent(JSON.stringify([ newObj ])); + image.src = `${SERVER_URL}?BIProfile=merge&d=${d}`; + } +}, 3000); \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index f5d9835416..abb0056d8d 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,7 +4,7 @@ const pkg = require('./package.json'); module.exports = { devtool: 'cheap-source-map', entry: { - L7: './src/index.js' + l7: './src/index.js' }, output: { filename: '[name].js',