From c9901d2a344d0b0e2bce0d0b5403f17d4a5bf947 Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Fri, 9 Aug 2019 10:16:40 +0800 Subject: [PATCH 1/5] feat(control): add marker --- demos/hz.html | 6 +- demos/taxi.html | 15 ++- demos/vector2.html | 5 + src/component/css/l7.css | 145 +++++++++++++++++++++++++ src/component/marker.js | 146 ++++++++++++++++++++++++++ src/component/popup.js | 11 +- src/geom/shader/meshline_frag.glsl | 9 ++ src/geom/shader/meshline_vert.glsl | 10 +- src/index.js | 3 + src/layer/render/line/drawMeshLine.js | 1 + src/util/anchor.js | 18 ++++ src/util/dom.js | 16 +++ 12 files changed, 372 insertions(+), 13 deletions(-) create mode 100644 src/component/marker.js create mode 100644 src/util/anchor.js diff --git a/demos/hz.html b/demos/hz.html index fe2058e2a1..07a0fe490c 100644 --- a/demos/hz.html +++ b/demos/hz.html @@ -36,13 +36,13 @@ scene.on('loaded', () => { zIndex: 2 }) .source(data) - .size(2) + .size(1) .color('#ff893a') .animate({ - enable:false, + enable:true, interval:0.2, duration:5, - trailLength:0.1 + trailLength:0.2 }) .render(); }); diff --git a/demos/taxi.html b/demos/taxi.html index 359263b8bd..205eb1282b 100644 --- a/demos/taxi.html +++ b/demos/taxi.html @@ -31,16 +31,23 @@ const scene = new L7.Scene({ maxZoom: 18 }); scene.on('loaded', () => { - $.get('https://gw.alipayobjects.com/os/rmsportal/kNDVHmyUWAKhWmWXmjxM.json', data => { + $.get('https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json', data => { scene.LineLayer({ zIndex: 2 }) .source(data) - //.color('#F08D41') + .size([2, 0]) + .shape('line') .color('#ff893a') - .animate({enable:true}) - //.render(); + .animate({ + enable:true, + interval:0.2, + duration:5, + trailLength:0.1 + }) + .render(); }); + $.get('https://gw.alipayobjects.com/os/rmsportal/vmvAxgsEwbpoSWbSYvix.json', data => { buildLayer = scene.PolygonLayer({ zIndex: 2 diff --git a/demos/vector2.html b/demos/vector2.html index 30cf610b4d..4c416d6127 100644 --- a/demos/vector2.html +++ b/demos/vector2.html @@ -114,6 +114,11 @@ scene.on('loaded', () => { "标注": layer3, }; const layerContr = new L7.Control.Layers({overlayers}).addTo(scene); + const popup = new L7.Popup({anchor:'left'}).setText('hello world') + const marker = new L7.Marker({color:'red'}) + .setLnglat([104.838088,34.075889 ]) + .setPopup(popup) + .addTo(scene); }); diff --git a/src/component/css/l7.css b/src/component/css/l7.css index f2de698cc0..93356e0a90 100644 --- a/src/component/css/l7.css +++ b/src/component/css/l7.css @@ -1,3 +1,32 @@ +.l7-marker { + position: absolute; + top: 0; + left: 0; + z-index: 5; +} +.l7-popup-anchor-top, +.l7-popup-anchor-top-left, +.l7-popup-anchor-top-right { + -webkit-flex-direction: column; + flex-direction: column; +} + +.l7-popup-anchor-bottom, +.l7-popup-anchor-bottom-left, +.l7-popup-anchor-bottom-right { + -webkit-flex-direction: column-reverse; + flex-direction: column-reverse; +} + +.l7-popup-anchor-left { + -webkit-flex-direction: row; + flex-direction: row; +} + +.l7-popup-anchor-right { + -webkit-flex-direction: row-reverse; + flex-direction: row-reverse; +} .l7-popup { position: absolute; top: 0; @@ -14,6 +43,122 @@ border: 10px solid transparent; z-index: 1; } +.l7-popup-anchor-top .l7-popup-tip { + -webkit-align-self: center; + align-self: center; + border-top: none; + border-bottom-color: #fff; +} + +.l7-popup-anchor-top-left .l7-popup-tip { + -webkit-align-self: flex-start; + align-self: flex-start; + border-top: none; + border-left: none; + border-bottom-color: #fff; +} + +.l7-popup-anchor-top-right .l7-popup-tip { + -webkit-align-self: flex-end; + align-self: flex-end; + border-top: none; + border-right: none; + border-bottom-color: #fff; +} + +.l7-popup-anchor-bottom .l7-popup-tip { + -webkit-align-self: center; + align-self: center; + border-bottom: none; + border-top-color: #fff; +} + +.l7-popup-anchor-bottom-left .l7-popup-tip { + -webkit-align-self: flex-start; + align-self: flex-start; + border-bottom: none; + border-left: none; + border-top-color: #fff; +} + +.l7-popup-anchor-bottom-right .l7-popup-tip { + -webkit-align-self: flex-end; + align-self: flex-end; + border-bottom: none; + border-right: none; + border-top-color: #fff; +} + +.l7-popup-anchor-left .l7-popup-tip { + -webkit-align-self: center; + align-self: center; + border-left: none; + border-right-color: #fff; +} + +.l7-popup-anchor-right .l7-popup-tip { + -webkit-align-self: center; + align-self: center; + border-right: none; + border-left-color: #fff; +} + +.l7-popup-close-button { + position: absolute; + right: 0; + top: 0; + border: 0; + border-radius: 0 3px 0 0; + cursor: pointer; + background-color: transparent; +} + +.l7-popup-close-button:hover { + background-color: rgba(0, 0, 0, 0.05); +} + +.l7-popup-content { + position: relative; + background: #fff; + border-radius: 3px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + padding: 10px 10px 15px; + pointer-events: auto; +} + +.l7-popup-anchor-top-left .l7-popup-content { + border-top-left-radius: 0; +} + +.l7-popup-anchor-top-right .l7-popup-content { + border-top-right-radius: 0; +} + +.l7-popup-anchor-bottom-left .l7-popup-content { + border-bottom-left-radius: 0; +} + +.l7-popup-anchor-bottom-right .l7-popup-content { + border-bottom-right-radius: 0; +} + +.l7-popup-track-pointer { + display: none; +} + +.l7-popup-track-pointer * { + pointer-events: none; + user-select: none; +} + +.l7-map:hover .l7-popup-track-pointer { + display: flex; +} + +.l7-map:active .l7-popup-track-pointer { + display: none; +} + .l7-popup-close-button { position: absolute; right: 0; diff --git a/src/component/marker.js b/src/component/marker.js new file mode 100644 index 0000000000..22f9b353ad --- /dev/null +++ b/src/component/marker.js @@ -0,0 +1,146 @@ +import Base from '../core/base'; +import { bindAll } from '../util/event'; +import { applyAnchorClass, anchorTranslate } from '../util/anchor'; +import * as DOM from '../util/dom'; +export default class Marker extends Base { + constructor(cfg) { + super({ + element: '', // DOM element + anchor: 'center', + offset: [ 0, 0 ], + color: '#2f54eb', + draggable: false, + ...cfg + + }); + bindAll([ + '_update', + '_onMove', + '_onUp', + '_addDragHandler', + '_onMapClick' + ], this); + this._init(); + } + _init() { + let element = this.get('element'); + if (!element) { + this._defaultMarker = true; + element = DOM.create('div'); + this.set('element', element); + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttributeNS(null, 'display', 'block'); + svg.setAttributeNS(null, 'height', '48px'); + svg.setAttributeNS(null, 'width', '48px'); + svg.setAttributeNS(null, 'viewBox', '0 0 1024 1024'); + + const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + path.setAttributeNS(null, 'd', 'M512 490.666667C453.12 490.666667 405.333333 442.88 405.333333 384 405.333333 325.12 453.12 277.333333 512 277.333333 570.88 277.333333 618.666667 325.12 618.666667 384 618.666667 442.88 570.88 490.666667 512 490.666667M512 85.333333C346.88 85.333333 213.333333 218.88 213.333333 384 213.333333 608 512 938.666667 512 938.666667 512 938.666667 810.666667 608 810.666667 384 810.666667 218.88 677.12 85.333333 512 85.333333Z'); + path.setAttributeNS(null, 'fill', this.get('color')); + svg.appendChild(path); + element.appendChild(svg); + + } + DOM.addClass(element, 'l7-marker'); + element.addEventListener('dragstart', e => { + e.preventDefault(); + }); + element.addEventListener('click', e => { + e.preventDefault(); + this._onMapClick(); + }); + applyAnchorClass(element, this.get('anchor'), 'marker'); + + this._popup = null; + + } + addTo(scene) { + this.remove(); + this._scene = scene; + this._scene.getContainer().appendChild(this.get('element')); + this._scene.on('camerachange', this._update); + this.setDraggable(this.get('draggable')); + this._update(); + // this._scene.on('click', this._onMapClick); + return this; + } + + remove() { + if (this._scene) { + this._scene.off('click', this._onMapClick); + this._scene.off('move', this._update); + this._scene.off('moveend', this._update); + this._scene.off('mousedown', this._addDragHandler); + this._scene.off('touchstart', this._addDragHandler); + this._scene.off('mouseup', this._onUp); + this._scene.off('touchend', this._onUp); + delete this._scene; + } + DOM.remove(this.get('element')); + if (this._popup) this._popup.remove(); + return this; + } + setLnglat(lngLat) { + this._lngLat = lngLat; + if (this._popup) this._popup.setLnglat(this._lngLat); + return this; + } + getLngLat() { + return this._lngLat; + } + + getElement() { + return this.get('element'); + } + + setPopup(popup) { + this._popup = popup; + if (this._lngLat) this._popup.setLnglat(this._lngLat); + return this; + } + + togglePopup() { + const popup = this._popup; + if (!popup) return this; + else if (popup.isOpen()) popup.remove(); + else popup.addTo(this._scene); + return this; + } + + getPopup() { + return this._popup; + } + + getOffset() { + + } + + setDraggable() { + + } + + isDraggable() { + return this._draggable; + } + _update() { + if (!this._scene) return; + this._updatePosition(); + DOM.setTransform(this.get('element'), `${anchorTranslate[ this.get('anchor')]}`); + + } + _onMapClick() { + this._scene.emit('click'); // 触发map点击事件,关闭其他popup + const element = this.get('element'); + + if (this._popup && element) { + this.togglePopup(); + } + } + _updatePosition() { + if (!this._scene) { return; } + const pos = this._pos = this._scene.lngLatToContainer(this._lngLat); + this.get('element').style.left = pos.x + 'px'; + this.get('element').style.top = pos.y + 'px'; + + } +} diff --git a/src/component/popup.js b/src/component/popup.js index 22e99f69e1..9c27d12099 100644 --- a/src/component/popup.js +++ b/src/component/popup.js @@ -1,6 +1,7 @@ import Base from '../core/base'; import { bindAll } from '../util/event'; import * as DOM from '../util/dom'; +import { applyAnchorClass, anchorTranslate } from '../util/anchor'; export default class Popup extends Base { constructor(cfg) { super({ @@ -28,12 +29,13 @@ export default class Popup extends Base { this._update(lngLat); return this; } + _update() { const hasPosition = this.lngLat; if (!this._scene || !hasPosition || !this._content) { return; } if (!this._container) { this._container = this.creatDom('div', 'l7-popup', this._scene.getContainer()); - // this._tip = this.creatDom('div', 'l7-popup-tip', this._container); + this._tip = this.creatDom('div', 'l7-popup-tip', this._container); this._container.appendChild(this._content); if (this.get('className')) { this.get('className').split(' ').forEach(name => @@ -45,13 +47,17 @@ export default class Popup extends Base { } this._updatePosition(); + DOM.setTransform(this._container, `${anchorTranslate[this.get('anchor')]}`); + applyAnchorClass(this._container, this.get('anchor'), 'popup'); } + _updatePosition() { if (!this._scene) { return; } const pos = this._scene.lngLatToContainer(this.lngLat); this._container.style.left = pos.x + 'px'; this._container.style.top = pos.y + 'px'; } + setHTML(html) { const frag = window.document.createDocumentFragment(); const temp = window.document.createElement('body'); @@ -124,4 +130,7 @@ export default class Popup extends Base { this.emit('close'); return this; } + isOpen() { + return !!this._scene; + } } diff --git a/src/geom/shader/meshline_frag.glsl b/src/geom/shader/meshline_frag.glsl index debc84c992..e786fd293b 100644 --- a/src/geom/shader/meshline_frag.glsl +++ b/src/geom/shader/meshline_frag.glsl @@ -20,6 +20,12 @@ varying float v_texture_y; varying float v_texture_percent; #endif +#ifdef ANIMATE +uniform float u_duration : 2.0; +uniform float u_interval : 1.0; +uniform float u_trailLength : 0.2; +#endif + void main() { #ifdef TEXTURE float texture_y_fract = fract(v_texture_y); @@ -40,6 +46,9 @@ void main() { gl_FragColor.a *= u_opacity; #endif #ifdef ANIMATE + float alpha =1.0 - fract( mod(1.0- v_distance_ratio,u_interval)* (1.0/u_interval) + u_time / u_duration); + alpha = (alpha + u_trailLength -1.0) / u_trailLength; + v_time = clamp(alpha,0.,1.); gl_FragColor.a *= v_time; #endif // anti-alias diff --git a/src/geom/shader/meshline_vert.glsl b/src/geom/shader/meshline_vert.glsl index f8031ad4e3..0d742e04c6 100644 --- a/src/geom/shader/meshline_vert.glsl +++ b/src/geom/shader/meshline_vert.glsl @@ -57,11 +57,11 @@ void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4(position.xy + offset.xy, 0., 1.0); // gl_Position.z -=0.8 * gl_Position.w; - #ifdef ANIMATE - float alpha =1.0 - fract( mod(1.0- distance_ratio,u_interval)* (1.0/u_interval) + u_time / u_duration); - alpha = (alpha + u_trailLength -1.0) / u_trailLength; - v_time = clamp(alpha,0.,1.); - #endif + // #ifdef ANIMATE + // float alpha =1.0 - fract( mod(1.0- distance_ratio,u_interval)* (1.0/u_interval) + u_time / u_duration); + // alpha = (alpha + u_trailLength -1.0) / u_trailLength; + // v_time = clamp(alpha,0.,1.); + // #endif // picking if(pickingId == u_activeId) { diff --git a/src/index.js b/src/index.js index 4f8da9a530..7d52591507 100755 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,9 @@ import { registerParser, registerTransform } from './source'; import { registerInteraction, getInteraction } from './interaction'; import { registerLayer } from './layer'; import Popup from './component/popup'; +import Marker from './component/marker'; import * as Control from './component/control'; + const version = Global.version; const exported = { version, @@ -20,6 +22,7 @@ const exported = { registerInteraction, getInteraction, Popup, + Marker, Control }; export default exported; diff --git a/src/layer/render/line/drawMeshLine.js b/src/layer/render/line/drawMeshLine.js index 6b81e0da3c..953085b537 100644 --- a/src/layer/render/line/drawMeshLine.js +++ b/src/layer/render/line/drawMeshLine.js @@ -70,6 +70,7 @@ export default function DrawLine(layerData, layer, buffer) { u_trailLength: trailLength }); lineMaterial.setDefinesvalue('ANIMATE', true); + lineMaterial.setDefinesvalue('DASHLINE', true); } return lineMesh; } diff --git a/src/util/anchor.js b/src/util/anchor.js new file mode 100644 index 0000000000..98cc65be71 --- /dev/null +++ b/src/util/anchor.js @@ -0,0 +1,18 @@ +export const anchorTranslate = { + center: 'translate(-50%,-50%)', + top: 'translate(-50%,0)', + 'top-left': 'translate(0,0)', + 'top-right': 'translate(-100%,0)', + bottom: 'translate(-50%,-100%)', + 'bottom-left': 'translate(0,-100%)', + 'bottom-right': 'translate(-100%,-100%)', + left: 'translate(0,-50%)', + right: 'translate(-100%,-50%)' +}; +export function applyAnchorClass(element, anchor, prefix) { + const classList = element.classList; + for (const key in anchorTranslate) { + classList.remove(`l7-${prefix}-anchor-${key}`); + } + classList.add(`l7-${prefix}-anchor-${anchor}`); +} diff --git a/src/util/dom.js b/src/util/dom.js index 9c41f1f823..f71fa6c088 100644 --- a/src/util/dom.js +++ b/src/util/dom.js @@ -1,4 +1,14 @@ import * as Util from './util'; +const docStyle = window.document.documentElement.style; +function testProp(props) { + if (!docStyle) return props[0]; + for (let i = 0; i < props.length; i++) { + if (props[i] in docStyle) { + return props[i]; + } + } + return props[0]; +} export function create(tagName, className, container) { const el = document.createElement(tagName); el.className = className || ''; @@ -78,3 +88,9 @@ export function empty(el) { el.removeChild(el.firstChild); } } + +const transformProp = testProp([ 'transform', 'WebkitTransform' ]); + +export function setTransform(el, value) { + el.style[transformProp] = value; +} From ee3244bec79bc87bb187a93e227f371aeb7c8f80 Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Mon, 12 Aug 2019 10:35:50 +0800 Subject: [PATCH 2/5] =?UTF-8?q?perf(shader):=20=E4=BC=98=E5=8C=96=E7=BA=BF?= =?UTF-8?q?=E5=8A=A8=E7=94=BB=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demos/01_circle.html | 11 ++- demos/hz.html | 97 ++++++++++++++++++++++++--- demos/marker.html | 96 ++++++++++++++++++++++++++ demos/vector2.html | 26 ++++--- src/component/control/zoom.js | 18 ++--- src/component/marker.js | 34 ++++++++-- src/component/popup.js | 6 +- src/core/scene.js | 2 +- src/geom/buffer/line/arcline.js | 3 + src/geom/shader/meshline_frag.glsl | 9 +-- src/geom/shader/meshline_vert.glsl | 10 +-- src/layer/line_layer.js | 5 ++ src/layer/render/line/drawMeshLine.js | 10 +-- src/map/AMap.js | 2 +- src/map/mapbox.js | 2 +- src/worker/workerTile.js | 3 +- 16 files changed, 275 insertions(+), 59 deletions(-) create mode 100644 demos/marker.html diff --git a/demos/01_circle.html b/demos/01_circle.html index a8fa80d791..45526361b8 100644 --- a/demos/01_circle.html +++ b/demos/01_circle.html @@ -13,7 +13,6 @@ - + + +
+ + + + + + + + + diff --git a/demos/vector2.html b/demos/vector2.html index 4c416d6127..45db086525 100644 --- a/demos/vector2.html +++ b/demos/vector2.html @@ -25,7 +25,7 @@ const scene = new L7.Scene({ id: 'map', - mapStyle: 'light', // 样式URL + mapStyle: 'dark', // 样式URL center: [104.838088,34.075889 ], pitch: 0, hash:false, @@ -42,7 +42,7 @@ scene.on('loaded', () => { attributeCtr.addTo(scene); scene.addTileSource('test',{ - url:'http://127.0.0.1:8080/{z}/{x}/{y}.pbf', + url:' https://mvt.amap.com/district/CHN2/{z}/{x}/{y}/4096?key=608d75903d29ad471362f8c58c550daf', type:'vector', minZoom: 0, maxZoom:9 @@ -54,8 +54,8 @@ scene.on('loaded', () => { .source('test',{ parser:{ type: 'mvt', - sourceLayer:'boundaries_admin_3', - idField:'id' + sourceLayer:'CHN_Cities', + idField:'adcode' } }) .shape('fill') @@ -70,20 +70,21 @@ scene.on('loaded', () => { const { lnglat, feature } = e; const popup = new L7.Popup() .setLnglat([lnglat.lng, lnglat.lat]) - .setHTML(feature.properties.id).addTo(scene); + .setHTML(feature.properties.NAME_CHN.toString()).addTo(scene); }) - const layer2 = scene.PolygonLayer({ + + const layer2 = scene.LineLayer({ zIndex:10, }) .source('test',{ parser:{ type: 'mvt', - sourceLayer:'boundaries_admin_3', - idField:'id' + sourceLayer:'CHN_L', + idField:'adcode' } }) .shape('line') - .size(1) + .size(2) .active(false) .color('#fff') .style({ @@ -91,6 +92,7 @@ scene.on('loaded', () => { }) .render(); +/** const layer3 = scene.PointLayer({ zIndex:10, }) @@ -109,13 +111,15 @@ scene.on('loaded', () => { opacity:1.0 }) .render(); + **/ const overlayers = { "行政区划": layer, - "标注": layer3, + "行政区边界": layer2, }; + const layerContr = new L7.Control.Layers({overlayers}).addTo(scene); const popup = new L7.Popup({anchor:'left'}).setText('hello world') - const marker = new L7.Marker({color:'red'}) + const marker = new L7.Marker({color:'blue'}) .setLnglat([104.838088,34.075889 ]) .setPopup(popup) .addTo(scene); diff --git a/src/component/control/zoom.js b/src/component/control/zoom.js index 52aa33dfac..a8ccdd7c60 100644 --- a/src/component/control/zoom.js +++ b/src/component/control/zoom.js @@ -12,8 +12,9 @@ export default class Zoom extends Control { ...cfg }); bindAll([ '_updateDisabled', '_zoomIn', '_zoomOut' ], this); + this._disabled = false; } - onAdd() { + onAdd(scene) { const zoomName = 'l7-control-zoom'; const container = DOM.create('div', zoomName + ' l7-bar'); @@ -21,14 +22,14 @@ export default class Zoom extends Control { zoomName + '-in', container, this._zoomIn); this._zoomOutButton = this._createButton(this.get('zoomOutText'), this.get('zoomOutTitle'), zoomName + '-out', container, this._zoomOut); + scene.on('zoomend', this._updateDisabled); + scene.on('zoomchange', this._updateDisabled); this._updateDisabled(); - this._scene.on('zoomend', this._updateDisabled); - this._scene.on('zoomchange', this._updateDisabled); return container; } - onRemove() { - this._scene.off('zoomend', this._updateDisabled); - this._scene.off('zoomchange', this._updateDisabled); + onRemove(scene) { + scene.off('zoomend', this._updateDisabled); + scene.off('zoomchange', this._updateDisabled); } disable() { this._disabled = true; @@ -63,11 +64,10 @@ export default class Zoom extends Control { const className = 'l7-disabled'; DOM.removeClass(this._zoomInButton, className); DOM.removeClass(this._zoomOutButton, className); - - if (this._disabled || scene.getZoom() === scene.get('minZoom')) { + if (this._disabled || scene.getZoom() <= scene.get('minZoom')) { DOM.addClass(this._zoomOutButton, className); } - if (this._disabled || scene._zoom === scene.get('maxZoom')) { + if (this._disabled || scene.getZoom() >= scene.get('maxZoom')) { DOM.addClass(this._zoomInButton, className); } } diff --git a/src/component/marker.js b/src/component/marker.js index 22f9b353ad..75e17c7a8b 100644 --- a/src/component/marker.js +++ b/src/component/marker.js @@ -42,12 +42,8 @@ export default class Marker extends Base { } DOM.addClass(element, 'l7-marker'); - element.addEventListener('dragstart', e => { - e.preventDefault(); - }); element.addEventListener('click', e => { - e.preventDefault(); - this._onMapClick(); + this._onMapClick(e); }); applyAnchorClass(element, this.get('anchor'), 'marker'); @@ -61,7 +57,6 @@ export default class Marker extends Base { this._scene.on('camerachange', this._update); this.setDraggable(this.get('draggable')); this._update(); - // this._scene.on('click', this._onMapClick); return this; } @@ -142,5 +137,32 @@ export default class Marker extends Base { this.get('element').style.left = pos.x + 'px'; this.get('element').style.top = pos.y + 'px'; + } + _bubbleUp() { + const eventsName = [ + 'mouseout', + 'mouseover', + 'mousemove', + 'mousedown', + 'mouseleave', + 'mouseup', + 'rightclick', + 'click', + 'dblclick', + 'wheel' + ]; + const element = this.get('element'); + eventsName.forEach(event => { + element.addEventListener(event, e => { + this._scene.emit(event, e); + }); + }); + } + + _addDragHandler() { + + } + _onUp() { + } } diff --git a/src/component/popup.js b/src/component/popup.js index 9c27d12099..31f8d02759 100644 --- a/src/component/popup.js +++ b/src/component/popup.js @@ -18,13 +18,13 @@ export default class Popup extends Base { if (this.get('closeOnClick')) { this._scene.on('click', this._onClickClose); } - this._scene.on('mapmove', this._update); + this._scene.on('camerachange', this._update); this._update(); } setLnglat(lngLat) { this.lngLat = lngLat; if (this._scene) { - this._scene.on('mapmove', this._update); + this._scene.on('camerachange', this._update); } this._update(lngLat); return this; @@ -123,7 +123,7 @@ export default class Popup extends Base { delete this._container; } if (this._scene) { - this._scene.off('mapmove', this._update); + this._scene.off('camerachange', this._update); this._scene.off('click', this._onClickClose); delete this._scene; } diff --git a/src/core/scene.js b/src/core/scene.js index 14dec56845..16e5b7e781 100644 --- a/src/core/scene.js +++ b/src/core/scene.js @@ -20,7 +20,6 @@ export default class Scene extends Base { super(cfg); this._initMap(); this.crs = epsg3857; - this._initContoller(); // this._initAttribution(); // 暂时取消,后面作为组件去加载 this.addImage(); this.fontAtlasManager = new FontAtlasManager(); @@ -68,6 +67,7 @@ export default class Scene extends Base { interaction._onHashChange(); } this.style = new Style(this, {}); + this._initContoller(); this.emit('loaded'); this._engine.update(); }); diff --git a/src/geom/buffer/line/arcline.js b/src/geom/buffer/line/arcline.js index cdd5bcdd2b..e5cd7a2266 100644 --- a/src/geom/buffer/line/arcline.js +++ b/src/geom/buffer/line/arcline.js @@ -5,6 +5,9 @@ export default class ArcLineBuffer extends BufferBase { layerData.forEach((feature, index) => { this._calculateArc(feature, index); }); + this.hasPattern = layerData.some(layer => { + return layer.pattern; + }); } _initAttributes() { super._initAttributes(); diff --git a/src/geom/shader/meshline_frag.glsl b/src/geom/shader/meshline_frag.glsl index e786fd293b..1162b985f2 100644 --- a/src/geom/shader/meshline_frag.glsl +++ b/src/geom/shader/meshline_frag.glsl @@ -6,7 +6,8 @@ uniform float u_dash_ratio : 0.0; uniform float u_blur : 0.9; varying vec4 v_color; -#ifdef DASHLINE +uniform float u_time : 0; +#if defined DASHLINE || defined ANIMATE varying float v_distance_ratio; #endif varying float v_dash_array; @@ -41,15 +42,15 @@ void main() { #endif #ifdef DASHLINE - gl_FragColor.a *= u_opacity * ceil(mod(v_distance_ratio + u_dash_offset, v_dash_array) - (v_dash_array * u_dash_ratio)); + gl_FragColor.a *= u_opacity * ceil(mod(v_distance_ratio + u_dash_offset + u_time / 10., v_dash_array) - (v_dash_array * u_dash_ratio)); #else gl_FragColor.a *= u_opacity; #endif #ifdef ANIMATE float alpha =1.0 - fract( mod(1.0- v_distance_ratio,u_interval)* (1.0/u_interval) + u_time / u_duration); alpha = (alpha + u_trailLength -1.0) / u_trailLength; - v_time = clamp(alpha,0.,1.); - gl_FragColor.a *= v_time; + alpha = smoothstep(0., 1., alpha); + gl_FragColor.a *= alpha; #endif // anti-alias float blur = 1. - smoothstep(u_blur, 1., length(v_normal)); diff --git a/src/geom/shader/meshline_vert.glsl b/src/geom/shader/meshline_vert.glsl index 0d742e04c6..1a5c3c9e6f 100644 --- a/src/geom/shader/meshline_vert.glsl +++ b/src/geom/shader/meshline_vert.glsl @@ -14,7 +14,7 @@ varying float v_time; varying vec4 v_color; varying float v_dash_array; varying vec2 v_normal; -#ifdef DASHLINE +#if defined DASHLINE || defined ANIMATE varying float v_distance_ratio; #endif @@ -37,7 +37,7 @@ void main() { v_color = a_color; v_dash_array = a_dash_array; float distance_ratio = a_distance / a_total_distance; - #ifdef DASHLINE +#if defined DASHLINE || defined ANIMATE v_distance_ratio = distance_ratio; #endif #ifdef TEXTURE @@ -57,12 +57,6 @@ void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4(position.xy + offset.xy, 0., 1.0); // gl_Position.z -=0.8 * gl_Position.w; - // #ifdef ANIMATE - // float alpha =1.0 - fract( mod(1.0- distance_ratio,u_interval)* (1.0/u_interval) + u_time / u_duration); - // alpha = (alpha + u_trailLength -1.0) / u_trailLength; - // v_time = clamp(alpha,0.,1.); - // #endif - // picking if(pickingId == u_activeId) { v_color = u_activeColor; diff --git a/src/layer/line_layer.js b/src/layer/line_layer.js index 7e70f0daa9..0b96e55129 100644 --- a/src/layer/line_layer.js +++ b/src/layer/line_layer.js @@ -1,8 +1,13 @@ import Layer from '../core/layer'; import { getRender } from './render'; export default class LineLayer extends Layer { + constructor(scene, cfg) { + super(scene, cfg); + this.set('type', 'line'); + } shape(type) { this.shapeType = type; + this.set('shape', type); return this; } preRender() { diff --git a/src/layer/render/line/drawMeshLine.js b/src/layer/render/line/drawMeshLine.js index 953085b537..a2d29d7160 100644 --- a/src/layer/render/line/drawMeshLine.js +++ b/src/layer/render/line/drawMeshLine.js @@ -9,9 +9,9 @@ export default function DrawLine(layerData, layer, buffer) { const activeOption = layer.get('activedOptions'); // const pattern = style.pattern; // const texture = layer.scene.image.singleImages[pattern]; - const hasPattern = layerData.some(layer => { - return layer.pattern; - }); + // const hasPattern = layerData.some(layer => { + // return layer.pattern; + // }); if (!buffer) { const geometryBuffer = getBuffer(layer.type, layer.shapeType); buffer = new geometryBuffer({ @@ -22,7 +22,7 @@ export default function DrawLine(layerData, layer, buffer) { }); } - const { attributes, indexArray } = buffer; + const { attributes, indexArray, hasPattern } = buffer; const geometry = new THREE.BufferGeometry(); @@ -70,7 +70,7 @@ export default function DrawLine(layerData, layer, buffer) { u_trailLength: trailLength }); lineMaterial.setDefinesvalue('ANIMATE', true); - lineMaterial.setDefinesvalue('DASHLINE', true); + // lineMaterial.setDefinesvalue('DASHLINE', true); } return lineMesh; } diff --git a/src/map/AMap.js b/src/map/AMap.js index b30a0e0f30..da40418842 100644 --- a/src/map/AMap.js +++ b/src/map/AMap.js @@ -33,7 +33,7 @@ export default class GaodeMap extends Base { this.addOverLayer(); setTimeout(() => { this.emit('mapLoad'); - }, 100); + }, 10); } initMap() { diff --git a/src/map/mapbox.js b/src/map/mapbox.js index b3e7ddf875..cba77624b0 100644 --- a/src/map/mapbox.js +++ b/src/map/mapbox.js @@ -26,7 +26,7 @@ export default class MapBox extends Base { this.addOverLayer(); setTimeout(() => { this.emit('mapLoad'); - }, 100); + }, 10); } diff --git a/src/worker/workerTile.js b/src/worker/workerTile.js index 46e4e97373..a3bfa3220d 100644 --- a/src/worker/workerTile.js +++ b/src/worker/workerTile.js @@ -40,7 +40,8 @@ export default class WorkerTile { const geometryBuffer = getBuffer(style.type, style.shape); const buffer = new geometryBuffer({ layerData: tileMapping.layerData, - shape: style.shape + shape: style.shape, + style }); sourceLayerData[style.layerId] = { buffer: { From b97c928c74183e8b0f07d3b26b34a47c962248ec Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Mon, 12 Aug 2019 14:52:50 +0800 Subject: [PATCH 3/5] refactor(map): container layout --- demos/hz.html | 76 ++--------------------------------------- demos/marker.html | 17 ++++++++- src/component/marker.js | 4 +-- src/component/popup.js | 6 +++- src/core/scene.js | 5 ++- src/map/AMap.js | 11 ++++-- 6 files changed, 37 insertions(+), 82 deletions(-) diff --git a/demos/hz.html b/demos/hz.html index cda1db3e96..4fd902d60b 100644 --- a/demos/hz.html +++ b/demos/hz.html @@ -30,84 +30,12 @@ const scene = new L7.Scene({ ], pitch:0, zoom: 5, + showBuildingBlock:false, minZoom: 0, maxZoom: 18 }); -const lineData = { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "properties": {}, - "geometry": { - "type": "LineString", - "coordinates": [ - [ - 117.02636718749999, - 37.79676317682161 - ], - [ - 117.20214843749999, - 37.23032838760387 - ], - [ - 117.31201171875001, - 36.756490329505176 - ], - [ - 117.43286132812499, - 36.38591277287651 - ], - [ - 117.586669921875, - 35.871246850027966 - ], - [ - 117.76245117187499, - 35.25459097465022 - ], - [ - 117.90527343750001, - 34.732584206123626 - ], - [ - 117.99316406249999, - 33.8339199536547 - ], - [ - 117.97119140625, - 33.119150226768866 - ], - [ - 117.48779296875, - 32.80574473290688 - ], - [ - 116.773681640625, - 32.713355353177555 - ], - [ - 115.67504882812501, - 32.704111144407406 - ], - [ - 114.510498046875, - 32.85190345738802 - ], - [ - 113.818359375, - 33.61461929233378 - ], - [ - 113.70849609375, - 33.970697997361626 - ] - ] - } - } - ] -} + scene.on('loaded', () => { $.get('https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json', data => { scene.LineLayer({ diff --git a/demos/marker.html b/demos/marker.html index bcd8759afe..0cd4187f5e 100644 --- a/demos/marker.html +++ b/demos/marker.html @@ -31,6 +31,22 @@ }); window.scene = scene; scene.on('loaded', function() { + $.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)=>{ + return feature.properties; + }) + + const layer = scene.PolygonLayer({ + zIndex:1, + }) + .source(region) + .color('cname',(value)=>{ + return (value =='中国' ? 'rgba(46,149,169,0.45)': 'rgba(227,244,244,0.1)'); + }) + .shape('fill') + .render(); + }); $.getJSON('https://gw.alipayobjects.com/os/basement_prod/0b96cca4-7e83-449a-93d0-2a77053e74ab.json', function(data) { console.log(data); data.nodes.forEach(item=>{ @@ -38,7 +54,6 @@ const total = item.gdp.Agriculture + item.gdp.Industry + item.gdp.Service; const size =Math.max(Math.min(parseInt(total / 20000), 150),40) - console.log(item.name, size); var data = [{ item: 'Agriculture', count: item.gdp.Agriculture, diff --git a/src/component/marker.js b/src/component/marker.js index 75e17c7a8b..1e9385f5f1 100644 --- a/src/component/marker.js +++ b/src/component/marker.js @@ -53,7 +53,7 @@ export default class Marker extends Base { addTo(scene) { this.remove(); this._scene = scene; - this._scene.getContainer().appendChild(this.get('element')); + this._scene.getMarkerContainer().appendChild(this.get('element')); this._scene.on('camerachange', this._update); this.setDraggable(this.get('draggable')); this._update(); @@ -124,7 +124,7 @@ export default class Marker extends Base { } _onMapClick() { - this._scene.emit('click'); // 触发map点击事件,关闭其他popup + // this._scene.emit('click'); // 触发map点击事件,关闭其他popup const element = this.get('element'); if (this._popup && element) { diff --git a/src/component/popup.js b/src/component/popup.js index 31f8d02759..d88c1457e4 100644 --- a/src/component/popup.js +++ b/src/component/popup.js @@ -34,13 +34,17 @@ export default class Popup extends Base { const hasPosition = this.lngLat; if (!this._scene || !hasPosition || !this._content) { return; } if (!this._container) { - this._container = this.creatDom('div', 'l7-popup', this._scene.getContainer()); + this._container = this.creatDom('div', 'l7-popup', this._scene.getMarkerContainer().parentNode); + this._tip = this.creatDom('div', 'l7-popup-tip', this._container); this._container.appendChild(this._content); if (this.get('className')) { this.get('className').split(' ').forEach(name => this._container.classList.add(name)); } + this._container.addEventListener('mousedown', e => { + e.stopPropagation(); + }); } if (this.get('maxWidth') && this._container.style.maxWidth !== this.get('maxWidth')) { this._container.style.maxWidth = this.get('maxWidth'); diff --git a/src/core/scene.js b/src/core/scene.js index 16e5b7e781..7c102a61cf 100644 --- a/src/core/scene.js +++ b/src/core/scene.js @@ -20,7 +20,6 @@ export default class Scene extends Base { super(cfg); this._initMap(); this.crs = epsg3857; - // this._initAttribution(); // 暂时取消,后面作为组件去加载 this.addImage(); this.fontAtlasManager = new FontAtlasManager(); this._layers = []; @@ -54,6 +53,7 @@ export default class Scene extends Base { const Map = new MapProvider(this._attrs); Map.mixMap(this); this._container = Map.container; + this._markerContainier = Map.l7_marker_Container; Map.on('mapLoad', () => { this.map = Map.map; this._initEngine(Map.renderDom); @@ -122,6 +122,9 @@ export default class Scene extends Base { getContainer() { return this._container; } + getMarkerContainer() { + return this._markerContainier; + } _registEvents() { const events = [ 'mouseout', diff --git a/src/map/AMap.js b/src/map/AMap.js index da40418842..2b203944c4 100644 --- a/src/map/AMap.js +++ b/src/map/AMap.js @@ -59,6 +59,7 @@ export default class GaodeMap extends Base { } else { this.map = new AMap.Map(this.container, this._attrs); } + this.amapContainer = this.map.getContainer().getElementsByClassName('amap-maps')[0]; } asyncCamera(engine) { this._engine = engine; @@ -96,13 +97,17 @@ export default class GaodeMap extends Base { return this.projectFlat(this.getCenter()); } addOverLayer() { - const canvasContainer = this.container instanceof HTMLElement ? this.container : document.getElementById(this.container); - this.canvasContainer = canvasContainer; + // const canvasContainer = this.container instanceof HTMLElement ? this.container : document.getElementById(this.container); + // this.canvasContainer = canvasContainer; this.renderDom = document.createElement('div'); this.renderDom.style.cssText += 'position: absolute;top: 0; z-index:1;height: 100%;width: 100%;pointer-events: none;'; this.renderDom.id = 'l7_canvaslayer'; - canvasContainer.appendChild(this.renderDom); + + this.amapContainer.appendChild(this.renderDom); + this.l7_marker_Container = document.createElement('div'); + this.l7_marker_Container.className = 'l7_marker'; + this.amapContainer.appendChild(this.l7_marker_Container); } mixMap(scene) { const map = this.map; From 109780f9e8ec7bd60191912ff8e6161ce9c5c9fd Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Tue, 13 Aug 2019 17:26:27 +0800 Subject: [PATCH 4/5] refactor(camera): update camera async --- demos/07_city.html | 2 +- demos/line_bug.html | 63 +++++++++++++++++++++++++++++++ src/core/layer.js | 3 -- src/core/scene.js | 9 ++--- src/geom/buffer/line/meshline.js | 3 ++ src/geom/shader/arcline_frag.glsl | 4 +- src/layer/render/line/drawArc.js | 2 +- src/map/AMap.js | 58 +++++++++++++++------------- 8 files changed, 105 insertions(+), 39 deletions(-) create mode 100644 demos/line_bug.html diff --git a/demos/07_city.html b/demos/07_city.html index 0b5acd860f..755c1573e8 100644 --- a/demos/07_city.html +++ b/demos/07_city.html @@ -17,7 +17,7 @@
- + + + + + + + diff --git a/src/core/layer.js b/src/core/layer.js index f6fcb6de4f..228057ba08 100644 --- a/src/core/layer.js +++ b/src/core/layer.js @@ -89,7 +89,6 @@ export default class Layer extends Base { if (object.type === 'composer') { this._object3D = object; this.scene._engine.composerLayers.push(object); - setTimeout(() => this.scene._engine.update(), 500); return; } type === 'fill' ? this.layerMesh = object : this.layerLineMesh = object; @@ -110,8 +109,6 @@ export default class Layer extends Base { if (type === 'fill') { this.get('pickingController').addPickMesh(object); } - this.scene._engine.update(); - // setTimeout(() => this.scene._engine.update(), 200); } remove(object) { if (object.type === 'composer') { diff --git a/src/core/scene.js b/src/core/scene.js index 7c102a61cf..a94034fd1a 100644 --- a/src/core/scene.js +++ b/src/core/scene.js @@ -29,7 +29,7 @@ export default class Scene extends Base { _initEngine(mapContainer) { this._engine = new Engine(mapContainer, this); this.registerMapEvent(); - // this._engine.run(); + this._engine.run(); compileBuiltinModules(); } _initContoller() { @@ -59,7 +59,7 @@ export default class Scene extends Base { this._initEngine(Map.renderDom); Map.asyncCamera(this._engine); this.initLayer(); - this._registEvents(); + // this._registEvents(); const hash = this.get('hash'); if (hash) { const Ctor = getInteraction('hash'); @@ -69,7 +69,6 @@ export default class Scene extends Base { this.style = new Style(this, {}); this._initContoller(); this.emit('loaded'); - this._engine.update(); }); } initLayer() { @@ -176,13 +175,13 @@ export default class Scene extends Base { registerMapEvent() { this._updateRender = () => this._engine.update(); this.map.on('mousemove', this._updateRender); - this.map.on('mapmove', this._updateRender); + // this.map.on('mapmove', this._updateRender); this.map.on('camerachange', this._updateRender); } unRegsterMapEvent() { this.map.off('mousemove', this._updateRender); - this.map.off('mapmove', this._updateRender); + // this.map.off('mapmove', this._updateRender); this.map.off('camerachange', this._updateRender); } // control diff --git a/src/geom/buffer/line/meshline.js b/src/geom/buffer/line/meshline.js index 196e381e2c..38e7cae96a 100644 --- a/src/geom/buffer/line/meshline.js +++ b/src/geom/buffer/line/meshline.js @@ -7,6 +7,9 @@ export default class MeshLineBuffer extends BufferBase { this._calculateLine(feature); delete feature.bufferInfo; }); + this.hasPattern = layerData.some(layer => { + return layer.pattern; + }); } _initAttributes() { super._initAttributes(); diff --git a/src/geom/shader/arcline_frag.glsl b/src/geom/shader/arcline_frag.glsl index 8797501ca2..9b3ec4a32f 100644 --- a/src/geom/shader/arcline_frag.glsl +++ b/src/geom/shader/arcline_frag.glsl @@ -6,8 +6,8 @@ if(v_color.a == 0.){ discard; } - #pragma include "pick" + gl_FragColor = v_color; gl_FragColor.a = v_color.a*u_opacity; - + #pragma include "pick" } \ No newline at end of file diff --git a/src/layer/render/line/drawArc.js b/src/layer/render/line/drawArc.js index 811c18023d..dd70ae5920 100644 --- a/src/layer/render/line/drawArc.js +++ b/src/layer/render/line/drawArc.js @@ -17,10 +17,10 @@ export default function DrawArcLine(layerData, layer, buffer) { const geometry = new THREE.BufferGeometry(); geometry.setIndex(new THREE.Uint32BufferAttribute(indexArray, 1)); geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3)); + geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1)); geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4)); geometry.addAttribute('a_instance', new THREE.Float32BufferAttribute(attributes.instanceArray, 4)); geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1)); - const lineMaterial = new ArcLineMaterial({ u_opacity: style.opacity, u_zoom: layer.scene.getZoom(), diff --git a/src/map/AMap.js b/src/map/AMap.js index 2b203944c4..8e0fc255c9 100644 --- a/src/map/AMap.js +++ b/src/map/AMap.js @@ -30,10 +30,6 @@ export default class GaodeMap extends Base { super(cfg); this.container = document.getElementById(this.get('id')); this.initMap(); - this.addOverLayer(); - setTimeout(() => { - this.emit('mapLoad'); - }, 10); } initMap() { @@ -56,35 +52,42 @@ export default class GaodeMap extends Base { this.map = map; this.container = map.getContainer(); this.get('mapStyle') && this.map.setMapStyle(this.get('mapStyle')); + this.addOverLayer(); + this.emit('mapLoad'); } else { this.map = new AMap.Map(this.container, this._attrs); + this.map.on('complete', () => { + this.addOverLayer(); + this.emit('mapLoad'); + }); } - this.amapContainer = this.map.getContainer().getElementsByClassName('amap-maps')[0]; + } asyncCamera(engine) { this._engine = engine; - const camera = engine._camera; - this.map.on('camerachange', e => { - const mapCamera = e.camera; - let { fov, near, far, height, pitch, rotation, aspect } = mapCamera; - pitch *= DEG2RAD; - rotation *= DEG2RAD; - camera.fov = (180 * fov) / Math.PI; - camera.aspect = aspect; - camera.near = near; - camera.far = far; - camera.updateProjectionMatrix(); - camera.position.z = height * Math.cos(pitch); - camera.position.x = height * Math.sin(pitch) * Math.sin(rotation); - camera.position.y = -height * Math.sin(pitch) * Math.cos(rotation); - camera.up.x = -Math.cos(pitch) * Math.sin(rotation); - camera.up.y = Math.cos(pitch) * Math.cos(rotation); - camera.up.z = Math.sin(pitch); - camera.lookAt(0, 0, 0); - camera.position.x += e.camera.position.x; - camera.position.y += -e.camera.position.y; - this._engine.update(); - }); + this.updateCamera(); + this.map.on('camerachange', this.updateCamera.bind(this)); + } + updateCamera() { + const camera = this._engine._camera; + const mapCamera = this.map.getCameraState(); + let { fov, near, far, height, pitch, rotation, aspect } = mapCamera; + pitch *= DEG2RAD; + rotation *= DEG2RAD; + camera.fov = (180 * fov) / Math.PI; + camera.aspect = aspect; + camera.near = near; + camera.far = far; + camera.updateProjectionMatrix(); + camera.position.z = height * Math.cos(pitch); + camera.position.x = height * Math.sin(pitch) * Math.sin(rotation); + camera.position.y = -height * Math.sin(pitch) * Math.cos(rotation); + camera.up.x = -Math.cos(pitch) * Math.sin(rotation); + camera.up.y = Math.cos(pitch) * Math.cos(rotation); + camera.up.z = Math.sin(pitch); + camera.lookAt(0, 0, 0); + camera.position.x += mapCamera.position.x; + camera.position.y += -mapCamera.position.y; } projectFlat(lnglat) { @@ -99,6 +102,7 @@ export default class GaodeMap extends Base { addOverLayer() { // const canvasContainer = this.container instanceof HTMLElement ? this.container : document.getElementById(this.container); // this.canvasContainer = canvasContainer; + 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;'; From 65a910926eef94bb0c5f9011aa0d8b0a7937ebeb Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Tue, 13 Aug 2019 17:43:49 +0800 Subject: [PATCH 5/5] fix(travis); update node version --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fee155eca2..30ee13076f 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: node_js node_js: - - "8" + - "12" env: matrix: @@ -11,6 +11,7 @@ addons: apt: packages: - xvfb + - libgconf-2-4 install: - export DISPLAY=':99.0'