Merge pull request #11 from antvis/marker

新增地图组件
放大缩小
比例尺
图层列表
marker
popup
This commit is contained in:
@thinkinggis 2019-08-13 17:49:10 +08:00 committed by GitHub
commit 11eb6f0690
28 changed files with 697 additions and 100 deletions

View File

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

View File

@ -13,7 +13,6 @@
<script>/*Fixing iframe window.innerHeight 0 issue in Safari*/ document.body.clientHeight; </script>
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
<script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
<link rel=stylesheet type=text/css href='../build/l7.css'>
<script src="../build/l7.js"></script>
<style>
#map { position:absolute; top:0; bottom:0; width:100%; }
@ -24,6 +23,8 @@
mapStyle: 'light', // 样式URL
center: [120.19382669582967, 30.258134],
pitch: 0,
minZoom:5,
maxZoom:15,
zoom: 12
});
window.scene = scene;
@ -45,6 +46,14 @@
strokeWidth: 1,
opacity: 0.9
}).render();
const popup = new L7.Popup({anchor:'left'}).setText('hello world')
const marker = new L7.Marker({color:'blue'})
.setLnglat( [120.19382669582967, 30.258134])
.setPopup(popup)
.addTo(scene);
layer.on('click',(e) => {
const { lnglat, feature } = e;
const popup = new L7.Popup()

View File

@ -17,7 +17,7 @@
<div id="map">
<div id ="info" class ="tooltip" style="display:none">
</div>
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
<script src="./assets/jquery-3.2.1.min.js"></script>
<script src="../build/L7.js"></script>
<script>

View File

@ -18,34 +18,42 @@
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
<script src="./assets/jquery-3.2.1.min.js"></script>
<script src="./assets/dat.gui.min.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.l7-1.2.0-beta.1/build/l7.js"></script>
<script src="../build/l7.js"></script>
<script>
var buildLayer =null;
const scene = new L7.Scene({
id: 'map',
mapStyle: 'dark', // 样式URL
center: [120.173104, 30.244072],
pitch: 66.50572,
zoom: 15.79,
minZoom:10
center: [
120.15935897827148,
30.261736090037477
],
pitch:0,
zoom: 5,
showBuildingBlock:false,
minZoom: 0,
maxZoom: 18
});
scene.on('loaded', () => {
$.get('https://gw.alipayobjects.com/os/basement_prod/40ef2173-df66-4154-a8c0-785e93a5f18e.json', data => {
scene.LineLayer({
zIndex: 2
})
.source(data)
.size(2)
.size(1)
.shape('line')
.color('#ff893a')
.animate({
enable:false,
interval:0.2,
duration:5,
trailLength:0.1
enable:true,
interval:0.4,
duration:1,
trailLength:0.8
})
.render();
});
$.get('https://gw.alipayobjects.com/os/rmsportal/ggFwDClGjjvpSMBIrcEx.json', data => {
buildLayer = scene.PolygonLayer({
zIndex: 2
@ -65,6 +73,7 @@ scene.on('loaded', () => {
});
});
</script>

63
demos/line_bug.html Normal file
View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="geometry" content="diagram">
<link rel="stylesheet" href="./assets/common.css">
<title>city demo</title>
<style>
#map { position:absolute; top:0; bottom:0; width:100%; }
#timepannel {
background: white;
z-index: 10;
position: absolute;
right:50px;
padding: 10px;
}
</style>
</head>
<body>
<div id ='timepannel'>时间: 6时</div>
<div id="map">
</div>
<script src="https://webapi.amap.com/maps?v=1.4.8&key=f28fca5384129d180ad82915156a9baf&plugin=Map3D"></script>
<script src="./assets/jquery-3.2.1.min.js"></script>
<script src="../build/L7.js"></script>
<script>
var buildLayer =null;
const scene = new L7.Scene({
id: 'map',
mapStyle: 'amap://styles/c9f1d10cae34f8ab05e425462c5a58d7', // 样式URL
center: [120.102915,30.261396],
pitch: 0,
zoom: 3,
minZoom: 5,
maxZoom: 18
});
scene.on('loaded', () => {
scene.image.addImage('arrow', '/demos/assets/arrow.png');
scene.image.addImage('right', '/demos/assets/right.png');
$.get('https://gw.alipayobjects.com/os/basement_prod/3ed18d7c-bce4-48ca-8716-5248b584481d.json',(data)=>{
const linelayer = scene.LineLayer({
zIndex: 2
})
.shape('line')
.size(10)
.source(data)
.color('#2b83ba')
.pattern('arrow')
.style({
patternSpacing: 20
})
.render();
});
})
</script>
</body>
</html>

111
demos/marker.html Normal file
View File

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://gw.alipayobjects.com/os/rmsportal/PqLCOJpqoOUfuPRacUzE.css" />
<title>气泡图</title>
<style> ::-webkit-scrollbar{display:none;}html,body{overflow:hidden;margin:0;}
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>/*Fixing iframe window.innerHeight 0 issue in Safari*/ document.body.clientHeight; </script>
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
<script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g2-3.5.1/dist/g2.min.js"></script>
<script src="../build/l7.js"></script>
<style>
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
<script>
G2.Global.renderer = 'svg'
var scene = new L7.Scene({
id: 'map',
mapStyle: 'light', // 样式URL
center: [120.19382669582967, 30.258134],
pitch: 0,
minZoom:5,
maxZoom:15,
zoom: 3
});
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=>{
const el = document.createElement('div');
const total = item.gdp.Agriculture + item.gdp.Industry + item.gdp.Service;
const size =Math.max(Math.min(parseInt(total / 20000), 150),40)
var data = [{
item: 'Agriculture',
count: item.gdp.Agriculture,
percent: item.gdp.Agriculture / total
}, {
item: 'Industry',
count: item.gdp.Industry,
percent: item.gdp.Industry / total
}, {
item: 'Service',
count: item.gdp.Service,
percent: item.gdp.Service / total
}];
var chart = new G2.Chart({
container: el,
width:size,
height:size,
render:'svg',
padding:5,
});
chart.source(data, {
percent: {
formatter: function formatter(val) {
val = val * 100 + '%';
return val;
}
}
});
chart.coord('theta', {
radius: 1.0
});
chart.legend(false);
chart.tooltip(false);
chart.intervalStack().position('percent').color('item').style({
lineWidth: 1,
stroke: '#fff'
});
chart.render();
const popup = new L7.Popup({anchor:'left'}).setText(item.name);
const marker = new L7.Marker({color:'blue', element:el})
.setLnglat( item.coordinates)
.setPopup(popup)
.addTo(scene);
})
})
});
</script>
</body>
</html>

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

@ -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,11 +111,18 @@ 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:'blue'})
.setLnglat([104.838088,34.075889 ])
.setPopup(popup)
.addTo(scene);
});

View File

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

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;

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

@ -0,0 +1,168 @@
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('click', e => {
this._onMapClick(e);
});
applyAnchorClass(element, this.get('anchor'), 'marker');
this._popup = null;
}
addTo(scene) {
this.remove();
this._scene = scene;
this._scene.getMarkerContainer().appendChild(this.get('element'));
this._scene.on('camerachange', this._update);
this.setDraggable(this.get('draggable'));
this._update();
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';
}
_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() {
}
}

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({
@ -17,41 +18,50 @@ 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;
}
_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._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');
}
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');
@ -117,11 +127,14 @@ 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;
}
this.emit('close');
return this;
}
isOpen() {
return !!this._scene;
}
}

View File

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

View File

@ -20,8 +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();
this._layers = [];
@ -31,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() {
@ -55,12 +53,13 @@ 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);
Map.asyncCamera(this._engine);
this.initLayer();
this._registEvents();
// this._registEvents();
const hash = this.get('hash');
if (hash) {
const Ctor = getInteraction('hash');
@ -68,8 +67,8 @@ export default class Scene extends Base {
interaction._onHashChange();
}
this.style = new Style(this, {});
this._initContoller();
this.emit('loaded');
this._engine.update();
});
}
initLayer() {
@ -122,6 +121,9 @@ export default class Scene extends Base {
getContainer() {
return this._container;
}
getMarkerContainer() {
return this._markerContainier;
}
_registEvents() {
const events = [
'mouseout',
@ -173,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

View File

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

View File

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

View File

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

View File

@ -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;
@ -20,6 +21,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);
@ -35,12 +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
gl_FragColor.a *= v_time;
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;
alpha = smoothstep(0., 1., alpha);
gl_FragColor.a *= alpha;
#endif
// anti-alias
float blur = 1. - smoothstep(u_blur, 1., length(v_normal));

View File

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

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

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

View File

@ -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(),

View File

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

View File

@ -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');
}, 100);
}
initMap() {
@ -56,34 +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');
});
}
}
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) {
@ -96,13 +100,18 @@ 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.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;';
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;

View File

@ -26,7 +26,7 @@ export default class MapBox extends Base {
this.addOverLayer();
setTimeout(() => {
this.emit('mapLoad');
}, 100);
}, 10);
}

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

View File

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