feat(control): add marker

This commit is contained in:
thinkinggis 2019-08-09 10:16:40 +08:00
parent 45ec241ed3
commit 39e870af09
12 changed files with 372 additions and 13 deletions

View File

@ -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();
});

View File

@ -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

View File

@ -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);
});

View File

@ -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;

146
src/component/marker.js Normal file
View File

@ -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';
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -70,6 +70,7 @@ export default function DrawLine(layerData, layer, buffer) {
u_trailLength: trailLength
});
lineMaterial.setDefinesvalue('ANIMATE', true);
lineMaterial.setDefinesvalue('DASHLINE', true);
}
return lineMesh;
}

18
src/util/anchor.js Normal file
View File

@ -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}`);
}

View File

@ -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;
}