mirror of https://gitee.com/antv-l7/antv-l7
Merge branch 'master' of https://github.com/antvis/L7
This commit is contained in:
commit
b89cedca5b
22
beta.sh
22
beta.sh
|
@ -1,11 +1,11 @@
|
|||
npm dist-tag add @antv/l7-component@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-core@2.5.17 beta
|
||||
npm dist-tag add @antv/l7@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-layers@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-map@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-maps@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-renderer@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-scene@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-source@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-three@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-utils@2.5.17 beta
|
||||
npm dist-tag add @antv/l7-component@2.5.36 beta
|
||||
npm dist-tag add @antv/l7-core@2.5.36 beta
|
||||
npm dist-tag add @antv/l7@2.5.36 beta
|
||||
npm dist-tag add @antv/l7-layers@2.5.36 beta
|
||||
npm dist-tag add @antv/l7-map@2.5.36 beta
|
||||
npm dist-tag add @antv/l7-maps@2.5.36 beta
|
||||
npm dist-tag add @antv/l7-renderer@2.5.36 beta
|
||||
npm dist-tag add @antv/l7-scene@2.5.36 beta
|
||||
npm dist-tag add @antv/l7-source@2.5.36 beta
|
||||
npm dist-tag add @antv/l7-three@2.5.36 beta
|
||||
npm dist-tag add @antv/l7-utils@2.5.36 beta
|
||||
|
|
|
@ -36,13 +36,13 @@ DrillDownLayer 提供默认提供通过 Layer 的交互事件,实现上钻下
|
|||
|
||||
向下钻取的触发事件 ⛔customTrigger 为 true 时不生效
|
||||
|
||||
### drillDownEvent
|
||||
### drillDownEvent
|
||||
|
||||
根据drillDownTriggerEvent类型下钻触发的回调事件 属性
|
||||
根据 drillDownTriggerEvent 类型下钻触发的回调事件 属性
|
||||
|
||||
### drillUpEvent
|
||||
|
||||
根据drillUpTriggleEvent类型上钻触发的回调事件 属性
|
||||
根据 drillUpTriggleEvent 类型上钻触发的回调事件 属性
|
||||
|
||||
### drillUpTriggleEvent
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Earth Mode
|
||||
order: 1
|
||||
---
|
||||
|
||||
`markdown:docs/api/earth/earth.zh.md`
|
|
@ -0,0 +1,134 @@
|
|||
---
|
||||
title: 地球模式
|
||||
order: 1
|
||||
---
|
||||
|
||||
`markdown:docs/common/style.md`
|
||||
|
||||
## 简介
|
||||
|
||||
L7Earth 相较于高德地图、mapbox 地图,是完全不同的一种表现形式,提供了全球视角下的可视化展示能力,为用户提供了更多的地理信息可视化表现形式。
|
||||
|
||||
✨ 为了区别普通的地图,L7Earth 提供了全新的 Earth 地图类型以及对应的 EarthLayer 图层
|
||||
|
||||
## 使用
|
||||
|
||||
```javascript
|
||||
// 1、引入对应模块
|
||||
import { Earth } from '@antv/l7-maps';
|
||||
import { EarthLayer } from '@antv/l7-layers';
|
||||
...
|
||||
// 2、构建 Earth Map
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Earth({}),
|
||||
});
|
||||
...
|
||||
// 3、构建地球图层,当前的 shape 为 base,表示基础球体
|
||||
const earthlayer = new EarthLayer()
|
||||
.source(
|
||||
// 地球表面的纹理
|
||||
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ',
|
||||
{
|
||||
parser: {
|
||||
type: 'image',
|
||||
extent: [121.168, 30.2828, 121.384, 30.421],
|
||||
},
|
||||
},
|
||||
)
|
||||
.color('#f00')
|
||||
.shape('base')
|
||||
.style({
|
||||
opacity: 1.0,
|
||||
radius: 40,
|
||||
globelOtions: {
|
||||
ambientRatio: 0.6, // 环境光
|
||||
diffuseRatio: 0.4, // 漫反射
|
||||
specularRatio: 0.1, // 高光反射
|
||||
earthTime: 0.1,
|
||||
},
|
||||
})
|
||||
.animate(true);
|
||||
|
||||
// 4、添加基础地球球体
|
||||
scene.addLayer(earthlayer);
|
||||
|
||||
// 经过上述的步骤,我们就可以在场景中添加一个基础的地球了
|
||||
```
|
||||
|
||||
## 独立的地图类型 Earth
|
||||
|
||||
### 构造函数 Earth(args)
|
||||
|
||||
作为 L7Earth 的基础地图类型,Earth 提供了地球系统的相机系统,目前只需要传入一个空对象。
|
||||
|
||||
- args: {}
|
||||
|
||||
### rotateY(option: { force: boolean; regScale: number})
|
||||
|
||||
提供了简单的方法控制地球系统的旋转(实际上控制的是相机的旋转)
|
||||
|
||||
- force: false 判断是否强制生效,默认该方法的优先级比用户鼠标操作要低,当用户操作相机的时候,该方法会失效
|
||||
- regScale: 0.01 旋转的角度(视觉上地球的旋转角度), regScale 表示的并不是实际的旋转角度,而是单位旋转角度的比例
|
||||
🌟 单位旋转角度 = Math.min(this.earthCameraZoom \* this.earthCameraZoom, 1)
|
||||
|
||||
## 地图图层 EarthLayer
|
||||
|
||||
地球图层区别于普通高德地图和 Mapbox 地图的图层,只在地球模式下可以被使用,用于表示地球的球体、大气层、辉光等效果。
|
||||
🌟 使用不同的 shape 参数表示区别不同的地球图层
|
||||
|
||||
### 地球球体图层 baseLayer
|
||||
|
||||
- source(map, parser)
|
||||
map: 地球表面纹理贴图的地址
|
||||
parser: 解析器,目前只需要写固定的对象值即可 { parser: { type: "image" } }
|
||||
- shape: 'base'
|
||||
🌟 目前支持的 shape 类型有 base、atomSphere、bloomSphere,当用户的 shape 参数不被识别时,自动降级为 base 类型
|
||||
- globelOtions: style 方法中的参数 ambientRatio: 环境光、diffuseRatio: 漫反射、specularRatio: 高光反射
|
||||
|
||||
```javascript
|
||||
const earthlayer = new EarthLayer()
|
||||
.source(
|
||||
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ',
|
||||
{
|
||||
parser: {
|
||||
type: 'image',
|
||||
},
|
||||
},
|
||||
)
|
||||
.shape('base')
|
||||
.style({
|
||||
globelOtions: {
|
||||
ambientRatio: 0.6, // 环境光
|
||||
diffuseRatio: 0.4, // 漫反射
|
||||
specularRatio: 0.1, // 高光反射
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### 地球内发光/大气图层 atomLayer
|
||||
|
||||
atomLayer 作为地球的效果图层,不需要传入数据,所以可以不调用 source 方法
|
||||
|
||||
```javascript
|
||||
const atomLayer = new EarthLayer()
|
||||
.color('#2E8AE6')
|
||||
.shape('atomSphere')
|
||||
.style({
|
||||
// 可以控制发光程度
|
||||
opacity: 1,
|
||||
});
|
||||
```
|
||||
|
||||
### 地球内外发光/辉光图层 bloomLayer
|
||||
|
||||
bloomLayer 作为地球的效果图层,不需要传入数据,所以可以不调用 source 方法
|
||||
|
||||
```javascript
|
||||
const bloomLayer = new EarthLayer()
|
||||
.color('#fff')
|
||||
.shape('bloomSphere')
|
||||
.style({
|
||||
opacity: 0.5,
|
||||
});
|
||||
```
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Earth Flyline
|
||||
order: 3
|
||||
---
|
||||
|
||||
`markdown:docs/api/earth/flyline.zh.md`
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
title: 飞线
|
||||
order: 3
|
||||
---
|
||||
|
||||
`markdown:docs/common/style.md`
|
||||
|
||||
## 简介
|
||||
|
||||
用户在地球模式下使用飞线图层无需做额外的操作,L7 会自动识别地球模式并相关的转化
|
||||
|
||||
## 使用
|
||||
|
||||
```javascript
|
||||
// 1、引入对应模块
|
||||
const flyLine = new LineLayer({ blend: 'normal' })
|
||||
.source(flydata, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
coordinates: 'coord',
|
||||
},
|
||||
})
|
||||
.color('#b97feb')
|
||||
.shape('arc3d')
|
||||
.size(0.5)
|
||||
.active(true)
|
||||
.animate({
|
||||
interval: 2,
|
||||
trailLength: 2,
|
||||
duration: 1,
|
||||
})
|
||||
.style({
|
||||
opacity: 1,
|
||||
segmentNumber: 60,
|
||||
globalArcHeight: 20,
|
||||
});
|
||||
...
|
||||
// 2、注册服务
|
||||
scene.addLayer(flyLine);
|
||||
|
||||
```
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Earth Point
|
||||
order: 3
|
||||
---
|
||||
|
||||
`markdown:docs/api/earth/point.zh.md`
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
title: 点图层
|
||||
order: 3
|
||||
---
|
||||
|
||||
`markdown:docs/common/style.md`
|
||||
|
||||
## 简介
|
||||
|
||||
用户在地球模式下使用点图层无需做额外的操作,L7 会自动识别地球模式并相关的转化
|
||||
|
||||
## 使用
|
||||
|
||||
```javascript
|
||||
// 1、构建 pointlayer
|
||||
const pointlayer = new PointLayer()
|
||||
.source(
|
||||
data,
|
||||
{
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
},
|
||||
)
|
||||
// .shape('circle') // cylinder
|
||||
.color('#f00')
|
||||
.size(20) // .size('', () => [1, 1, 10])
|
||||
|
||||
...
|
||||
|
||||
// 2、添加 pointlayer 图层对象
|
||||
scene.addLayer(pointlayer);
|
||||
|
||||
```
|
|
@ -136,6 +136,10 @@ L7 将 threejs 的引用封装成一个特殊的图层对象,在使用上与
|
|||
|
||||
用户通过该方法管理加载模型的动画
|
||||
|
||||
### getRenderCamera(): THREE.Camera
|
||||
|
||||
返回根据当前地图场景参数下对应的 THREEJS 相机
|
||||
|
||||
## 加载模型
|
||||
|
||||
用户可以使用 threejs 提供的能力加载其支持的任意模型
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import { Scene, EarthLayer, LineLayer } from '@antv/l7';
|
||||
import { Earth } from '@antv/l7-maps';
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Earth({})
|
||||
});
|
||||
|
||||
// TODO: 地球模式下背景色默认为 #000 通过 setBgColor 方法我们可以设置可视化层的背景色
|
||||
scene.setBgColor('#333');
|
||||
|
||||
const flydata = [{ coord: [[ 104.195397, 35.86166 ], [ 100.992541, 15.870032 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 114.727669, 4.535277 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 9.501785, 56.26392 ]] }, { coord: [[ 104.195397, 35.86166 ], [ -66.590149, 18.220833 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 174.885971, -40.900557 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 104.990963, 12.565679 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 6.129582999999999, 49.815273 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 8.468945999999999, 60.47202399999999 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 108.277199, 14.058324 ]] }, { coord: [[ 104.195397, 35.86166 ], [ -95.712891, 37.09024 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 121.49917, 25.12653 ]] }, { coord: [[ 104.195397, 35.86166 ], [ -9.429499000000002, 6.428055 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 127.766922, 35.907757 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 10.451526, 51.165691 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 23.881275, 55.169438 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 34.851612, 31.046051 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 53.847818, 23.424076 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 102.495496, 19.85627 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 21.824312, 39.074208 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 25.48583, 42.733883 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 15.472962, 49.81749199999999 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 78.96288, 20.593684 ]] }, { coord: [[ 104.195397, 35.86166 ], [ -3.435973, 55.378051 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 33.429859, 35.126413 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 8.227511999999999, 46.818188 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 114.066662, 22.588638 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 14.550072, 47.516231 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 2.213749, 46.227638 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 12.56738, 41.87194 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 105.318756, 61.52401 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 80.77179699999999, 7.873053999999999 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 5.291265999999999, 52.132633 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 35.243322, 38.963745 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 18.643501, 60.12816100000001 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 25.748151, 61.92410999999999 ]] }, { coord: [[ 104.195397, 35.86166 ], [ -3.74922, 40.46366700000001 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 113.551538, 22.109432 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 4.469936, 50.503887 ]] }, { coord: [[ 104.195397, 35.86166 ], [ -106.346771, 56.130366 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 138.252924, 36.204824 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 17.679076, 43.915886 ]] }, { coord: [[ 104.195397, 35.86166 ], [ -88.49765, 17.189877 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 25.013607, 58.595272 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 101.975766, 4.210484 ]] }, { coord: [[ 104.195397, 35.86166 ], [ -8.24389, 53.41291 ]] }, { coord: [[ 104.195397, 35.86166 ], [ -8.224454, 39.39987199999999 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 133.775136, -25.274398 ]] }, { coord: [[ 104.195397, 35.86166 ], [ 121.774017, 12.879721 ]] }];
|
||||
const flyLine = new LineLayer({ blend: 'normal' })
|
||||
.source(flydata, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
coordinates: 'coord'
|
||||
}
|
||||
})
|
||||
.color('#b97feb')
|
||||
.shape('arc3d')
|
||||
.size(0.5)
|
||||
.active(true)
|
||||
.animate({
|
||||
interval: 2,
|
||||
trailLength: 2,
|
||||
duration: 1
|
||||
})
|
||||
.style({
|
||||
opacity: 1,
|
||||
segmentNumber: 60,
|
||||
globalArcHeight: 20
|
||||
});
|
||||
|
||||
|
||||
const earthlayer = new EarthLayer()
|
||||
.source(
|
||||
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ',
|
||||
{
|
||||
parser: {
|
||||
type: 'image'
|
||||
}
|
||||
}
|
||||
)
|
||||
.color('#2E8AE6')
|
||||
.shape('fill')
|
||||
.style({
|
||||
globelOtions: {
|
||||
ambientRatio: 0.6, // 环境光
|
||||
diffuseRatio: 0.4, // 漫反射
|
||||
specularRatio: 0.1 // 高光反射
|
||||
}
|
||||
})
|
||||
.animate(true);
|
||||
|
||||
const atomLayer = new EarthLayer()
|
||||
.color('#2E8AE6')
|
||||
.shape('atomSphere')
|
||||
.style({
|
||||
opacity: 1
|
||||
});
|
||||
|
||||
const bloomLayer = new EarthLayer().color('#fff').shape('bloomSphere')
|
||||
.style({
|
||||
opacity: 0.7
|
||||
});
|
||||
|
||||
scene.on('loaded', () => {
|
||||
scene.addLayer(earthlayer);
|
||||
|
||||
scene.addLayer(atomLayer);
|
||||
scene.addLayer(bloomLayer);
|
||||
|
||||
scene.addLayer(flyLine);
|
||||
|
||||
earthlayer.setEarthTime(4.0);
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"title": {
|
||||
"zh": "地球模式 - arc3d图层",
|
||||
"en": "Earth Mode - lineLayer/arc3d"
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "flyline.js",
|
||||
"title": "飞线",
|
||||
"screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*ZrpHTKS1_FsAAAAAAAAAAAAAARQnAQ"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: flyline
|
||||
order: 0
|
||||
---
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: 飞线
|
||||
order: 0
|
||||
---
|
|
@ -0,0 +1,320 @@
|
|||
import { Scene, PointLayer, EarthLayer } from '@antv/l7';
|
||||
import { Earth } from '@antv/l7-maps';
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Earth({})
|
||||
});
|
||||
|
||||
const d = [
|
||||
{ lng: 121.61865234375, lat: 25.29437116258816 },
|
||||
{ lng: 121.058349609375, lat: 25.015928763367857 },
|
||||
{ lng: 120.7177734375, lat: 24.587090339209634 },
|
||||
{ lng: 120.28930664062499, lat: 23.936054914599815 },
|
||||
{ lng: 120.12451171875, lat: 23.553916518321625 },
|
||||
{ lng: 120.08056640625, lat: 23.120153621695614 },
|
||||
{ lng: 120.234375, lat: 22.867317960075614 },
|
||||
{ lng: 120.43212890625, lat: 22.52270570348246 },
|
||||
{ lng: 120.65185546875, lat: 22.370396344320053 },
|
||||
{ lng: 120.750732421875, lat: 21.922663209325922 },
|
||||
{ lng: 120.948486328125, lat: 22.268764039073968 },
|
||||
{ lng: 121.124267578125, lat: 22.806567100271522 },
|
||||
{ lng: 121.56372070312499, lat: 23.915970370510227 },
|
||||
{ lng: 121.88232421875, lat: 24.557116164309626 },
|
||||
{ lng: 121.95922851562501, lat: 25.075648445630527 },
|
||||
{ lng: 109.97314453125, lat: 20.076570104545173 },
|
||||
{ lng: 108.896484375, lat: 19.663280219987662 },
|
||||
{ lng: 108.61083984375, lat: 18.979025953255267 },
|
||||
{ lng: 108.80859375, lat: 18.47960905583197 },
|
||||
{ lng: 109.599609375, lat: 18.35452552912664 },
|
||||
{ lng: 110.32470703125, lat: 18.771115062337024 },
|
||||
{ lng: 111.005859375, lat: 19.78738018198621 },
|
||||
{ lng: 127.657407, lat: 49.76027 },
|
||||
{ lng: 129.397818, lat: 49.4406 },
|
||||
{ lng: 130.582293, lat: 48.729687 },
|
||||
{ lng: 130.987282, lat: 47.790132 },
|
||||
{ lng: 132.506672, lat: 47.78897 },
|
||||
{ lng: 133.373596, lat: 48.183442 },
|
||||
{ lng: 135.026311, lat: 48.47823 },
|
||||
{ lng: 134.500814, lat: 47.57844 },
|
||||
{ lng: 134.112362, lat: 47.212467 },
|
||||
{ lng: 133.769644, lat: 46.116927 },
|
||||
{ lng: 133.097127, lat: 45.144066 },
|
||||
{ lng: 131.883454, lat: 45.321162 },
|
||||
{ lng: 131.025212, lat: 44.967953 },
|
||||
{ lng: 131.288555, lat: 44.11152 },
|
||||
{ lng: 131.144688, lat: 42.92999 },
|
||||
{ lng: 130.633866, lat: 42.903015 },
|
||||
{ lng: 130.640016, lat: 42.395009 },
|
||||
{ lng: 129.994267, lat: 42.985387 },
|
||||
{ lng: 129.596669, lat: 42.424982 },
|
||||
{ lng: 128.052215, lat: 41.994285 },
|
||||
{ lng: 128.208433, lat: 41.466772 },
|
||||
{ lng: 127.343783, lat: 41.503152 },
|
||||
{ lng: 126.869083, lat: 41.816569 },
|
||||
{ lng: 126.182045, lat: 41.107336 },
|
||||
{ lng: 125.079942, lat: 40.569824 },
|
||||
{ lng: 124.265625, lat: 39.928493 },
|
||||
{ lng: 122.86757, lat: 39.637788 },
|
||||
{ lng: 122.131388, lat: 39.170452 },
|
||||
{ lng: 121.054554, lat: 38.897471 },
|
||||
{ lng: 121.585995, lat: 39.360854 },
|
||||
{ lng: 121.376757, lat: 39.750261 },
|
||||
{ lng: 122.168595, lat: 40.422443 },
|
||||
{ lng: 121.640359, lat: 40.94639 },
|
||||
{ lng: 120.768629, lat: 40.593388 },
|
||||
{ lng: 119.639602, lat: 39.898056 },
|
||||
{ lng: 119.023464, lat: 39.252333 },
|
||||
{ lng: 118.042749, lat: 39.204274 },
|
||||
{ lng: 117.532702, lat: 38.737636 },
|
||||
{ lng: 118.059699, lat: 38.061476 },
|
||||
{ lng: 118.87815, lat: 37.897325 },
|
||||
{ lng: 118.911636, lat: 37.448464 },
|
||||
{ lng: 119.702802, lat: 37.156389 },
|
||||
{ lng: 120.823457, lat: 37.870428 },
|
||||
{ lng: 121.711259, lat: 37.481123 },
|
||||
{ lng: 122.357937, lat: 37.454484 },
|
||||
{ lng: 122.519995, lat: 36.930614 },
|
||||
{ lng: 121.104164, lat: 36.651329 },
|
||||
{ lng: 120.637009, lat: 36.11144 },
|
||||
{ lng: 119.664562, lat: 35.609791 },
|
||||
{ lng: 119.151208, lat: 34.909859 },
|
||||
{ lng: 120.227525, lat: 34.360332 },
|
||||
{ lng: 120.620369, lat: 33.376723 },
|
||||
{ lng: 121.229014, lat: 32.460319 },
|
||||
{ lng: 121.908146, lat: 31.692174 },
|
||||
{ lng: 121.891919, lat: 30.949352 },
|
||||
{ lng: 121.264257, lat: 30.676267 },
|
||||
{ lng: 121.503519, lat: 30.142915 },
|
||||
{ lng: 122.092114, lat: 29.83252 },
|
||||
{ lng: 121.938428, lat: 29.018022 },
|
||||
{ lng: 121.684439, lat: 28.225513 },
|
||||
{ lng: 121.125661, lat: 28.135673 },
|
||||
{ lng: 120.395473, lat: 27.053207 },
|
||||
{ lng: 119.585497, lat: 25.740781 },
|
||||
{ lng: 118.656871, lat: 24.547391 },
|
||||
{ lng: 117.281606, lat: 23.624501 },
|
||||
{ lng: 115.890735, lat: 22.782873 },
|
||||
{ lng: 114.763827, lat: 22.668074 },
|
||||
{ lng: 114.152547, lat: 22.22376 },
|
||||
{ lng: 113.80678, lat: 22.54834 },
|
||||
{ lng: 113.241078, lat: 22.051367 },
|
||||
{ lng: 111.843592, lat: 21.550494 },
|
||||
{ lng: 110.785466, lat: 21.397144 },
|
||||
{ lng: 110.444039, lat: 20.341033 },
|
||||
{ lng: 109.889861, lat: 20.282457 },
|
||||
{ lng: 109.627655, lat: 21.008227 },
|
||||
{ lng: 109.864488, lat: 21.395051 },
|
||||
{ lng: 108.522813, lat: 21.715212 },
|
||||
{ lng: 108.05018, lat: 21.55238 },
|
||||
{ lng: 107.04342, lat: 21.811899 },
|
||||
{ lng: 106.567273, lat: 22.218205 },
|
||||
{ lng: 106.725403, lat: 22.794268 },
|
||||
{ lng: 105.811247, lat: 22.976892 },
|
||||
{ lng: 105.329209, lat: 23.352063 },
|
||||
{ lng: 104.476858, lat: 22.81915 },
|
||||
{ lng: 103.504515, lat: 22.703757 },
|
||||
{ lng: 102.706992, lat: 22.708795 },
|
||||
{ lng: 102.170436, lat: 22.464753 },
|
||||
{ lng: 101.652018, lat: 22.318199 },
|
||||
{ lng: 101.80312, lat: 21.174367 },
|
||||
{ lng: 101.270026, lat: 21.201652 },
|
||||
{ lng: 101.180005, lat: 21.436573 },
|
||||
{ lng: 101.150033, lat: 21.849984 },
|
||||
{ lng: 100.416538, lat: 21.558839 },
|
||||
{ lng: 99.983489, lat: 21.742937 },
|
||||
{ lng: 99.240899, lat: 22.118314 },
|
||||
{ lng: 99.531992, lat: 22.949039 },
|
||||
{ lng: 98.898749, lat: 23.142722 },
|
||||
{ lng: 98.660262, lat: 24.063286 },
|
||||
{ lng: 97.60472, lat: 23.897405 },
|
||||
{ lng: 97.724609, lat: 25.083637 },
|
||||
{ lng: 98.671838, lat: 25.918703 },
|
||||
{ lng: 98.712094, lat: 26.743536 },
|
||||
{ lng: 98.68269, lat: 27.508812 },
|
||||
{ lng: 98.246231, lat: 27.747221 },
|
||||
{ lng: 97.911988, lat: 28.335945 },
|
||||
{ lng: 97.327114, lat: 28.261583 },
|
||||
{ lng: 96.248833, lat: 28.411031 },
|
||||
{ lng: 96.586591, lat: 28.83098 },
|
||||
{ lng: 96.117679, lat: 29.452802 },
|
||||
{ lng: 95.404802, lat: 29.031717 },
|
||||
{ lng: 94.56599, lat: 29.277438 },
|
||||
{ lng: 93.413348, lat: 28.640629 },
|
||||
{ lng: 92.503119, lat: 27.896876 },
|
||||
{ lng: 91.696657, lat: 27.771742 },
|
||||
{ lng: 91.258854, lat: 28.040614 },
|
||||
{ lng: 90.730514, lat: 28.064954 },
|
||||
{ lng: 90.015829, lat: 28.296439 },
|
||||
{ lng: 89.47581, lat: 28.042759 },
|
||||
{ lng: 88.814248, lat: 27.299316 },
|
||||
{ lng: 88.730326, lat: 28.086865 },
|
||||
{ lng: 88.120441, lat: 27.876542 },
|
||||
{ lng: 86.954517, lat: 27.974262 },
|
||||
{ lng: 85.82332, lat: 28.203576 },
|
||||
{ lng: 85.011638, lat: 28.642774 },
|
||||
{ lng: 84.23458, lat: 28.839894 },
|
||||
{ lng: 83.898993, lat: 29.320226 },
|
||||
{ lng: 83.337115, lat: 29.463732 },
|
||||
{ lng: 82.327513, lat: 30.115268 },
|
||||
{ lng: 81.525804, lat: 30.422717 },
|
||||
{ lng: 81.111256, lat: 30.183481 },
|
||||
{ lng: 79.721367, lat: 30.882715 },
|
||||
{ lng: 78.738894, lat: 31.515906 },
|
||||
{ lng: 78.458446, lat: 32.618164 },
|
||||
{ lng: 79.176129, lat: 32.48378 },
|
||||
{ lng: 79.208892, lat: 32.994395 },
|
||||
{ lng: 78.811086, lat: 33.506198 },
|
||||
{ lng: 78.912269, lat: 34.321936 },
|
||||
{ lng: 77.837451, lat: 35.49401 },
|
||||
{ lng: 76.192848, lat: 35.898403 },
|
||||
{ lng: 75.896897, lat: 36.666806 },
|
||||
{ lng: 75.158028, lat: 37.133031 },
|
||||
{ lng: 74.980002, lat: 37.41999 },
|
||||
{ lng: 74.829986, lat: 37.990007 },
|
||||
{ lng: 74.864816, lat: 38.378846 },
|
||||
{ lng: 74.257514, lat: 38.606507 },
|
||||
{ lng: 73.928852, lat: 38.505815 },
|
||||
{ lng: 73.675379, lat: 39.431237 },
|
||||
{ lng: 73.960013, lat: 39.660008 },
|
||||
{ lng: 73.822244, lat: 39.893973 },
|
||||
{ lng: 74.776862, lat: 40.366425 },
|
||||
{ lng: 75.467828, lat: 40.562072 },
|
||||
{ lng: 76.526368, lat: 40.427946 },
|
||||
{ lng: 76.904484, lat: 41.066486 },
|
||||
{ lng: 78.187197, lat: 41.185316 },
|
||||
{ lng: 78.543661, lat: 41.582243 },
|
||||
{ lng: 80.11943, lat: 42.123941 },
|
||||
{ lng: 80.25999, lat: 42.349999 },
|
||||
{ lng: 80.18015, lat: 42.920068 },
|
||||
{ lng: 80.866206, lat: 43.180362 },
|
||||
{ lng: 79.966106, lat: 44.917517 },
|
||||
{ lng: 81.947071, lat: 45.317027 },
|
||||
{ lng: 82.458926, lat: 45.53965 },
|
||||
{ lng: 83.180484, lat: 47.330031 },
|
||||
{ lng: 85.16429, lat: 47.000956 },
|
||||
{ lng: 85.720484, lat: 47.452969 },
|
||||
{ lng: 85.768233, lat: 48.455751 },
|
||||
{ lng: 86.598776, lat: 48.549182 },
|
||||
{ lng: 87.35997, lat: 49.214981 },
|
||||
{ lng: 87.751264, lat: 49.297198 },
|
||||
{ lng: 88.013832, lat: 48.599463 },
|
||||
{ lng: 88.854298, lat: 48.069082 },
|
||||
{ lng: 90.280826, lat: 47.693549 },
|
||||
{ lng: 90.970809, lat: 46.888146 },
|
||||
{ lng: 90.585768, lat: 45.719716 },
|
||||
{ lng: 90.94554, lat: 45.286073 },
|
||||
{ lng: 92.133891, lat: 45.115076 },
|
||||
{ lng: 93.480734, lat: 44.975472 },
|
||||
{ lng: 94.688929, lat: 44.352332 },
|
||||
{ lng: 95.306875, lat: 44.241331 },
|
||||
{ lng: 95.762455, lat: 43.319449 },
|
||||
{ lng: 96.349396, lat: 42.725635 },
|
||||
{ lng: 97.451757, lat: 42.74889 },
|
||||
{ lng: 99.515817, lat: 42.524691 },
|
||||
{ lng: 100.845866, lat: 42.663804 },
|
||||
{ lng: 101.83304, lat: 42.514873 },
|
||||
{ lng: 103.312278, lat: 41.907468 },
|
||||
{ lng: 104.522282, lat: 41.908347 },
|
||||
{ lng: 104.964994, lat: 41.59741 },
|
||||
{ lng: 106.129316, lat: 42.134328 },
|
||||
{ lng: 107.744773, lat: 42.481516 },
|
||||
{ lng: 109.243596, lat: 42.519446 },
|
||||
{ lng: 110.412103, lat: 42.871234 },
|
||||
{ lng: 111.129682, lat: 43.406834 },
|
||||
{ lng: 111.829588, lat: 43.743118 },
|
||||
{ lng: 111.667737, lat: 44.073176 },
|
||||
{ lng: 111.348377, lat: 44.457442 },
|
||||
{ lng: 111.873306, lat: 45.102079 },
|
||||
{ lng: 112.436062, lat: 45.011646 },
|
||||
{ lng: 113.463907, lat: 44.808893 },
|
||||
{ lng: 114.460332, lat: 45.339817 },
|
||||
{ lng: 115.985096, lat: 45.727235 },
|
||||
{ lng: 116.717868, lat: 46.388202 },
|
||||
{ lng: 117.421701, lat: 46.672733 },
|
||||
{ lng: 118.874326, lat: 46.805412 },
|
||||
{ lng: 119.66327, lat: 46.69268 },
|
||||
{ lng: 119.772824, lat: 47.048059 },
|
||||
{ lng: 118.866574, lat: 47.74706 },
|
||||
{ lng: 118.064143, lat: 48.06673 },
|
||||
{ lng: 117.295507, lat: 47.697709 },
|
||||
{ lng: 116.308953, lat: 47.85341 },
|
||||
{ lng: 115.742837, lat: 47.726545 },
|
||||
{ lng: 115.485282, lat: 48.135383 },
|
||||
{ lng: 116.191802, lat: 49.134598 },
|
||||
{ lng: 116.678801, lat: 49.888531 },
|
||||
{ lng: 117.879244, lat: 49.510983 },
|
||||
{ lng: 119.288461, lat: 50.142883 },
|
||||
{ lng: 119.279366, lat: 50.582908 },
|
||||
{ lng: 120.18205, lat: 51.643566 },
|
||||
{ lng: 120.738191, lat: 51.964115 },
|
||||
{ lng: 120.725789, lat: 52.516226 },
|
||||
{ lng: 120.177089, lat: 52.753886 },
|
||||
{ lng: 121.003085, lat: 53.251401 },
|
||||
{ lng: 122.245748, lat: 53.431726 },
|
||||
{ lng: 123.571507, lat: 53.458804 },
|
||||
{ lng: 125.068211, lat: 53.161045 },
|
||||
{ lng: 125.946349, lat: 52.792799 },
|
||||
{ lng: 126.564399, lat: 51.784255 },
|
||||
{ lng: 126.939157, lat: 51.353894 },
|
||||
{ lng: 127.287456, lat: 50.739797 },
|
||||
{ lng: 127.657407, lat: 49.76027 }
|
||||
];
|
||||
|
||||
const pointlayer = new PointLayer()
|
||||
.source(
|
||||
d,
|
||||
{
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat'
|
||||
}
|
||||
}
|
||||
)
|
||||
.shape('cylinder')
|
||||
.color('#f00')
|
||||
.size('', () => [ 1, 1, 10 ])
|
||||
.active(true);
|
||||
|
||||
const earthlayer = new EarthLayer()
|
||||
.source(
|
||||
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ',
|
||||
{
|
||||
parser: {
|
||||
type: 'image'
|
||||
}
|
||||
}
|
||||
)
|
||||
.shape('fill')
|
||||
.style({
|
||||
opacity: 1.0,
|
||||
radius: 40,
|
||||
globelOtions: {
|
||||
ambientRatio: 0.6, // 环境光
|
||||
diffuseRatio: 0.4, // 漫反射
|
||||
specularRatio: 0.1 // 高光反射
|
||||
}
|
||||
})
|
||||
.animate(true);
|
||||
|
||||
const atomLayer = new EarthLayer()
|
||||
.color('#2E8AE6')
|
||||
.shape('atomSphere')
|
||||
.style({
|
||||
opacity: 1
|
||||
});
|
||||
|
||||
const bloomLayer = new EarthLayer().color('#fff').shape('bloomSphere')
|
||||
.style({
|
||||
opacity: 0.6
|
||||
});
|
||||
|
||||
scene.on('loaded', () => {
|
||||
scene.addLayer(earthlayer);
|
||||
scene.addLayer(pointlayer);
|
||||
|
||||
scene.addLayer(atomLayer);
|
||||
scene.addLayer(bloomLayer);
|
||||
|
||||
earthlayer.setEarthTime(4.0);
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"title": {
|
||||
"zh": "地球模式 - 点图层",
|
||||
"en": "Earth Mode - pointLayer"
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "point.js",
|
||||
"title": "点图层",
|
||||
"screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*R5uPS4SIMi0AAAAAAAAAAAAAARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "cylinder.js",
|
||||
"title": "圆柱图层",
|
||||
"screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*u2iWTrhJnL0AAAAAAAAAAAAAARQnAQ"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,320 @@
|
|||
import { Scene, PointLayer, EarthLayer } from '@antv/l7';
|
||||
import { Earth } from '@antv/l7-maps';
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Earth({})
|
||||
});
|
||||
|
||||
const d = [
|
||||
{ lng: 121.61865234375, lat: 25.29437116258816 },
|
||||
{ lng: 121.058349609375, lat: 25.015928763367857 },
|
||||
{ lng: 120.7177734375, lat: 24.587090339209634 },
|
||||
{ lng: 120.28930664062499, lat: 23.936054914599815 },
|
||||
{ lng: 120.12451171875, lat: 23.553916518321625 },
|
||||
{ lng: 120.08056640625, lat: 23.120153621695614 },
|
||||
{ lng: 120.234375, lat: 22.867317960075614 },
|
||||
{ lng: 120.43212890625, lat: 22.52270570348246 },
|
||||
{ lng: 120.65185546875, lat: 22.370396344320053 },
|
||||
{ lng: 120.750732421875, lat: 21.922663209325922 },
|
||||
{ lng: 120.948486328125, lat: 22.268764039073968 },
|
||||
{ lng: 121.124267578125, lat: 22.806567100271522 },
|
||||
{ lng: 121.56372070312499, lat: 23.915970370510227 },
|
||||
{ lng: 121.88232421875, lat: 24.557116164309626 },
|
||||
{ lng: 121.95922851562501, lat: 25.075648445630527 },
|
||||
{ lng: 109.97314453125, lat: 20.076570104545173 },
|
||||
{ lng: 108.896484375, lat: 19.663280219987662 },
|
||||
{ lng: 108.61083984375, lat: 18.979025953255267 },
|
||||
{ lng: 108.80859375, lat: 18.47960905583197 },
|
||||
{ lng: 109.599609375, lat: 18.35452552912664 },
|
||||
{ lng: 110.32470703125, lat: 18.771115062337024 },
|
||||
{ lng: 111.005859375, lat: 19.78738018198621 },
|
||||
{ lng: 127.657407, lat: 49.76027 },
|
||||
{ lng: 129.397818, lat: 49.4406 },
|
||||
{ lng: 130.582293, lat: 48.729687 },
|
||||
{ lng: 130.987282, lat: 47.790132 },
|
||||
{ lng: 132.506672, lat: 47.78897 },
|
||||
{ lng: 133.373596, lat: 48.183442 },
|
||||
{ lng: 135.026311, lat: 48.47823 },
|
||||
{ lng: 134.500814, lat: 47.57844 },
|
||||
{ lng: 134.112362, lat: 47.212467 },
|
||||
{ lng: 133.769644, lat: 46.116927 },
|
||||
{ lng: 133.097127, lat: 45.144066 },
|
||||
{ lng: 131.883454, lat: 45.321162 },
|
||||
{ lng: 131.025212, lat: 44.967953 },
|
||||
{ lng: 131.288555, lat: 44.11152 },
|
||||
{ lng: 131.144688, lat: 42.92999 },
|
||||
{ lng: 130.633866, lat: 42.903015 },
|
||||
{ lng: 130.640016, lat: 42.395009 },
|
||||
{ lng: 129.994267, lat: 42.985387 },
|
||||
{ lng: 129.596669, lat: 42.424982 },
|
||||
{ lng: 128.052215, lat: 41.994285 },
|
||||
{ lng: 128.208433, lat: 41.466772 },
|
||||
{ lng: 127.343783, lat: 41.503152 },
|
||||
{ lng: 126.869083, lat: 41.816569 },
|
||||
{ lng: 126.182045, lat: 41.107336 },
|
||||
{ lng: 125.079942, lat: 40.569824 },
|
||||
{ lng: 124.265625, lat: 39.928493 },
|
||||
{ lng: 122.86757, lat: 39.637788 },
|
||||
{ lng: 122.131388, lat: 39.170452 },
|
||||
{ lng: 121.054554, lat: 38.897471 },
|
||||
{ lng: 121.585995, lat: 39.360854 },
|
||||
{ lng: 121.376757, lat: 39.750261 },
|
||||
{ lng: 122.168595, lat: 40.422443 },
|
||||
{ lng: 121.640359, lat: 40.94639 },
|
||||
{ lng: 120.768629, lat: 40.593388 },
|
||||
{ lng: 119.639602, lat: 39.898056 },
|
||||
{ lng: 119.023464, lat: 39.252333 },
|
||||
{ lng: 118.042749, lat: 39.204274 },
|
||||
{ lng: 117.532702, lat: 38.737636 },
|
||||
{ lng: 118.059699, lat: 38.061476 },
|
||||
{ lng: 118.87815, lat: 37.897325 },
|
||||
{ lng: 118.911636, lat: 37.448464 },
|
||||
{ lng: 119.702802, lat: 37.156389 },
|
||||
{ lng: 120.823457, lat: 37.870428 },
|
||||
{ lng: 121.711259, lat: 37.481123 },
|
||||
{ lng: 122.357937, lat: 37.454484 },
|
||||
{ lng: 122.519995, lat: 36.930614 },
|
||||
{ lng: 121.104164, lat: 36.651329 },
|
||||
{ lng: 120.637009, lat: 36.11144 },
|
||||
{ lng: 119.664562, lat: 35.609791 },
|
||||
{ lng: 119.151208, lat: 34.909859 },
|
||||
{ lng: 120.227525, lat: 34.360332 },
|
||||
{ lng: 120.620369, lat: 33.376723 },
|
||||
{ lng: 121.229014, lat: 32.460319 },
|
||||
{ lng: 121.908146, lat: 31.692174 },
|
||||
{ lng: 121.891919, lat: 30.949352 },
|
||||
{ lng: 121.264257, lat: 30.676267 },
|
||||
{ lng: 121.503519, lat: 30.142915 },
|
||||
{ lng: 122.092114, lat: 29.83252 },
|
||||
{ lng: 121.938428, lat: 29.018022 },
|
||||
{ lng: 121.684439, lat: 28.225513 },
|
||||
{ lng: 121.125661, lat: 28.135673 },
|
||||
{ lng: 120.395473, lat: 27.053207 },
|
||||
{ lng: 119.585497, lat: 25.740781 },
|
||||
{ lng: 118.656871, lat: 24.547391 },
|
||||
{ lng: 117.281606, lat: 23.624501 },
|
||||
{ lng: 115.890735, lat: 22.782873 },
|
||||
{ lng: 114.763827, lat: 22.668074 },
|
||||
{ lng: 114.152547, lat: 22.22376 },
|
||||
{ lng: 113.80678, lat: 22.54834 },
|
||||
{ lng: 113.241078, lat: 22.051367 },
|
||||
{ lng: 111.843592, lat: 21.550494 },
|
||||
{ lng: 110.785466, lat: 21.397144 },
|
||||
{ lng: 110.444039, lat: 20.341033 },
|
||||
{ lng: 109.889861, lat: 20.282457 },
|
||||
{ lng: 109.627655, lat: 21.008227 },
|
||||
{ lng: 109.864488, lat: 21.395051 },
|
||||
{ lng: 108.522813, lat: 21.715212 },
|
||||
{ lng: 108.05018, lat: 21.55238 },
|
||||
{ lng: 107.04342, lat: 21.811899 },
|
||||
{ lng: 106.567273, lat: 22.218205 },
|
||||
{ lng: 106.725403, lat: 22.794268 },
|
||||
{ lng: 105.811247, lat: 22.976892 },
|
||||
{ lng: 105.329209, lat: 23.352063 },
|
||||
{ lng: 104.476858, lat: 22.81915 },
|
||||
{ lng: 103.504515, lat: 22.703757 },
|
||||
{ lng: 102.706992, lat: 22.708795 },
|
||||
{ lng: 102.170436, lat: 22.464753 },
|
||||
{ lng: 101.652018, lat: 22.318199 },
|
||||
{ lng: 101.80312, lat: 21.174367 },
|
||||
{ lng: 101.270026, lat: 21.201652 },
|
||||
{ lng: 101.180005, lat: 21.436573 },
|
||||
{ lng: 101.150033, lat: 21.849984 },
|
||||
{ lng: 100.416538, lat: 21.558839 },
|
||||
{ lng: 99.983489, lat: 21.742937 },
|
||||
{ lng: 99.240899, lat: 22.118314 },
|
||||
{ lng: 99.531992, lat: 22.949039 },
|
||||
{ lng: 98.898749, lat: 23.142722 },
|
||||
{ lng: 98.660262, lat: 24.063286 },
|
||||
{ lng: 97.60472, lat: 23.897405 },
|
||||
{ lng: 97.724609, lat: 25.083637 },
|
||||
{ lng: 98.671838, lat: 25.918703 },
|
||||
{ lng: 98.712094, lat: 26.743536 },
|
||||
{ lng: 98.68269, lat: 27.508812 },
|
||||
{ lng: 98.246231, lat: 27.747221 },
|
||||
{ lng: 97.911988, lat: 28.335945 },
|
||||
{ lng: 97.327114, lat: 28.261583 },
|
||||
{ lng: 96.248833, lat: 28.411031 },
|
||||
{ lng: 96.586591, lat: 28.83098 },
|
||||
{ lng: 96.117679, lat: 29.452802 },
|
||||
{ lng: 95.404802, lat: 29.031717 },
|
||||
{ lng: 94.56599, lat: 29.277438 },
|
||||
{ lng: 93.413348, lat: 28.640629 },
|
||||
{ lng: 92.503119, lat: 27.896876 },
|
||||
{ lng: 91.696657, lat: 27.771742 },
|
||||
{ lng: 91.258854, lat: 28.040614 },
|
||||
{ lng: 90.730514, lat: 28.064954 },
|
||||
{ lng: 90.015829, lat: 28.296439 },
|
||||
{ lng: 89.47581, lat: 28.042759 },
|
||||
{ lng: 88.814248, lat: 27.299316 },
|
||||
{ lng: 88.730326, lat: 28.086865 },
|
||||
{ lng: 88.120441, lat: 27.876542 },
|
||||
{ lng: 86.954517, lat: 27.974262 },
|
||||
{ lng: 85.82332, lat: 28.203576 },
|
||||
{ lng: 85.011638, lat: 28.642774 },
|
||||
{ lng: 84.23458, lat: 28.839894 },
|
||||
{ lng: 83.898993, lat: 29.320226 },
|
||||
{ lng: 83.337115, lat: 29.463732 },
|
||||
{ lng: 82.327513, lat: 30.115268 },
|
||||
{ lng: 81.525804, lat: 30.422717 },
|
||||
{ lng: 81.111256, lat: 30.183481 },
|
||||
{ lng: 79.721367, lat: 30.882715 },
|
||||
{ lng: 78.738894, lat: 31.515906 },
|
||||
{ lng: 78.458446, lat: 32.618164 },
|
||||
{ lng: 79.176129, lat: 32.48378 },
|
||||
{ lng: 79.208892, lat: 32.994395 },
|
||||
{ lng: 78.811086, lat: 33.506198 },
|
||||
{ lng: 78.912269, lat: 34.321936 },
|
||||
{ lng: 77.837451, lat: 35.49401 },
|
||||
{ lng: 76.192848, lat: 35.898403 },
|
||||
{ lng: 75.896897, lat: 36.666806 },
|
||||
{ lng: 75.158028, lat: 37.133031 },
|
||||
{ lng: 74.980002, lat: 37.41999 },
|
||||
{ lng: 74.829986, lat: 37.990007 },
|
||||
{ lng: 74.864816, lat: 38.378846 },
|
||||
{ lng: 74.257514, lat: 38.606507 },
|
||||
{ lng: 73.928852, lat: 38.505815 },
|
||||
{ lng: 73.675379, lat: 39.431237 },
|
||||
{ lng: 73.960013, lat: 39.660008 },
|
||||
{ lng: 73.822244, lat: 39.893973 },
|
||||
{ lng: 74.776862, lat: 40.366425 },
|
||||
{ lng: 75.467828, lat: 40.562072 },
|
||||
{ lng: 76.526368, lat: 40.427946 },
|
||||
{ lng: 76.904484, lat: 41.066486 },
|
||||
{ lng: 78.187197, lat: 41.185316 },
|
||||
{ lng: 78.543661, lat: 41.582243 },
|
||||
{ lng: 80.11943, lat: 42.123941 },
|
||||
{ lng: 80.25999, lat: 42.349999 },
|
||||
{ lng: 80.18015, lat: 42.920068 },
|
||||
{ lng: 80.866206, lat: 43.180362 },
|
||||
{ lng: 79.966106, lat: 44.917517 },
|
||||
{ lng: 81.947071, lat: 45.317027 },
|
||||
{ lng: 82.458926, lat: 45.53965 },
|
||||
{ lng: 83.180484, lat: 47.330031 },
|
||||
{ lng: 85.16429, lat: 47.000956 },
|
||||
{ lng: 85.720484, lat: 47.452969 },
|
||||
{ lng: 85.768233, lat: 48.455751 },
|
||||
{ lng: 86.598776, lat: 48.549182 },
|
||||
{ lng: 87.35997, lat: 49.214981 },
|
||||
{ lng: 87.751264, lat: 49.297198 },
|
||||
{ lng: 88.013832, lat: 48.599463 },
|
||||
{ lng: 88.854298, lat: 48.069082 },
|
||||
{ lng: 90.280826, lat: 47.693549 },
|
||||
{ lng: 90.970809, lat: 46.888146 },
|
||||
{ lng: 90.585768, lat: 45.719716 },
|
||||
{ lng: 90.94554, lat: 45.286073 },
|
||||
{ lng: 92.133891, lat: 45.115076 },
|
||||
{ lng: 93.480734, lat: 44.975472 },
|
||||
{ lng: 94.688929, lat: 44.352332 },
|
||||
{ lng: 95.306875, lat: 44.241331 },
|
||||
{ lng: 95.762455, lat: 43.319449 },
|
||||
{ lng: 96.349396, lat: 42.725635 },
|
||||
{ lng: 97.451757, lat: 42.74889 },
|
||||
{ lng: 99.515817, lat: 42.524691 },
|
||||
{ lng: 100.845866, lat: 42.663804 },
|
||||
{ lng: 101.83304, lat: 42.514873 },
|
||||
{ lng: 103.312278, lat: 41.907468 },
|
||||
{ lng: 104.522282, lat: 41.908347 },
|
||||
{ lng: 104.964994, lat: 41.59741 },
|
||||
{ lng: 106.129316, lat: 42.134328 },
|
||||
{ lng: 107.744773, lat: 42.481516 },
|
||||
{ lng: 109.243596, lat: 42.519446 },
|
||||
{ lng: 110.412103, lat: 42.871234 },
|
||||
{ lng: 111.129682, lat: 43.406834 },
|
||||
{ lng: 111.829588, lat: 43.743118 },
|
||||
{ lng: 111.667737, lat: 44.073176 },
|
||||
{ lng: 111.348377, lat: 44.457442 },
|
||||
{ lng: 111.873306, lat: 45.102079 },
|
||||
{ lng: 112.436062, lat: 45.011646 },
|
||||
{ lng: 113.463907, lat: 44.808893 },
|
||||
{ lng: 114.460332, lat: 45.339817 },
|
||||
{ lng: 115.985096, lat: 45.727235 },
|
||||
{ lng: 116.717868, lat: 46.388202 },
|
||||
{ lng: 117.421701, lat: 46.672733 },
|
||||
{ lng: 118.874326, lat: 46.805412 },
|
||||
{ lng: 119.66327, lat: 46.69268 },
|
||||
{ lng: 119.772824, lat: 47.048059 },
|
||||
{ lng: 118.866574, lat: 47.74706 },
|
||||
{ lng: 118.064143, lat: 48.06673 },
|
||||
{ lng: 117.295507, lat: 47.697709 },
|
||||
{ lng: 116.308953, lat: 47.85341 },
|
||||
{ lng: 115.742837, lat: 47.726545 },
|
||||
{ lng: 115.485282, lat: 48.135383 },
|
||||
{ lng: 116.191802, lat: 49.134598 },
|
||||
{ lng: 116.678801, lat: 49.888531 },
|
||||
{ lng: 117.879244, lat: 49.510983 },
|
||||
{ lng: 119.288461, lat: 50.142883 },
|
||||
{ lng: 119.279366, lat: 50.582908 },
|
||||
{ lng: 120.18205, lat: 51.643566 },
|
||||
{ lng: 120.738191, lat: 51.964115 },
|
||||
{ lng: 120.725789, lat: 52.516226 },
|
||||
{ lng: 120.177089, lat: 52.753886 },
|
||||
{ lng: 121.003085, lat: 53.251401 },
|
||||
{ lng: 122.245748, lat: 53.431726 },
|
||||
{ lng: 123.571507, lat: 53.458804 },
|
||||
{ lng: 125.068211, lat: 53.161045 },
|
||||
{ lng: 125.946349, lat: 52.792799 },
|
||||
{ lng: 126.564399, lat: 51.784255 },
|
||||
{ lng: 126.939157, lat: 51.353894 },
|
||||
{ lng: 127.287456, lat: 50.739797 },
|
||||
{ lng: 127.657407, lat: 49.76027 }
|
||||
];
|
||||
|
||||
const pointlayer = new PointLayer()
|
||||
.source(
|
||||
d,
|
||||
{
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat'
|
||||
}
|
||||
}
|
||||
)
|
||||
.shape('circle')
|
||||
.color('#f00')
|
||||
.size(10)
|
||||
.active(true);
|
||||
|
||||
const earthlayer = new EarthLayer()
|
||||
.source(
|
||||
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*3-3NSpqRqUoAAAAAAAAAAAAAARQnAQ',
|
||||
{
|
||||
parser: {
|
||||
type: 'image'
|
||||
}
|
||||
}
|
||||
)
|
||||
.shape('base')
|
||||
.style({
|
||||
opacity: 1.0,
|
||||
radius: 40,
|
||||
globelOtions: {
|
||||
ambientRatio: 0.6, // 环境光
|
||||
diffuseRatio: 0.4, // 漫反射
|
||||
specularRatio: 0.1 // 高光反射
|
||||
}
|
||||
})
|
||||
.animate(true);
|
||||
|
||||
const atomLayer = new EarthLayer()
|
||||
.color('#2E8AE6')
|
||||
.shape('atomSphere')
|
||||
.style({
|
||||
opacity: 1
|
||||
});
|
||||
|
||||
const bloomLayer = new EarthLayer().color('#fff').shape('bloomSphere')
|
||||
.style({
|
||||
opacity: 0.6
|
||||
});
|
||||
|
||||
scene.on('loaded', () => {
|
||||
scene.addLayer(earthlayer);
|
||||
scene.addLayer(pointlayer);
|
||||
|
||||
scene.addLayer(atomLayer);
|
||||
scene.addLayer(bloomLayer);
|
||||
|
||||
earthlayer.setEarthTime(4.0);
|
||||
});
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: PointLayer
|
||||
order: 0
|
||||
---
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: 点图层
|
||||
order: 0
|
||||
---
|
|
@ -0,0 +1,111 @@
|
|||
import { Scene } from '@antv/l7';
|
||||
import { GaodeMap } from '@antv/l7-maps';
|
||||
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
|
||||
import * as THREE from 'three';
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
center: [ 111.4453125, 32.84267363195431 ],
|
||||
pitch: 45,
|
||||
rotation: 30,
|
||||
zoom: 12
|
||||
})
|
||||
});
|
||||
|
||||
scene.on('loaded', () => {
|
||||
scene.registerRenderService(ThreeRender);
|
||||
|
||||
const threeJSLayer = new ThreeLayer({
|
||||
enableMultiPassRenderer: false,
|
||||
onAddMeshes: (threeScene, layer) => {
|
||||
threeScene.add(new THREE.AmbientLight(0xffffff));
|
||||
const sunlight = new THREE.DirectionalLight(0xffffff, 0.25);
|
||||
sunlight.position.set(0, 80000000, 100000000);
|
||||
sunlight.matrixWorldNeedsUpdate = true;
|
||||
threeScene.add(sunlight);
|
||||
|
||||
const center = scene.getCenter();
|
||||
|
||||
const cubeGeometry = new THREE.BoxBufferGeometry(10000, 10000, 10000);
|
||||
const cubeMaterial = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide });
|
||||
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
|
||||
layer.setObjectLngLat(cube, [ center.lng + 0.05, center.lat ], 0);
|
||||
threeScene.add(cube);
|
||||
|
||||
// 使用 Three.js glTFLoader 加载模型
|
||||
const loader = new GLTFLoader();
|
||||
loader.load(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
|
||||
gltf => {
|
||||
// 根据 GeoJSON 数据放置模型
|
||||
layer.getSource().data.dataArray.forEach(({ coordinates }) => {
|
||||
const gltfScene = gltf.scene;
|
||||
setDouble(gltfScene);
|
||||
layer.adjustMeshToMap(gltfScene);
|
||||
// gltfScene.scale.set(1000, 1000, 1000)
|
||||
layer.setMeshScale(gltfScene, 1000, 1000, 1000);
|
||||
|
||||
layer.setObjectLngLat(
|
||||
gltfScene,
|
||||
[ coordinates[0] + 0.02, coordinates[1] ],
|
||||
0
|
||||
);
|
||||
|
||||
const animations = gltf.animations;
|
||||
if (animations && animations.length) {
|
||||
const mixer = new THREE.AnimationMixer(gltfScene);
|
||||
|
||||
const animation = animations[2];
|
||||
|
||||
const action = mixer.clipAction(animation);
|
||||
|
||||
action.play();
|
||||
layer.addAnimateMixer(mixer);
|
||||
}
|
||||
// layer.setObjectLngLat(gltfScene, [center.lng + 0.05, center.lat] as ILngLat, 0)
|
||||
let t = 0;
|
||||
setInterval(() => {
|
||||
t += 0.01;
|
||||
layer.setObjectLngLat(
|
||||
gltfScene,
|
||||
[ center.lng, center.lat + Math.sin(t) * 0.1 ],
|
||||
0
|
||||
);
|
||||
}, 16);
|
||||
|
||||
// 向场景中添加模型
|
||||
threeScene.add(gltfScene);
|
||||
});
|
||||
// 重绘图层
|
||||
layer.render();
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.source({
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [ 111.4453125, 32.84267363195431 ]
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
.animate(true);
|
||||
scene.addLayer(threeJSLayer);
|
||||
});
|
||||
|
||||
function setDouble(object) {
|
||||
if (object.children && object.children.length && object.children.length > 0) {
|
||||
object.children.map(child => setDouble(child));
|
||||
} else if (object.material) {
|
||||
object.material.side = THREE.DoubleSide;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
import { Scene, PolygonLayer } from '@antv/l7';
|
||||
import { GaodeMap } from '@antv/l7-maps';
|
||||
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
|
||||
import * as THREE from 'three';
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||
import { animate, easeInOut } from 'popmotion';
|
||||
|
||||
let isTravel = false;
|
||||
|
||||
function travel(
|
||||
mesh,
|
||||
path,
|
||||
duration,
|
||||
callback
|
||||
) {
|
||||
if (path.length < 2 || isTravel) return;
|
||||
isTravel = true;
|
||||
let startIndex = 0;
|
||||
const len = path.length;
|
||||
const currentP = path[0],
|
||||
nextP = path[1];
|
||||
const t = duration / len;
|
||||
|
||||
move(currentP, nextP);
|
||||
function move(currentP, nextP) {
|
||||
animate({
|
||||
from: {
|
||||
x: currentP.x,
|
||||
y: currentP.y,
|
||||
z: currentP.z
|
||||
},
|
||||
to: {
|
||||
x: nextP.x,
|
||||
y: nextP.y,
|
||||
z: nextP.z
|
||||
},
|
||||
ease: easeInOut,
|
||||
duration: t,
|
||||
repeatType: 'loop',
|
||||
onUpdate: o => {
|
||||
mesh.position.set(o.x, o.y, o.z);
|
||||
},
|
||||
onComplete: () => {
|
||||
startIndex++;
|
||||
if (startIndex < len - 1) {
|
||||
const currentP = path[startIndex],
|
||||
nextP = path[startIndex + 1];
|
||||
mesh.lookAt(nextP);
|
||||
|
||||
move(currentP, nextP);
|
||||
} else {
|
||||
isTravel = false;
|
||||
callback && callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
center: [ 112, 35.39847 ],
|
||||
pitch: 45,
|
||||
rotation: 30,
|
||||
zoom: 5
|
||||
})
|
||||
});
|
||||
|
||||
scene.on('loaded', () => {
|
||||
scene.registerRenderService(ThreeRender);
|
||||
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json'
|
||||
)
|
||||
.then(d => d.json())
|
||||
.then(data => {
|
||||
const polygonlayer = new PolygonLayer({
|
||||
name: '01',
|
||||
zIndex: -1
|
||||
})
|
||||
.source(data)
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49'
|
||||
])
|
||||
.shape('fill')
|
||||
.select(true)
|
||||
.style({
|
||||
opacity: 1.0
|
||||
});
|
||||
scene.addLayer(polygonlayer);
|
||||
});
|
||||
|
||||
const threeJSLayer = new ThreeLayer({
|
||||
enableMultiPassRenderer: false,
|
||||
onAddMeshes: (threeScene, layer) => {
|
||||
// 添加光
|
||||
threeScene.add(new THREE.AmbientLight(0xffffff));
|
||||
const sunlight = new THREE.DirectionalLight(0xffffff, 0.25);
|
||||
sunlight.position.set(0, 80000000, 100000000);
|
||||
sunlight.matrixWorldNeedsUpdate = true;
|
||||
threeScene.add(sunlight);
|
||||
|
||||
const lineData = [
|
||||
[ 116.71874999999999, 26.745610382199022 ],
|
||||
[ 117.3779296875, 28.8831596093235 ],
|
||||
[ 115.75195312499999, 31.466153715024294 ],
|
||||
[ 113.466796875, 33.32134852669881 ],
|
||||
[ 113.9501953125, 35.85343961959182 ],
|
||||
[ 115.400390625, 38.272688535980976 ],
|
||||
[ 116.5869140625, 40.3130432088809 ],
|
||||
[ 115.6201171875, 42.261049162113856 ],
|
||||
[ 112.236328125, 42.94033923363181 ],
|
||||
[ 109.3798828125, 41.04621681452063 ],
|
||||
[ 103.84277343749999, 39.80853604144591 ],
|
||||
[ 98.9208984375, 39.842286020743394 ],
|
||||
[ 95.2294921875, 40.713955826286046 ],
|
||||
[ 91.7138671875, 39.87601941962116 ],
|
||||
[ 90.8349609375, 37.125286284966805 ],
|
||||
[ 90.3076171875, 35.88905007936091 ],
|
||||
[ 90.703125, 33.284619968887675 ],
|
||||
[ 92.94433593749999, 31.98944183792288 ],
|
||||
[ 96.2841796875, 32.21280106801518 ],
|
||||
[ 98.87695312499999, 32.0639555946604 ],
|
||||
[ 102.919921875, 28.459033019728043 ],
|
||||
[ 107.9736328125, 28.497660832963472 ],
|
||||
[ 108.10546875, 24.206889622398023 ],
|
||||
[ 109.072265625, 23.039297747769726 ],
|
||||
[ 112.763671875, 24.44714958973082 ],
|
||||
[ 116.54296874999999, 25.958044673317843 ]
|
||||
];
|
||||
|
||||
const lineCoordData = lineData.map(d => {
|
||||
return layer.lnglatToCoord(d);
|
||||
});
|
||||
|
||||
|
||||
const rawPoints = [];
|
||||
lineCoordData.map(d => {
|
||||
rawPoints.push(new THREE.Vector3(d[0], d[1], 0));
|
||||
return '';
|
||||
});
|
||||
const curve = new THREE.CatmullRomCurve3(rawPoints);
|
||||
const points = curve.getPoints(200);
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints(points);
|
||||
|
||||
const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
|
||||
|
||||
const line = new THREE.LineLoop(geometry, material);
|
||||
threeScene.add(line);
|
||||
|
||||
|
||||
// 使用 Three.js glTFLoader 加载模型
|
||||
const loader = new GLTFLoader();
|
||||
loader.load(
|
||||
'https://gw.alipayobjects.com/os/antvdemo/assets/gltf/truck/CesiumMilkTruck.gltf', // Truck
|
||||
gltf => {
|
||||
// 根据 GeoJSON 数据放置模型
|
||||
const gltfScene = gltf.scene.clone();
|
||||
setDouble(gltfScene);
|
||||
layer.getSource().data.dataArray.forEach(() => {
|
||||
layer.adjustMeshToMap(gltfScene);
|
||||
gltfScene.scale.set(500000, 500000, 500000);
|
||||
|
||||
const animations = gltf.animations;
|
||||
if (animations && animations.length) {
|
||||
const mixer = new THREE.AnimationMixer(gltfScene);
|
||||
// @ts-ignore
|
||||
for (let i = 0; i < animations.length; i++) {
|
||||
const animation = animations[i];
|
||||
|
||||
// There's .3333 seconds junk at the tail of the Monster animation that
|
||||
// keeps it from looping cleanly. Clip it at 3 seconds
|
||||
|
||||
const action = mixer.clipAction(animation);
|
||||
|
||||
action.play();
|
||||
}
|
||||
layer.addAnimateMixer(mixer);
|
||||
}
|
||||
|
||||
// 向场景中添加模型
|
||||
threeScene.add(gltfScene);
|
||||
});
|
||||
|
||||
travelLoop();
|
||||
function travelLoop() {
|
||||
travel(gltfScene, points, 5000, () => {
|
||||
travelLoop();
|
||||
});
|
||||
}
|
||||
// 重绘图层
|
||||
layer.render();
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.source({
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [ 112, 35.39847 ]
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
.animate(true);
|
||||
scene.addLayer(threeJSLayer);
|
||||
});
|
||||
|
||||
function setDouble(object) {
|
||||
if (object.children && object.children.length && object.children.length > 0) {
|
||||
object.children.map(child => setDouble(child));
|
||||
} else if (object.material) {
|
||||
object.material.side = THREE.DoubleSide;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
import { Scene } from '@antv/l7';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
|
||||
import * as THREE from 'three';
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Mapbox({
|
||||
center: [ 121.4, 31.258134 ],
|
||||
pitch: 45,
|
||||
rotation: 30,
|
||||
zoom: 15
|
||||
})
|
||||
});
|
||||
|
||||
scene.on('loaded', () => {
|
||||
scene.registerRenderService(ThreeRender);
|
||||
|
||||
const threeJSLayer = new ThreeLayer({
|
||||
enableMultiPassRenderer: false,
|
||||
onAddMeshes: (threeScene, layer) => {
|
||||
threeScene.add(new THREE.AmbientLight(0xffffff));
|
||||
const sunlight = new THREE.DirectionalLight(0xffffff, 0.25);
|
||||
sunlight.position.set(0, 80000000, 100000000);
|
||||
sunlight.matrixWorldNeedsUpdate = true;
|
||||
threeScene.add(sunlight);
|
||||
// 使用 Three.js glTFLoader 加载模型
|
||||
|
||||
const loader = new GLTFLoader();
|
||||
loader.load(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
|
||||
gltf => {
|
||||
// 根据 GeoJSON 数据放置模型
|
||||
layer.getSource().data.dataArray.forEach(() => {
|
||||
const gltfScene = gltf.scene;
|
||||
|
||||
layer.adjustMeshToMap(gltfScene);
|
||||
layer.setMeshScale(gltfScene, 10, 10, 10);
|
||||
|
||||
const animations = gltf.animations;
|
||||
if (animations && animations.length) {
|
||||
const mixer = new THREE.AnimationMixer(gltfScene);
|
||||
const animation = animations[2];
|
||||
const action = mixer.clipAction(animation);
|
||||
action.play();
|
||||
layer.addAnimateMixer(mixer);
|
||||
}
|
||||
// 向场景中添加模型
|
||||
threeScene.add(gltfScene);
|
||||
});
|
||||
// 重绘图层
|
||||
layer.render();
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.source({
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [ 121.4, 31.258134 ]
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
.animate(true);
|
||||
scene.addLayer(threeJSLayer);
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"title": {
|
||||
"zh": "第三方引擎",
|
||||
"en": "other engine"
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "amap_ant.js",
|
||||
"title": "高德地图",
|
||||
"screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*1_W2SIR8swwAAAAAAAAAAAAAARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "amap_car.js",
|
||||
"title": "高德地图 car",
|
||||
"screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*C3JRTI_qlxEAAAAAAAAAAAAAARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "mapbox_ant.js",
|
||||
"title": "mapbox 地图",
|
||||
"screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*kflKRJvm3hYAAAAAAAAAAAAAARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "space_click.js",
|
||||
"title": "点击建筑",
|
||||
"screenshot":"https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*AY5vSIMeLy8AAAAAAAAAAAAAARQnAQ"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,437 @@
|
|||
import { Scene } from '@antv/l7';
|
||||
import { GaodeMap } from '@antv/l7-maps';
|
||||
import { ThreeLayer, ThreeRender } from '@antv/l7-three';
|
||||
import * as THREE from 'three';
|
||||
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader';
|
||||
import { animate, easeInOut } from 'popmotion';
|
||||
|
||||
function changeValue(
|
||||
startValue,
|
||||
endValue,
|
||||
duration = 500,
|
||||
callback,
|
||||
complete
|
||||
) {
|
||||
if (typeof startValue === 'number') {
|
||||
animate({
|
||||
from: {
|
||||
v: startValue
|
||||
},
|
||||
to: {
|
||||
v: endValue
|
||||
},
|
||||
ease: easeInOut,
|
||||
duration,
|
||||
onUpdate: o => {
|
||||
callback(o.v);
|
||||
return '';
|
||||
},
|
||||
onComplete: () => {
|
||||
complete && complete();
|
||||
return '';
|
||||
}
|
||||
});
|
||||
} else {
|
||||
animate({
|
||||
from: {
|
||||
lng: startValue.lng,
|
||||
lat: startValue.lat,
|
||||
pitch: startValue.pitch,
|
||||
rotation: startValue.rotation,
|
||||
zoom: startValue.zoom
|
||||
},
|
||||
to: {
|
||||
lng: (endValue).lng,
|
||||
lat: (endValue).lat,
|
||||
pitch: (endValue).pitch,
|
||||
rotation: (endValue).rotation,
|
||||
zoom: (endValue).zoom
|
||||
},
|
||||
ease: easeInOut,
|
||||
duration,
|
||||
onUpdate: o => {
|
||||
callback(o);
|
||||
return '';
|
||||
},
|
||||
onComplete: () => {
|
||||
complete && complete();
|
||||
return '';
|
||||
}
|
||||
});
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
const raycaster = new THREE.Raycaster();
|
||||
const lng = 120.1;
|
||||
const lat = 30.265;
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
center: [ lng, lat ],
|
||||
pitch: 70,
|
||||
rotation: 220,
|
||||
zoom: 16
|
||||
})
|
||||
});
|
||||
|
||||
scene.on('loaded', () => {
|
||||
|
||||
const mouse = new THREE.Vector2();
|
||||
let zspace,
|
||||
aspace,
|
||||
ASpaceTextMesh,
|
||||
ZSpaceTextMesh;
|
||||
|
||||
scene.registerRenderService(ThreeRender);
|
||||
|
||||
const center = scene.getCenter();
|
||||
|
||||
const threeJSLayer = new ThreeLayer({
|
||||
enableMultiPassRenderer: false,
|
||||
// @ts-ignore
|
||||
onAddMeshes: (threeScene, layer) => {
|
||||
threeScene.add(new THREE.AmbientLight(0xffffff));
|
||||
const sunlight = new THREE.DirectionalLight(0xffffff, 0.25);
|
||||
sunlight.position.set(0, 80000000, 100000000);
|
||||
sunlight.matrixWorldNeedsUpdate = true;
|
||||
threeScene.add(sunlight);
|
||||
|
||||
// map
|
||||
// https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ
|
||||
|
||||
// height
|
||||
// https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ
|
||||
|
||||
const image = new Image();
|
||||
image.crossOrigin = '';
|
||||
image.src =
|
||||
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*eYFaRYlnnOUAAAAAAAAAAAAAARQnAQ';
|
||||
image.onload = () => {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(image, 0, 0, image.width, image.height);
|
||||
const heightData = ctx.getImageData(0, 0, image.width, image.height)
|
||||
.data;
|
||||
|
||||
const s = 53000;
|
||||
|
||||
const geometry = new THREE.PlaneGeometry(s, s, 255, 255);
|
||||
|
||||
geometry.vertices.map((v, i) => {
|
||||
const r = heightData[i * 4];
|
||||
const g = heightData[i * 4 + 1];
|
||||
const b = heightData[i * 4 + 2];
|
||||
let h =
|
||||
-10000.0 +
|
||||
(r * 255.0 * 256.0 * 256.0 + g * 255.0 * 256.0 + b * 255.0) *
|
||||
0.1;
|
||||
h = h / 20 - 127600;
|
||||
h = Math.max(0, h);
|
||||
|
||||
v.z = h;
|
||||
return '';
|
||||
});
|
||||
const material = new THREE.MeshPhongMaterial({
|
||||
transparent: true,
|
||||
// opacity: 0.6,
|
||||
map: new THREE.TextureLoader().load(
|
||||
'https://gw.alipayobjects.com/mdn/rms_23a451/afts/img/A*gA0NRbuOF5cAAAAAAAAAAAAAARQnAQ'
|
||||
),
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
const plane = new THREE.Mesh(geometry, material);
|
||||
layer.setObjectLngLat(plane, [ 120.1008, 30.2573 ], 0);
|
||||
plane.position.z = 10;
|
||||
threeScene.add(plane);
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
// 使用 Three.js glTFLoader 加载模型
|
||||
const loader = new GLTFLoader();
|
||||
loader.load(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/3ca0a546-92d8-4ba0-a89c-017c218d5bea.gltf',
|
||||
gltf => {
|
||||
const antModel = gltf.scene;
|
||||
setDouble(antModel);
|
||||
// antModel.children[0].material.side = THREE.DoubleSide
|
||||
layer.adjustMeshToMap(antModel);
|
||||
layer.setMeshScale(antModel, 20, 20, 20);
|
||||
layer.setObjectLngLat(
|
||||
antModel,
|
||||
[ center.lng - 0.002, center.lat ],
|
||||
0
|
||||
);
|
||||
|
||||
const animations = gltf.animations;
|
||||
if (animations && animations.length) {
|
||||
const mixer = new THREE.AnimationMixer(antModel);
|
||||
const animation = animations[1];
|
||||
const action = mixer.clipAction(animation);
|
||||
action.play();
|
||||
layer.addAnimateMixer(mixer);
|
||||
}
|
||||
antModel.rotation.y = Math.PI;
|
||||
// 向场景中添加模型
|
||||
threeScene.add(antModel);
|
||||
// 重绘图层
|
||||
layer.render();
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
const v = `
|
||||
varying vec2 vUv;
|
||||
varying vec4 worldPosition;
|
||||
void main() {
|
||||
vUv = uv;
|
||||
worldPosition = modelMatrix * vec4(position, 1.0);
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}`;
|
||||
const f = `
|
||||
varying vec2 vUv;
|
||||
varying vec4 worldPosition;
|
||||
uniform vec3 color;
|
||||
void main() {
|
||||
gl_FragColor = vec4(color, fract(worldPosition.z / 50.0));
|
||||
}`;
|
||||
const shadermaterial = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
color: {
|
||||
value: new THREE.Vector3(0.21372549, 0.34705882, 0.56470588)
|
||||
}
|
||||
},
|
||||
vertexShader: v,
|
||||
fragmentShader: f,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
|
||||
const fbxLoaded = new FBXLoader();
|
||||
// load ZSpace
|
||||
fbxLoaded.load(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/af1652c9-3c4f-4e73-ac4c-1f78fefbaf6a.fbx',
|
||||
gltf => {
|
||||
zspace = gltf;
|
||||
layer.adjustMeshToMap(zspace);
|
||||
// @ts-ignore
|
||||
zspace.children[0].material = shadermaterial;
|
||||
layer.setMeshScale(zspace, 10, 10, 10);
|
||||
|
||||
layer.setObjectLngLat(zspace, [ 120.1015, 30.2661 ], 0);
|
||||
zspace.rotation.x = Math.PI * 2;
|
||||
zspace.rotation.z = -Math.PI * (-2 / 15);
|
||||
threeScene.add(zspace);
|
||||
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
fbxLoaded.load(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/11d6e4c1-bd5b-4dc1-bae5-ac51c14e9056.fbx',
|
||||
model => {
|
||||
aspace = model;
|
||||
layer.adjustMeshToMap(aspace);
|
||||
// @ts-ignore
|
||||
aspace.children[0].material = shadermaterial;
|
||||
|
||||
layer.setMeshScale(aspace, 8, 8, 8);
|
||||
layer.setObjectLngLat(aspace, [ 120.099, 30.261 ], 0);
|
||||
aspace.rotation.x = Math.PI * 2;
|
||||
aspace.rotation.z = -Math.PI * (3 / 15);
|
||||
threeScene.add(aspace);
|
||||
|
||||
return '';
|
||||
}
|
||||
);
|
||||
|
||||
const textLoader = new THREE.FontLoader();
|
||||
textLoader.load(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/0a3f46eb-294e-4d95-87f2-052c26ad4bf1.json',
|
||||
font => {
|
||||
const fontOptions = {
|
||||
size: 360, // 字号大小,一般为大写字母的高度
|
||||
height: 50, // 文字的厚度
|
||||
font, // 字体,默认是'helvetiker',需对应引用的字体文件
|
||||
bevelThickness: 10, // 倒角厚度
|
||||
bevelSize: 10, // 倒角宽度
|
||||
curveSegments: 30, // 弧线分段数,使得文字的曲线更加光滑
|
||||
bevelEnabled: true // 布尔值,是否使用倒角,意为在边缘处斜切
|
||||
};
|
||||
const aspaceGeo = new THREE.TextGeometry('ASpace', fontOptions);
|
||||
aspaceGeo.center();
|
||||
const zspaceGeo = new THREE.TextGeometry('ZSpace', fontOptions);
|
||||
zspaceGeo.center();
|
||||
|
||||
const fontMat = new THREE.MeshPhongMaterial({
|
||||
color: 0xcccccc,
|
||||
shininess: 60,
|
||||
specular: 0xcccccc,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
|
||||
const testHeight = 900;
|
||||
|
||||
ASpaceTextMesh = new THREE.Mesh(aspaceGeo, fontMat);
|
||||
ASpaceTextMesh.rotation.x = Math.PI / 2;
|
||||
ASpaceTextMesh.rotation.y = (-Math.PI * 3) / 4;
|
||||
layer.setObjectLngLat(
|
||||
ASpaceTextMesh,
|
||||
[ 120.099, 30.261 ],
|
||||
testHeight
|
||||
);
|
||||
threeScene.add(ASpaceTextMesh);
|
||||
|
||||
ZSpaceTextMesh = new THREE.Mesh(zspaceGeo, fontMat);
|
||||
ZSpaceTextMesh.rotation.x = Math.PI / 2;
|
||||
ZSpaceTextMesh.rotation.y = (-Math.PI * 3) / 4;
|
||||
layer.setObjectLngLat(
|
||||
ZSpaceTextMesh,
|
||||
[ 120.103, 30.2661 ],
|
||||
testHeight
|
||||
);
|
||||
threeScene.add(ZSpaceTextMesh);
|
||||
|
||||
getH(0, 200);
|
||||
function getH(h1, h2) {
|
||||
changeValue(
|
||||
h1,
|
||||
h2,
|
||||
1000,
|
||||
h => {
|
||||
ASpaceTextMesh.position.z = testHeight + h;
|
||||
ZSpaceTextMesh.position.z = testHeight + h;
|
||||
return '';
|
||||
},
|
||||
() => {
|
||||
setTimeout(() => getH(h2, h1), 10);
|
||||
return '';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
.source({
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [ 111.4453125, 32.84267363195431 ]
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
.animate(true);
|
||||
scene.addLayer(threeJSLayer);
|
||||
// @ts-ignore
|
||||
let currentCamera = threeJSLayer.threeRenderService.getRenderCamera();
|
||||
const currentView = {
|
||||
lng: center.lng,
|
||||
lat: center.lat,
|
||||
pitch: 70,
|
||||
rotation: 220,
|
||||
zoom: 16
|
||||
};
|
||||
|
||||
scene.on('zoom', () => {
|
||||
const cen = scene.getCenter();
|
||||
currentView.lng = cen.lng;
|
||||
currentView.lat = cen.lat;
|
||||
currentView.pitch = scene.getPitch();
|
||||
currentView.zoom = scene.getZoom();
|
||||
return '';
|
||||
});
|
||||
|
||||
scene.getMapService().on('mapchange', () => {
|
||||
// @ts-ignore
|
||||
currentCamera = threeJSLayer.getRenderCamera();
|
||||
currentView.pitch = scene.getPitch();
|
||||
return '';
|
||||
});
|
||||
|
||||
const ASpaceView = {
|
||||
lng: 120.109509,
|
||||
lat: 30.251529,
|
||||
pitch: 83,
|
||||
rotation: 225,
|
||||
zoom: 16
|
||||
};
|
||||
const ZSpaceView = {
|
||||
lng: 120.112026,
|
||||
lat: 30.256881,
|
||||
pitch: 80,
|
||||
rotation: 220,
|
||||
zoom: 16
|
||||
};
|
||||
|
||||
scene.on('click', ev => {
|
||||
// @ts-ignore
|
||||
const size = scene?.map?.getSize();
|
||||
mouse.x = (ev.pixel.x / size.width) * 2 - 1;
|
||||
mouse.y = -(ev.pixel.y / size.height) * 2 + 1;
|
||||
raycaster.setFromCamera(mouse, currentCamera);
|
||||
const intersects = raycaster.intersectObjects([ zspace, aspace ], true);
|
||||
if (intersects.length > 0) {
|
||||
const object = intersects[0].object;
|
||||
if (object.name === 'Z空间') {
|
||||
selectSpace(currentView, ZSpaceView, ZSpaceTextMesh);
|
||||
} else {
|
||||
selectSpace(currentView, ASpaceView, ASpaceTextMesh);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
function selectSpace(
|
||||
currentView,
|
||||
targetView,
|
||||
spaceText
|
||||
) {
|
||||
if (spaceText) {
|
||||
changeValue(
|
||||
spaceText.rotation.y,
|
||||
spaceText.rotation.y + Math.PI * 2,
|
||||
500,
|
||||
r => {
|
||||
spaceText.rotation.y = r;
|
||||
return '';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
changeValue(currentView, targetView, 500, view => {
|
||||
scene.setCenter([ view.lng, view.lat ]);
|
||||
scene.setPitch(view.pitch);
|
||||
scene.setRotation(view.rotation);
|
||||
scene.setZoom(view.zoom);
|
||||
|
||||
currentView.lng = view.lng;
|
||||
currentView.lat = view.lat;
|
||||
currentView.pitch = view.pitch;
|
||||
currentView.rotation = view.rotation;
|
||||
currentView.zoom = view.zoom;
|
||||
|
||||
return '';
|
||||
});
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
function setDouble(object) {
|
||||
if (object.children && object.children.length && object.children.length > 0) {
|
||||
object.children.map(child => setDouble(child));
|
||||
} else if (object.material) {
|
||||
object.material.side = THREE.DoubleSide;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Threejs
|
||||
order: 0
|
||||
---
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Threejs
|
||||
order: 0
|
||||
---
|
|
@ -9,6 +9,11 @@ window.l7Maps = require('@antv/l7-maps');
|
|||
window.l7React = require('@antv/l7-react');
|
||||
window.l7Draw = require('@antv/l7-draw');
|
||||
window.l7District = require('@antv/l7-district');
|
||||
window.l7Three = require('@antv/l7-three');
|
||||
window.three = require('three');
|
||||
window.GLTFLoader = require('three/examples/jsm/loaders/GLTFLoader');
|
||||
window.FBXLoader = require('three/examples/jsm/loaders/FBXLoader');
|
||||
window.react = require('react');
|
||||
window.popmotion = require('popmotion');
|
||||
window.reactDom = require('react-dom');
|
||||
window.antd = require('antd');
|
||||
|
|
|
@ -190,6 +190,14 @@ module.exports = {
|
|||
en: 'import other gl'
|
||||
},
|
||||
order: 3
|
||||
},
|
||||
{
|
||||
slug: 'api/earth',
|
||||
title: {
|
||||
zh: '地球模式',
|
||||
en: 'Earth Mode'
|
||||
},
|
||||
order: 3
|
||||
}
|
||||
],
|
||||
examples: [
|
||||
|
@ -225,6 +233,22 @@ module.exports = {
|
|||
en: 'L7 Draw'
|
||||
}
|
||||
},
|
||||
{
|
||||
slug: 'engine',
|
||||
icon: 'map',
|
||||
title: {
|
||||
zh: '第三方引擎',
|
||||
en: 'other engine'
|
||||
}
|
||||
},
|
||||
{
|
||||
slug: 'earth',
|
||||
icon: 'map',
|
||||
title: {
|
||||
zh: '地球模式',
|
||||
en: 'Earth Mode'
|
||||
}
|
||||
},
|
||||
{
|
||||
slug: 'point',
|
||||
icon: 'point',
|
||||
|
|
|
@ -19,6 +19,7 @@ exports.onCreateWebpackConfig = ({ getConfig }) => {
|
|||
'@antv/l7-renderer': path.resolve(__dirname, 'packages/renderer/src'),
|
||||
'@antv/l7-scene': path.resolve(__dirname, 'packages/scene/src'),
|
||||
'@antv/l7-source': path.resolve(__dirname, 'packages/source/src'),
|
||||
'@antv/l7-utils': path.resolve(__dirname, 'packages/utils/src')
|
||||
'@antv/l7-utils': path.resolve(__dirname, 'packages/utils/src'),
|
||||
'@antv/l7-three': path.resolve(__dirname, 'packages/three/src')
|
||||
}
|
||||
};
|
||||
|
|
22
latest.sh
22
latest.sh
|
@ -1,11 +1,11 @@
|
|||
npm dist-tag add @antv/l7-component@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-core@2.5.19 latest
|
||||
npm dist-tag add @antv/l7@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-layers@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-map@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-maps@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-renderer@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-scene@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-source@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-three@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-utils@2.5.19 latest
|
||||
npm dist-tag add @antv/l7-component@2.5.35 latest
|
||||
npm dist-tag add @antv/l7-core@2.5.35 latest
|
||||
npm dist-tag add @antv/l7@2.5.35 latest
|
||||
npm dist-tag add @antv/l7-layers@2.5.35 latest
|
||||
npm dist-tag add @antv/l7-map@2.5.35 latest
|
||||
npm dist-tag add @antv/l7-maps@2.5.35 latest
|
||||
npm dist-tag add @antv/l7-renderer@2.5.35 latest
|
||||
npm dist-tag add @antv/l7-scene@2.5.35 latest
|
||||
npm dist-tag add @antv/l7-source@2.5.35 latest
|
||||
npm dist-tag add @antv/l7-three@2.5.35 latest
|
||||
npm dist-tag add @antv/l7-utils@2.5.35 latest
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"message": "chore: publish"
|
||||
}
|
||||
},
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"publishConfig": {
|
||||
|
|
|
@ -197,5 +197,7 @@
|
|||
"tnpm": {
|
||||
"mode": "yarn"
|
||||
},
|
||||
"dependencies": {}
|
||||
"dependencies": {
|
||||
"@antv/geo-coord": "^1.0.8"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-component",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -25,8 +25,8 @@
|
|||
"author": "lzxue",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/l7-core": "^2.5.30",
|
||||
"@antv/l7-utils": "^2.5.30",
|
||||
"@antv/l7-core": "^2.5.41",
|
||||
"@antv/l7-utils": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"eventemitter3": "^4.0.0",
|
||||
"inversify": "^5.0.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-core",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -24,7 +24,7 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/async-hook": "^2.1.0",
|
||||
"@antv/l7-utils": "^2.5.30",
|
||||
"@antv/l7-utils": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@mapbox/tiny-sdf": "^1.1.1",
|
||||
"ajv": "^6.10.2",
|
||||
|
|
|
@ -140,7 +140,14 @@ export default class PickingService implements IPickingService {
|
|||
return features;
|
||||
}
|
||||
private async pickingAllLayer(target: IInteractionTarget) {
|
||||
if (this.alreadyInPicking || this.layerService.alreadyInRendering) {
|
||||
if (
|
||||
// TODO: this.alreadyInPicking 避免多次重复拾取
|
||||
this.alreadyInPicking ||
|
||||
// TODO: this.layerService.alreadyInRendering 一个渲染序列中只进行一次拾取操作
|
||||
this.layerService.alreadyInRendering ||
|
||||
// TODO: this.layerService.isMapDragging() 如果地图正在拖拽 则不进行拾取操作
|
||||
this.layerService.isMapDragging()
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.alreadyInPicking = true;
|
||||
|
|
|
@ -101,6 +101,8 @@ export interface ILayer {
|
|||
layerModelNeedUpdate: boolean;
|
||||
styleNeedUpdate: boolean;
|
||||
layerModel: ILayerModel;
|
||||
layerChildren: ILayer[]; // 在图层中添加子图层
|
||||
sceneContainer: Container | undefined;
|
||||
dataState: IDataState; // 数据流状态
|
||||
pickedFeatureID: number | null;
|
||||
hooks: {
|
||||
|
@ -124,10 +126,20 @@ export interface ILayer {
|
|||
options?: ISourceCFG;
|
||||
};
|
||||
multiPassRenderer: IMultiPassRenderer;
|
||||
|
||||
/**
|
||||
* threejs 适配兼容相关的方法
|
||||
* @param lnglat
|
||||
* @param altitude
|
||||
* @param rotation
|
||||
* @param scale
|
||||
*/
|
||||
|
||||
threeRenderService?: any;
|
||||
needPick(type: string): boolean;
|
||||
getLayerConfig(): Partial<ILayerConfig & ISceneConfig>;
|
||||
getContainer(): Container;
|
||||
setContainer(container: Container): void;
|
||||
setContainer(container: Container, sceneContainer: Container): void;
|
||||
setCurrentPickId(id: number | null): void;
|
||||
getCurrentPickId(): number | null;
|
||||
setCurrentSelectedId(id: number | null): void;
|
||||
|
@ -220,14 +232,6 @@ export interface ILayer {
|
|||
setAnimateStartTime(): void;
|
||||
getLayerAnimateTime(): number;
|
||||
|
||||
/**
|
||||
* threejs 适配兼容相关的方法
|
||||
* @param lnglat
|
||||
* @param altitude
|
||||
* @param rotation
|
||||
* @param scale
|
||||
*/
|
||||
|
||||
// 获取对应地图的经纬度模型矩阵
|
||||
getModelMatrix?(
|
||||
lnglat: ILngLat,
|
||||
|
@ -260,6 +264,9 @@ export interface ILayer {
|
|||
// 增加加载模型的动画混合器
|
||||
addAnimateMixer?(mixer: any): void;
|
||||
|
||||
// 返回当前的 threejs camera
|
||||
getRenderCamera?(): any;
|
||||
|
||||
/**
|
||||
* 地球模式相关的方法
|
||||
*/
|
||||
|
@ -372,10 +379,11 @@ export interface ILayerService {
|
|||
getLayers(): ILayer[];
|
||||
getLayer(id: string): ILayer | undefined;
|
||||
getLayerByName(name: string): ILayer | undefined;
|
||||
remove(layer: ILayer): void;
|
||||
remove(layer: ILayer, parentLayer?: ILayer): void;
|
||||
removeAllLayers(): void;
|
||||
updateRenderOrder(): void;
|
||||
renderLayers(type?: string): void;
|
||||
getOESTextureFloat(): boolean;
|
||||
isMapDragging(): boolean;
|
||||
destroy(): void;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { rgb2arr } from '@antv/l7-utils';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import 'reflect-metadata';
|
||||
import { ILayer } from '../..';
|
||||
import { TYPES } from '../../types';
|
||||
import Clock from '../../utils/clock';
|
||||
import { IGlobalConfigService } from '../config/IConfigService';
|
||||
import { IMapService } from '../map/IMapService';
|
||||
import { IRendererService } from '../renderer/IRendererService';
|
||||
import { ILayerModel, ILayerService } from './ILayerService';
|
||||
|
||||
|
@ -28,6 +30,9 @@ export default class LayerService implements ILayerService {
|
|||
@inject(TYPES.IRendererService)
|
||||
private readonly renderService: IRendererService;
|
||||
|
||||
@inject(TYPES.IMapService)
|
||||
private readonly mapService: IMapService;
|
||||
|
||||
@inject(TYPES.IGlobalConfigService)
|
||||
private readonly configService: IGlobalConfigService;
|
||||
|
||||
|
@ -59,11 +64,20 @@ export default class LayerService implements ILayerService {
|
|||
return this.layers.find((layer) => layer.name === name);
|
||||
}
|
||||
|
||||
public remove(layer: ILayer): void {
|
||||
const layerIndex = this.layers.indexOf(layer);
|
||||
if (layerIndex > -1) {
|
||||
this.layers.splice(layerIndex, 1);
|
||||
public remove(layer: ILayer, parentLayer?: ILayer): void {
|
||||
// Tip: layer.layerChildren 当 layer 存在子图层的情况
|
||||
if (parentLayer) {
|
||||
const layerIndex = parentLayer.layerChildren.indexOf(layer);
|
||||
if (layerIndex > -1) {
|
||||
parentLayer.layerChildren.splice(layerIndex, 1);
|
||||
}
|
||||
} else {
|
||||
const layerIndex = this.layers.indexOf(layer);
|
||||
if (layerIndex > -1) {
|
||||
this.layers.splice(layerIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
layer.emit('remove', null);
|
||||
layer.destroy();
|
||||
this.renderLayers();
|
||||
|
@ -86,17 +100,29 @@ export default class LayerService implements ILayerService {
|
|||
this.alreadyInRendering = true;
|
||||
this.clear();
|
||||
this.updateRenderOrder();
|
||||
|
||||
this.layers
|
||||
.filter((layer) => layer.inited)
|
||||
.filter((layer) => layer.isVisible())
|
||||
.forEach((layer) => {
|
||||
// trigger hooks
|
||||
layer.hooks.beforeRenderData.call();
|
||||
layer.hooks.beforeRender.call();
|
||||
layer.render();
|
||||
layer.hooks.afterRender.call();
|
||||
// Tip: 渲染 layer 的子图层 默认 layerChildren 为空数组 表示没有子图层 目前只有 ImageTileLayer 有子图层
|
||||
renderLayerEvent(layer.layerChildren);
|
||||
renderLayerEvent([layer]);
|
||||
});
|
||||
this.alreadyInRendering = false;
|
||||
|
||||
function renderLayerEvent(layers: ILayer[]) {
|
||||
layers
|
||||
.filter((layer) => layer.inited)
|
||||
.filter((layer) => layer.isVisible())
|
||||
.forEach((layer) => {
|
||||
// trigger hooks
|
||||
layer.hooks.beforeRenderData.call();
|
||||
layer.hooks.beforeRender.call();
|
||||
layer.render();
|
||||
layer.hooks.afterRender.call();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public updateRenderOrder() {
|
||||
|
@ -106,7 +132,14 @@ export default class LayerService implements ILayerService {
|
|||
}
|
||||
|
||||
public destroy() {
|
||||
this.layers.forEach((layer) => layer.destroy());
|
||||
this.layers.forEach((layer) => {
|
||||
// Tip: layer.layerChildren 当 layer 存在子图层的情况
|
||||
if (layer.layerChildren) {
|
||||
layer.layerChildren.forEach((child) => child.destroy());
|
||||
layer.layerChildren = [];
|
||||
}
|
||||
layer.destroy();
|
||||
});
|
||||
this.layers = [];
|
||||
this.renderLayers();
|
||||
}
|
||||
|
@ -129,6 +162,16 @@ export default class LayerService implements ILayerService {
|
|||
return this.renderService.extensionObject.OES_texture_float;
|
||||
}
|
||||
|
||||
// TODO: 判断地图是否正在被拖动
|
||||
public isMapDragging() {
|
||||
return this.mapService.dragging;
|
||||
}
|
||||
|
||||
private runRender() {
|
||||
this.renderLayers();
|
||||
this.layerRenderID = requestAnimationFrame(this.runRender.bind(this));
|
||||
}
|
||||
|
||||
// 渲染检测
|
||||
private renderTest(renderType: string | undefined): boolean {
|
||||
const now = new Date().getTime();
|
||||
|
@ -141,8 +184,9 @@ export default class LayerService implements ILayerService {
|
|||
if (renderType) {
|
||||
switch (renderType) {
|
||||
case 'picking':
|
||||
// return false;
|
||||
// TODO: picking 类型的渲染事件
|
||||
// 若是上次触发为地图或动画触发的渲染,则认为是地图事件与拾取事件在同时触发,放弃此次渲染
|
||||
// 若是上次触发为地图触发的渲染,则认为是地图事件与拾取事件在同时触发,放弃此次渲染
|
||||
if (
|
||||
this.lastRenderType === 'mapRender' ||
|
||||
this.lastRenderType === 'animate'
|
||||
|
@ -159,6 +203,7 @@ export default class LayerService implements ILayerService {
|
|||
return true;
|
||||
}
|
||||
case 'animate':
|
||||
// return false;
|
||||
if (this.lastRenderType === 'mapRender') {
|
||||
this.lastRenderType = 'animate';
|
||||
return false;
|
||||
|
@ -178,19 +223,20 @@ export default class LayerService implements ILayerService {
|
|||
}
|
||||
|
||||
private clear() {
|
||||
const color = rgb2arr(this.mapService.bgColor) as [
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
number,
|
||||
];
|
||||
this.renderService.clear({
|
||||
color: [0, 0, 0, 0],
|
||||
color,
|
||||
depth: 1,
|
||||
stencil: 0,
|
||||
framebuffer: null,
|
||||
});
|
||||
}
|
||||
|
||||
private runRender() {
|
||||
this.renderLayers('animate');
|
||||
this.layerRenderID = requestAnimationFrame(this.runRender.bind(this));
|
||||
}
|
||||
|
||||
private stopRender() {
|
||||
cancelAnimationFrame(this.layerRenderID);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,9 @@ export interface IMapWrapper {
|
|||
export interface IMapService<RawMap = {}> {
|
||||
version?: string;
|
||||
map: RawMap;
|
||||
dragging: boolean;
|
||||
bgColor: string;
|
||||
setBgColor(color: string): void;
|
||||
init(): void;
|
||||
initViewPort?(): void;
|
||||
destroy(): void;
|
||||
|
@ -106,7 +109,86 @@ export interface IMapService<RawMap = {}> {
|
|||
): void;
|
||||
}
|
||||
|
||||
export const MapServiceEvent = ['mapload'];
|
||||
export interface IEarthService<RawMap = {}> {
|
||||
version?: string;
|
||||
map: RawMap;
|
||||
bgColor: string;
|
||||
setBgColor(color: string): void;
|
||||
init(): void;
|
||||
initViewPort?(): void;
|
||||
destroy(): void;
|
||||
onCameraChanged(callback: (viewport: IViewport) => void): void;
|
||||
// init map
|
||||
addMarkerContainer(): void;
|
||||
getMarkerContainer(): HTMLElement;
|
||||
// MapEvent // 定义事件类型
|
||||
|
||||
on(type: string, handler: (...args: any[]) => void): void;
|
||||
off(type: string, handler: (...args: any[]) => void): void;
|
||||
once(type: string, handler: (...args: any[]) => void): void;
|
||||
// get dom
|
||||
getContainer(): HTMLElement | null;
|
||||
getSize(): [number, number];
|
||||
// get map status method
|
||||
getMinZoom(): number;
|
||||
getMaxZoom(): number;
|
||||
// get map params
|
||||
getType(): string;
|
||||
getZoom(): number;
|
||||
getCenter(option?: ICameraOptions): ILngLat;
|
||||
getPitch(): number;
|
||||
getRotation(): number;
|
||||
getBounds(): Bounds;
|
||||
getMapContainer(): HTMLElement | null;
|
||||
getMapCanvasContainer(): HTMLElement;
|
||||
|
||||
// control with raw map
|
||||
setRotation(rotation: number): void;
|
||||
zoomIn(option?: any, eventData?: any): void;
|
||||
zoomOut(option?: any, eventData?: any): void;
|
||||
panTo(p: Point): void;
|
||||
panBy(x: number, y: number): void;
|
||||
fitBounds(bound: Bounds, fitBoundsOptions?: unknown): void;
|
||||
setZoomAndCenter(zoom: number, center: Point): void;
|
||||
setCenter(center: [number, number], option?: ICameraOptions): void;
|
||||
setPitch(pitch: number): void;
|
||||
setZoom(zoom: number): void;
|
||||
setMapStyle(style: any): void;
|
||||
setMapStatus(option: Partial<IStatusOptions>): void;
|
||||
|
||||
// coordinates methods
|
||||
pixelToLngLat(pixel: Point): ILngLat;
|
||||
lngLatToPixel(lnglat: Point): IPoint;
|
||||
containerToLngLat(pixel: Point): ILngLat;
|
||||
lngLatToContainer(lnglat: Point): IPoint;
|
||||
lngLatToMercator(lnglat: [number, number], altitude: number): IMercator;
|
||||
getModelMatrix(
|
||||
lnglat: [number, number],
|
||||
altitude: number,
|
||||
rotate: [number, number, number],
|
||||
scale: [number, number, number],
|
||||
origin: IMercator,
|
||||
): number[];
|
||||
lngLatToCoord?(lnglat: [number, number]): [number, number];
|
||||
lngLatToCoords?(
|
||||
lnglatArray: number[][][] | number[][],
|
||||
): number[][][] | number[][] | number[][][] | number[][];
|
||||
// lngLatToCoords?(lnglatArray: any): any;
|
||||
getCustomCoordCenter?(): [number, number];
|
||||
exportMap(type: 'jpg' | 'png'): string;
|
||||
|
||||
// 地球模式下的地图方法/属性
|
||||
rotateY?(
|
||||
option:
|
||||
| {
|
||||
force?: boolean;
|
||||
reg?: number;
|
||||
}
|
||||
| undefined,
|
||||
): void;
|
||||
}
|
||||
|
||||
export const MapServiceEvent = ['mapload', 'mapchange'];
|
||||
|
||||
/**
|
||||
* 地图初始化配置项
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
varying vec4 v_PickingResult;
|
||||
uniform vec4 u_HighlightColor : [0, 0, 0, 0];
|
||||
uniform float u_PickingStage : 0.0;
|
||||
uniform float u_Dragging;
|
||||
|
||||
#define PICKING_NONE 0.0
|
||||
#define PICKING_ENCODE 1.0
|
||||
|
@ -42,5 +43,7 @@ vec4 filterPickingColor(vec4 color) {
|
|||
* highlight color if this item is selected, otherwise unmodified argument.
|
||||
*/
|
||||
vec4 filterColor(vec4 color) {
|
||||
// TODO: 过滤多余的 shader 计算
|
||||
if(u_Dragging > 0.0) return color;
|
||||
return filterPickingColor(filterHighlightColor(color));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "A Large-scale WebGL-powered Geospatial Data Visualization",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -25,12 +25,12 @@
|
|||
"author": "antv",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@antv/l7-component": "^2.5.30",
|
||||
"@antv/l7-core": "^2.5.30",
|
||||
"@antv/l7-layers": "^2.5.30",
|
||||
"@antv/l7-maps": "^2.5.30",
|
||||
"@antv/l7-scene": "^2.5.30",
|
||||
"@antv/l7-utils": "^2.5.30",
|
||||
"@antv/l7-component": "^2.5.41",
|
||||
"@antv/l7-core": "^2.5.41",
|
||||
"@antv/l7-layers": "^2.5.41",
|
||||
"@antv/l7-maps": "^2.5.41",
|
||||
"@antv/l7-scene": "^2.5.41",
|
||||
"@antv/l7-utils": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7"
|
||||
},
|
||||
"gitHead": "684ba4eb806a798713496d3fc0b4d1e17517dc31",
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
const version = '2.5.30';
|
||||
const version = '2.5.41';
|
||||
export { version };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-layers",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "L7's collection of built-in layers",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -23,10 +23,12 @@
|
|||
"author": "xiaoiver",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/geo-coord": "^1.0.8",
|
||||
"@antv/async-hook": "^2.1.0",
|
||||
"@antv/l7-core": "^2.5.30",
|
||||
"@antv/l7-source": "^2.5.30",
|
||||
"@antv/l7-utils": "^2.5.30",
|
||||
"@antv/geo-coord": "^1.0.8",
|
||||
"@antv/l7-core": "^2.5.41",
|
||||
"@antv/l7-source": "^2.5.41",
|
||||
"@antv/l7-utils": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@mapbox/martini": "^0.2.0",
|
||||
"@turf/meta": "^6.0.2",
|
||||
|
|
|
@ -113,6 +113,11 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
|
||||
public layerModel: ILayerModel;
|
||||
|
||||
// TODO: 记录 sceneContainer 供创建子图层的时候使用 如 imageTileLayer
|
||||
public sceneContainer: Container | undefined;
|
||||
// TODO: 用于保存子图层对象
|
||||
public layerChildren: ILayer[] = [];
|
||||
|
||||
@lazyInject(TYPES.IGlobalConfigService)
|
||||
protected readonly configService: IGlobalConfigService;
|
||||
|
||||
|
@ -222,8 +227,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
* -> SceneContainer 1.*
|
||||
* -> LayerContainer 1.*
|
||||
*/
|
||||
public setContainer(container: Container) {
|
||||
public setContainer(container: Container, sceneContainer: Container) {
|
||||
this.container = container;
|
||||
this.sceneContainer = sceneContainer;
|
||||
}
|
||||
|
||||
public getContainer() {
|
||||
|
|
|
@ -5,6 +5,7 @@ import earcut from 'earcut';
|
|||
import { mat4, vec3 } from 'gl-matrix';
|
||||
import {
|
||||
EARTH_RADIUS,
|
||||
EARTH_RADIUS_OUTER,
|
||||
EARTH_SEGMENTS,
|
||||
lglt2xyz,
|
||||
primitiveSphere,
|
||||
|
@ -415,3 +416,16 @@ export function earthTriangulation() {
|
|||
normals: normalArr,
|
||||
};
|
||||
}
|
||||
|
||||
export function earthOuterTriangulation() {
|
||||
const earthmesh = primitiveSphere(EARTH_RADIUS + EARTH_RADIUS_OUTER, {
|
||||
segments: EARTH_SEGMENTS,
|
||||
});
|
||||
const { positionsArr, indicesArr, normalArr } = earthmesh;
|
||||
return {
|
||||
vertices: positionsArr,
|
||||
indices: indicesArr,
|
||||
size: 5,
|
||||
normals: normalArr,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,20 +1,28 @@
|
|||
import BaseLayer from '../core/BaseLayer';
|
||||
import EarthAtomSphereModel from './models/atmosphere';
|
||||
import BaseEarthModel from './models/base';
|
||||
import EarthBloomSphereModel from './models/bloomsphere';
|
||||
|
||||
export type EarthType = 'base';
|
||||
interface IEarthLayerStyleOptions {
|
||||
opacity: number;
|
||||
setEarthTime(time: number): void;
|
||||
}
|
||||
|
||||
const EarthModels: { [key in EarthType]: any } = {
|
||||
export type EarthModelType = 'base' | 'atomSphere' | 'bloomSphere';
|
||||
|
||||
const EarthModels: { [key in EarthModelType]: any } = {
|
||||
base: BaseEarthModel,
|
||||
atomSphere: EarthAtomSphereModel,
|
||||
bloomSphere: EarthBloomSphereModel,
|
||||
};
|
||||
|
||||
const earthLayerTypes = ['base', 'atomSphere', 'bloomSphere'];
|
||||
|
||||
export default class EarthLayer extends BaseLayer<IEarthLayerStyleOptions> {
|
||||
public type: string = 'EarthLayer';
|
||||
|
||||
public buildModels() {
|
||||
const shape = 'base';
|
||||
const shape = this.getModelType();
|
||||
this.layerModel = new EarthModels[shape](this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
|
@ -30,4 +38,15 @@ export default class EarthLayer extends BaseLayer<IEarthLayerStyleOptions> {
|
|||
console.error('请在 scene loaded 之后执行该方法!');
|
||||
}
|
||||
}
|
||||
|
||||
protected getModelType(): EarthModelType {
|
||||
const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute(
|
||||
'shape',
|
||||
);
|
||||
let shape = (shapeAttribute?.scale?.field || 'base') as string;
|
||||
if (earthLayerTypes.indexOf(shape) < 0) {
|
||||
shape = 'base';
|
||||
}
|
||||
return shape as EarthModelType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
IModel,
|
||||
IModelUniform,
|
||||
} from '@antv/l7-core';
|
||||
import { isNumber } from 'lodash';
|
||||
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { earthTriangulation } from '../../core/triangulation';
|
||||
import atmoSphereFrag from '../shaders/atmosphere_frag.glsl';
|
||||
import atmoSphereVert from '../shaders/atmosphere_vert.glsl';
|
||||
interface IAtmoLayerStyleOptions {
|
||||
opacity: number;
|
||||
}
|
||||
|
||||
export default class EarthAtomSphereModel extends BaseModel {
|
||||
public getUninforms(): IModelUniform {
|
||||
const {
|
||||
opacity = 1,
|
||||
} = this.layer.getLayerConfig() as IAtmoLayerStyleOptions;
|
||||
return {
|
||||
u_opacity: isNumber(opacity) ? opacity : 1.0,
|
||||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public clearModels() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
// TODO: 调整图层的绘制顺序 地球大气层
|
||||
this.layer.zIndex = -997;
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'earthAtmoSphere',
|
||||
vertexShader: atmoSphereVert,
|
||||
fragmentShader: atmoSphereFrag,
|
||||
triangulation: earthTriangulation,
|
||||
depth: {
|
||||
enable: false,
|
||||
},
|
||||
blend: this.getBlend(),
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
protected registerBuiltinAttributes() {
|
||||
// point layer size;
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'size',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Size',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 1,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
const { size = 1 } = feature;
|
||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'normal',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Normal',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.STATIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 3,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
normal: number[],
|
||||
) => {
|
||||
return normal;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'uv',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Uv',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 2,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
return [vertex[3], vertex[4]];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -91,6 +91,8 @@ export default class BaseEarthModel extends BaseModel {
|
|||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
// TODO: 调整图层的绘制顺序 地球大气层
|
||||
this.layer.zIndex = -998;
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'baseEarth',
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
IModel,
|
||||
IModelUniform,
|
||||
} from '@antv/l7-core';
|
||||
import { isNumber } from 'lodash';
|
||||
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { earthOuterTriangulation } from '../../core/triangulation';
|
||||
import bloomSphereFrag from '../shaders/bloomsphere_frag.glsl';
|
||||
import bloomSphereVert from '../shaders/bloomsphere_vert.glsl';
|
||||
interface IBloomLayerStyleOptions {
|
||||
opacity: number;
|
||||
}
|
||||
|
||||
export default class EarthBloomSphereModel extends BaseModel {
|
||||
public getUninforms(): IModelUniform {
|
||||
const {
|
||||
opacity = 1,
|
||||
} = this.layer.getLayerConfig() as IBloomLayerStyleOptions;
|
||||
return {
|
||||
u_opacity: isNumber(opacity) ? opacity : 1.0,
|
||||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public clearModels() {
|
||||
return '';
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
// TODO: 调整图层的绘制顺序,让它保持在地球后面(减少锯齿现象)
|
||||
this.layer.zIndex = -999;
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'earthBloomSphere',
|
||||
vertexShader: bloomSphereVert,
|
||||
fragmentShader: bloomSphereFrag,
|
||||
triangulation: earthOuterTriangulation,
|
||||
depth: {
|
||||
enable: false,
|
||||
},
|
||||
blend: this.getBlend(),
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
protected registerBuiltinAttributes() {
|
||||
// point layer size;
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'size',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Size',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 1,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
const { size = 1 } = feature;
|
||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'normal',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Normal',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.STATIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 3,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
normal: number[],
|
||||
) => {
|
||||
return normal;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'uv',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Uv',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 2,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
return [vertex[3], vertex[4]];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
uniform float u_opacity;
|
||||
uniform vec3 u_CameraPosition;
|
||||
|
||||
varying vec3 vVertexNormal;
|
||||
varying float v_offset;
|
||||
varying vec4 v_Color;
|
||||
void main() {
|
||||
|
||||
|
||||
// float intensity = pow(0.5 + dot(normalize(vVertexNormal), normalize(u_CameraPosition)), 3.0);
|
||||
float intensity = pow(v_offset + dot(normalize(vVertexNormal), normalize(u_CameraPosition)), 3.0);
|
||||
// TODO: 去除背面
|
||||
if(intensity > 1.0) intensity = 0.0;
|
||||
|
||||
gl_FragColor = vec4(v_Color.rgb, v_Color.a * intensity * u_opacity);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
attribute vec3 a_Position;
|
||||
attribute vec3 a_Normal;
|
||||
attribute vec2 a_Uv;
|
||||
attribute vec4 a_Color;
|
||||
uniform vec3 u_CameraPosition;
|
||||
varying float v_CamreaDistance;
|
||||
|
||||
uniform mat4 u_ViewProjectionMatrix;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_ViewMatrix;
|
||||
|
||||
varying vec3 vVertexNormal;
|
||||
varying vec4 v_Color;
|
||||
varying float v_offset;
|
||||
|
||||
void main() {
|
||||
float EARTH_RADIUS = 100.0;
|
||||
|
||||
v_Color = a_Color;
|
||||
|
||||
v_offset = min(((length(u_CameraPosition) - EARTH_RADIUS)/600.0) * 0.5 + 0.4, 1.0);
|
||||
vVertexNormal = a_Normal;
|
||||
|
||||
gl_Position = u_ViewProjectionMatrix * u_ModelMatrix * vec4(a_Position, 1.0);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
uniform float u_opacity;
|
||||
uniform vec3 u_CameraPosition;
|
||||
varying vec3 vVertexNormal;
|
||||
|
||||
varying vec4 v_Color;
|
||||
void main() {
|
||||
|
||||
|
||||
float intensity = - dot(normalize(vVertexNormal), normalize(u_CameraPosition));
|
||||
// TODO: 去除背面
|
||||
if(intensity > 1.0) intensity = 0.0;
|
||||
|
||||
gl_FragColor = vec4(v_Color.rgb, v_Color.a * intensity * u_opacity);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
attribute vec3 a_Position;
|
||||
attribute vec3 a_Normal;
|
||||
attribute vec2 a_Uv;
|
||||
attribute vec4 a_Color;
|
||||
uniform vec3 u_CameraPosition;
|
||||
uniform mat4 u_ViewProjectionMatrix;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_ViewMatrix;
|
||||
|
||||
varying vec3 vVertexNormal;
|
||||
varying vec4 v_Color;
|
||||
|
||||
void main() {
|
||||
v_Color = a_Color;
|
||||
|
||||
vVertexNormal = a_Normal;
|
||||
|
||||
gl_Position = u_ViewProjectionMatrix * u_ModelMatrix * vec4(a_Position, 1.0);
|
||||
}
|
|
@ -5,6 +5,8 @@ import { mat4, vec3 } from 'gl-matrix';
|
|||
export const EARTH_RADIUS = 100;
|
||||
export const EARTH_SEGMENTS = 36;
|
||||
|
||||
export const EARTH_RADIUS_OUTER = 40;
|
||||
|
||||
/**
|
||||
* 角度转弧度
|
||||
* @param deg
|
||||
|
@ -61,7 +63,6 @@ export function primitiveSphere(
|
|||
const indicesArr = [];
|
||||
const positions = [];
|
||||
const positionsArr = [];
|
||||
const normals = [];
|
||||
const normalArr = [];
|
||||
const uvs = [];
|
||||
|
||||
|
@ -96,7 +97,6 @@ export function primitiveSphere(
|
|||
positionsArr.push(...tmpVec3.slice());
|
||||
|
||||
vec3.normalize(tmpVec3, tmpVec3);
|
||||
normals.push(tmpVec3.slice());
|
||||
normalArr.push(...tmpVec3.slice());
|
||||
|
||||
uvs.push([normalizedY, 1 - normalizedZ]);
|
||||
|
@ -141,7 +141,6 @@ export function primitiveSphere(
|
|||
return {
|
||||
cells: indices,
|
||||
positions,
|
||||
normals,
|
||||
uvs,
|
||||
positionsArr,
|
||||
indicesArr,
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
import BaseLayer from '../core/BaseLayer';
|
||||
import ImageTileModels, { ImageTileModelType } from './models/index';
|
||||
interface IImageLayerStyleOptions {
|
||||
opacity: number;
|
||||
}
|
||||
export default class ImageTileLayer extends BaseLayer<IImageLayerStyleOptions> {
|
||||
public type: string = 'ImageTileLayer';
|
||||
public buildModels() {
|
||||
const modelType = this.getModelType();
|
||||
this.layerModel = new ImageTileModels[modelType](this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
this.models = this.layerModel.buildModels();
|
||||
}
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
opacity: {
|
||||
type: 'number',
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
protected getDefaultConfig() {
|
||||
const type = this.getModelType();
|
||||
const defaultConfig = {
|
||||
imageTile: {},
|
||||
};
|
||||
return defaultConfig[type];
|
||||
}
|
||||
|
||||
protected getModelType(): ImageTileModelType {
|
||||
return 'imageTile';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
ILayer,
|
||||
ILayerPlugin,
|
||||
IModel,
|
||||
IModelUniform,
|
||||
IRasterParserDataItem,
|
||||
IStyleAttributeService,
|
||||
ITexture2D,
|
||||
lazyInject,
|
||||
TYPES,
|
||||
} from '@antv/l7-core';
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { RasterImageTriangulation } from '../../core/triangulation';
|
||||
import ImageTileFrag from './shaders/imagetile_frag.glsl';
|
||||
import ImageTileVert from './shaders/imagetile_vert.glsl';
|
||||
|
||||
import Tile from '../utils/Tile';
|
||||
|
||||
interface IImageLayerStyleOptions {
|
||||
resolution: string;
|
||||
maxSourceZoom: number;
|
||||
}
|
||||
|
||||
export default class ImageTileModel extends BaseModel {
|
||||
public tileLayer: any;
|
||||
public getUninforms(): IModelUniform {
|
||||
return {};
|
||||
}
|
||||
|
||||
// 临时的瓦片测试方法
|
||||
public tile() {
|
||||
const [WS, EN] = this.mapService.getBounds();
|
||||
const NE = { lng: EN[0], lat: EN[1] };
|
||||
const SW = { lng: WS[0], lat: WS[1] };
|
||||
this.tileLayer.calCurrentTiles({
|
||||
NE,
|
||||
SW,
|
||||
tileCenter: this.mapService.getCenter(),
|
||||
currentZoom: this.mapService.getZoom(),
|
||||
minSourceZoom: this.mapService.getMinZoom(),
|
||||
minZoom: this.mapService.getMinZoom(),
|
||||
maxZoom: this.mapService.getMaxZoom(),
|
||||
});
|
||||
}
|
||||
|
||||
public initModels() {
|
||||
// TODO: 瓦片组件默认在最下层
|
||||
this.layer.zIndex = -999;
|
||||
const {
|
||||
resolution = 'low',
|
||||
maxSourceZoom = 17,
|
||||
} = this.layer.getLayerConfig() as IImageLayerStyleOptions;
|
||||
const source = this.layer.getSource();
|
||||
// 当存在 url 的时候生效
|
||||
if (source.data.tileurl) {
|
||||
this.tileLayer = new Tile({
|
||||
url: source.data.tileurl,
|
||||
layerService: this.layerService,
|
||||
layer: this.layer,
|
||||
resolution,
|
||||
maxSourceZoom,
|
||||
// Tip: 当前为 default
|
||||
crstype: 'epsg3857',
|
||||
});
|
||||
|
||||
this.tile();
|
||||
let t = new Date().getTime();
|
||||
this.mapService.on('mapchange', () => {
|
||||
const newT = new Date().getTime();
|
||||
const cutT = newT - t;
|
||||
t = newT;
|
||||
if (cutT < 16) {
|
||||
return;
|
||||
}
|
||||
this.tile();
|
||||
});
|
||||
}
|
||||
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'ImageTileLayer',
|
||||
vertexShader: ImageTileVert,
|
||||
fragmentShader: ImageTileFrag,
|
||||
triangulation: RasterImageTriangulation,
|
||||
primitive: gl.TRIANGLES,
|
||||
depth: { enable: false },
|
||||
blend: this.getBlend(),
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public clearModels() {
|
||||
this.tileLayer.removeTiles();
|
||||
}
|
||||
|
||||
public buildModels() {
|
||||
return this.initModels();
|
||||
}
|
||||
|
||||
protected registerBuiltinAttributes() {
|
||||
// point layer size;
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'uv',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Uv',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 2,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
return [vertex[3], vertex[4]];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import ImageTileModel from './imagetile';
|
||||
export type ImageTileModelType = 'imageTile';
|
||||
|
||||
const ImageTileModels: { [key in ImageTileModelType]: any } = {
|
||||
imageTile: ImageTileModel,
|
||||
};
|
||||
|
||||
export default ImageTileModels;
|
|
@ -0,0 +1,4 @@
|
|||
precision mediump float;
|
||||
void main() {
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
precision highp float;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_Mvp;
|
||||
attribute vec3 a_Position;
|
||||
#pragma include "projection"
|
||||
void main() {
|
||||
vec4 project_pos = project_position(vec4(a_Position, 1.0));
|
||||
// gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy,0., 1.0));
|
||||
if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x
|
||||
gl_Position = u_Mvp * (vec4(project_pos.xy,0., 1.0));
|
||||
} else {
|
||||
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy,0., 1.0));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
precision mediump float;
|
||||
uniform float u_opacity: 1.0;
|
||||
uniform sampler2D u_texture;
|
||||
varying vec2 v_texCoord;
|
||||
void main() {
|
||||
vec4 color = texture2D(u_texture,vec2(v_texCoord.x,v_texCoord.y));
|
||||
gl_FragColor = color;
|
||||
gl_FragColor.a *= u_opacity;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
precision highp float;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_Mvp;
|
||||
attribute vec3 a_Position;
|
||||
attribute vec2 a_Uv;
|
||||
varying vec2 v_texCoord;
|
||||
#pragma include "projection"
|
||||
void main() {
|
||||
v_texCoord = a_Uv;
|
||||
vec4 project_pos = project_position(vec4(a_Position, 1.0));
|
||||
// gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy,0., 1.0));
|
||||
if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x
|
||||
gl_Position = u_Mvp * (vec4(project_pos.xy,0., 1.0));
|
||||
} else {
|
||||
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy,0., 1.0));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
import { LngLatBounds, toBounds, toLngLatBounds } from '@antv/geo-coord';
|
||||
import { Container } from 'inversify';
|
||||
import ImageLayer from '../../image';
|
||||
|
||||
interface IUrlParams {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
s?: string;
|
||||
}
|
||||
|
||||
const r2d = 180 / Math.PI;
|
||||
const tileURLRegex = /\{([zxy])\}/g;
|
||||
|
||||
export default class ImageTile {
|
||||
public tile: number[]; // 当前图片瓦片的索引
|
||||
public name: string;
|
||||
public imageLayer: any;
|
||||
constructor(
|
||||
key: string,
|
||||
url: string,
|
||||
container: Container,
|
||||
sceneContainer: Container,
|
||||
) {
|
||||
this.name = key;
|
||||
this.tile = key.split('_').map((v) => Number(v));
|
||||
|
||||
const urlParams = {
|
||||
x: this.tile[0],
|
||||
y: this.tile[1],
|
||||
z: this.tile[2],
|
||||
};
|
||||
const imageSrc = this.getTileURL(urlParams, url);
|
||||
|
||||
const lnglatBounds = this.tileLnglatBounds(this.tile);
|
||||
const west = lnglatBounds.getWest();
|
||||
const south = lnglatBounds.getSouth();
|
||||
const east = lnglatBounds.getEast();
|
||||
const north = lnglatBounds.getNorth();
|
||||
|
||||
const imageLayer = new ImageLayer({});
|
||||
imageLayer.source(
|
||||
// 'https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg',
|
||||
imageSrc,
|
||||
{
|
||||
parser: {
|
||||
type: 'image',
|
||||
// extent: [121.168, 30.2828, 121.384, 30.4219],
|
||||
extent: [west, south, east, north],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
imageLayer.setContainer(container, sceneContainer);
|
||||
imageLayer.init();
|
||||
|
||||
this.imageLayer = imageLayer;
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.imageLayer.clearModels();
|
||||
this.imageLayer.destroy();
|
||||
}
|
||||
|
||||
public getTileURL(urlParams: IUrlParams, path: string) {
|
||||
if (!urlParams.s) {
|
||||
// Default to a random choice of a, b or c
|
||||
urlParams.s = String.fromCharCode(97 + Math.floor(Math.random() * 3));
|
||||
}
|
||||
|
||||
tileURLRegex.lastIndex = 0;
|
||||
return path.replace(tileURLRegex, (value, key: any) => {
|
||||
// @ts-ignore
|
||||
return urlParams[key];
|
||||
});
|
||||
}
|
||||
|
||||
// Get tile bounds in WGS84 coordinates
|
||||
public tileLnglatBounds(tile: number[]) {
|
||||
const e = this.tile2lng(tile[0] + 1, tile[2]);
|
||||
const w = this.tile2lng(tile[0], tile[2]);
|
||||
const s = this.tile2lat(tile[1] + 1, tile[2]);
|
||||
const n = this.tile2lat(tile[1], tile[2]);
|
||||
return toLngLatBounds([w, n], [e, s]);
|
||||
}
|
||||
|
||||
public tile2lng(x: number, z: number) {
|
||||
return (x / Math.pow(2, z)) * 360 - 180;
|
||||
}
|
||||
|
||||
public tile2lat(y: number, z: number) {
|
||||
const n = Math.PI - (2 * Math.PI * y) / Math.pow(2, z);
|
||||
return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,359 @@
|
|||
import { Bounds, GeoCoordinates, Point, toLngLat } from '@antv/geo-coord';
|
||||
import {
|
||||
createLayerContainer,
|
||||
ILayer,
|
||||
ILayerService,
|
||||
ILngLat,
|
||||
} from '@antv/l7-core';
|
||||
import { Container } from 'inversify';
|
||||
|
||||
import ImageTile from './ImageTile';
|
||||
import TileCache from './tileCache';
|
||||
|
||||
// Tip: 瓦片地图的存储上限
|
||||
const CacheLimit = 30;
|
||||
|
||||
export default class Tile {
|
||||
public tileList: any = {};
|
||||
public tileCache: any;
|
||||
|
||||
public updateTileList: any[];
|
||||
public tileZoom: number;
|
||||
public noPruneRange: any;
|
||||
public url: string;
|
||||
public resolution: number;
|
||||
public maxSourceZoom: number;
|
||||
public crstype: string;
|
||||
public currentCrs: any;
|
||||
|
||||
public layerService: ILayerService;
|
||||
public layer: ILayer;
|
||||
constructor(props: any) {
|
||||
this.layerService = props.layerService;
|
||||
this.layer = props.layer;
|
||||
this.url = props.url;
|
||||
this.resolution = props.resolution === 'low' ? -1 : 0;
|
||||
this.maxSourceZoom = props.maxSourceZoom;
|
||||
this.crstype = props.crstype;
|
||||
|
||||
this.currentCrs = new GeoCoordinates.default({
|
||||
start: { x: 0, y: 0 },
|
||||
end: { x: 0, y: 0 },
|
||||
projection: this.crstype,
|
||||
}).crs as any;
|
||||
|
||||
this.destroyTile = this.destroyTile.bind(this);
|
||||
this.tileCache = new TileCache(CacheLimit, this.destroyTile);
|
||||
|
||||
this.updateTileList = [];
|
||||
|
||||
this.removeTiles = this.removeTiles.bind(this);
|
||||
}
|
||||
|
||||
public calCurrentTiles(oprions: any) {
|
||||
const {
|
||||
NE,
|
||||
SW,
|
||||
tileCenter,
|
||||
currentZoom,
|
||||
minSourceZoom,
|
||||
minZoom,
|
||||
maxZoom,
|
||||
} = oprions;
|
||||
// TODO: 当前瓦片的层级要比地图底图的层级低
|
||||
if (currentZoom >= this.maxSourceZoom) {
|
||||
return;
|
||||
}
|
||||
const zoom = Math.floor(currentZoom) + this.resolution;
|
||||
|
||||
this.tileZoom = zoom > this.maxSourceZoom ? this.maxSourceZoom : zoom;
|
||||
|
||||
if (
|
||||
currentZoom < minZoom ||
|
||||
currentZoom >= maxZoom ||
|
||||
currentZoom < minSourceZoom
|
||||
) {
|
||||
this.removeTiles();
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateTileList = [];
|
||||
|
||||
// 计算瓦片中心
|
||||
const centerPoint = this.currentCrs.lngLatToPoint(
|
||||
toLngLat(tileCenter.lng, tileCenter.lat),
|
||||
this.tileZoom,
|
||||
);
|
||||
const centerXY = centerPoint.divideBy(256).floor();
|
||||
|
||||
const pixelBounds = this.getPixelBounds(
|
||||
NE,
|
||||
SW,
|
||||
tileCenter,
|
||||
this.tileZoom,
|
||||
this.currentCrs,
|
||||
); // 计算像素范围
|
||||
const tileRange = this.pxBoundsToTileRange(pixelBounds); // 计算瓦片范围
|
||||
|
||||
const margin = 4;
|
||||
|
||||
this.noPruneRange = new Bounds(
|
||||
tileRange.getBottomLeft().subtract([margin, -margin]),
|
||||
tileRange.getTopRight().add([margin, -margin]),
|
||||
);
|
||||
|
||||
// T: isFinite(n: number) 用于检测 n 是否无穷大
|
||||
if (
|
||||
!(
|
||||
isFinite(tileRange.min.x) &&
|
||||
isFinite(tileRange.min.y) &&
|
||||
isFinite(tileRange.max.x) &&
|
||||
isFinite(tileRange.max.y)
|
||||
)
|
||||
) {
|
||||
throw new Error('Attempted to load an infinite number of tiles');
|
||||
}
|
||||
|
||||
// 根据视野判断新增的瓦片索引
|
||||
for (let j = tileRange.min.y; j <= tileRange.max.y; j++) {
|
||||
for (let i = tileRange.min.x; i <= tileRange.max.x; i++) {
|
||||
const coords = [i, j, this.tileZoom];
|
||||
const tile = this.tileList[coords.join('_')];
|
||||
if (tile) {
|
||||
tile.current = true;
|
||||
} else {
|
||||
this.tileList[coords.join('_')] = {
|
||||
current: true,
|
||||
coords,
|
||||
};
|
||||
this.updateTileList.push(coords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 瓦片列表排序
|
||||
this.updateTileList.sort((a: any, b: any) => {
|
||||
const tile1 = a;
|
||||
const tile2 = b;
|
||||
const d1 =
|
||||
Math.pow(tile1[0] * 1 - centerXY.x, 2) +
|
||||
Math.pow(tile1[1] * 1 - centerXY.y, 2);
|
||||
const d2 =
|
||||
Math.pow(tile2[0] * 1 - centerXY.x, 2) +
|
||||
Math.pow(tile2[1] * 1 - centerXY.y, 2);
|
||||
return d1 - d2;
|
||||
});
|
||||
|
||||
this.pruneTiles();
|
||||
this.updateTileList.forEach((coords: any) => {
|
||||
const key = coords.join('_');
|
||||
if (this.tileList[key].current) {
|
||||
this.requestTile(key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public pxBoundsToTileRange(pixelBounds: any) {
|
||||
return new Bounds(
|
||||
pixelBounds.min.divideBy(256).floor(),
|
||||
pixelBounds.max
|
||||
.divideBy(256)
|
||||
.ceil()
|
||||
.subtract([1, 1]),
|
||||
);
|
||||
}
|
||||
|
||||
public getPixelBounds(
|
||||
NE: ILngLat,
|
||||
SW: ILngLat,
|
||||
tileCenter: ILngLat,
|
||||
tileZoom: number,
|
||||
crs: any,
|
||||
) {
|
||||
const zoom = tileZoom;
|
||||
const NEPoint = crs.lngLatToPoint(toLngLat(NE.lng, NE.lat), zoom);
|
||||
const SWPoint = crs.lngLatToPoint(toLngLat(SW.lng, SW.lat), zoom);
|
||||
const centerPoint = crs.lngLatToPoint(
|
||||
toLngLat(tileCenter.lng, tileCenter.lat),
|
||||
zoom,
|
||||
);
|
||||
const topHeight = centerPoint.y - NEPoint.y;
|
||||
const bottomHeight = SWPoint.y - centerPoint.y;
|
||||
// 跨日界线的情况
|
||||
let leftWidth;
|
||||
let rightWidth;
|
||||
if (tileCenter.lng - NE.lng > 0 || tileCenter.lng - SW.lng < 0) {
|
||||
const width =
|
||||
((Math.pow(2, zoom) * 256) / 360) * (180 - NE.lng) +
|
||||
((Math.pow(2, zoom) * 256) / 360) * (SW.lng + 180);
|
||||
if (tileCenter.lng - NE.lng > 0) {
|
||||
// 日界线在右侧
|
||||
leftWidth =
|
||||
((Math.pow(2, zoom) * 256) / 360) * (tileCenter.lng - NE.lng);
|
||||
rightWidth = width - leftWidth;
|
||||
} else {
|
||||
rightWidth =
|
||||
((Math.pow(2, zoom) * 256) / 360) * (SW.lng - tileCenter.lng);
|
||||
leftWidth = width - rightWidth;
|
||||
}
|
||||
} else {
|
||||
// 不跨日界线
|
||||
leftWidth = ((Math.pow(2, zoom) * 256) / 360) * (tileCenter.lng - SW.lng);
|
||||
rightWidth =
|
||||
((Math.pow(2, zoom) * 256) / 360) * (NE.lng - tileCenter.lng);
|
||||
}
|
||||
const pixelBounds = new Bounds(
|
||||
centerPoint.subtract(leftWidth, topHeight),
|
||||
centerPoint.add(rightWidth, bottomHeight),
|
||||
);
|
||||
return pixelBounds;
|
||||
}
|
||||
|
||||
public pruneTiles() {
|
||||
Object.keys(this.tileList).map((key) => {
|
||||
const c = this.tileList[key].coords;
|
||||
// 如果不是同一个缩放层级,则将瓦片设为不显示
|
||||
if (
|
||||
c[2] !== this.tileZoom ||
|
||||
!this.noPruneRange.contains(new Point(c[0], c[1]))
|
||||
) {
|
||||
this.tileList[key].current = false;
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(this.tileList).map((key) => {
|
||||
const tile = this.tileList[key];
|
||||
tile.retain = tile.current;
|
||||
});
|
||||
|
||||
Object.keys(this.tileList).map((key) => {
|
||||
const tile = this.tileList[key];
|
||||
if (tile.current && !tile.active) {
|
||||
const [x, y, z] = key.split('_').map((v) => Number(v));
|
||||
|
||||
if (!this.retainParent(x, y, z, z - 5)) {
|
||||
this.retainChildren(x, y, z, z + 2);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.removeOutTiles();
|
||||
}
|
||||
|
||||
public requestTile(key: string) {
|
||||
const t = this.tileList[key];
|
||||
if (!t) {
|
||||
return;
|
||||
}
|
||||
let tile = this.tileCache.getTile(key);
|
||||
if (!tile) {
|
||||
const container = createLayerContainer(
|
||||
this.layer.sceneContainer as Container,
|
||||
);
|
||||
tile = new ImageTile(
|
||||
key,
|
||||
this.url,
|
||||
container,
|
||||
this.layer.sceneContainer as Container,
|
||||
);
|
||||
tile.name = key;
|
||||
|
||||
t.current = true;
|
||||
t.retain = true;
|
||||
t.active = true;
|
||||
|
||||
// 往 imageTileLayer 中添加子图层
|
||||
this.layer.layerChildren.push(tile.imageLayer);
|
||||
|
||||
this.tileCache.setTile(tile, key);
|
||||
|
||||
this.pruneTiles();
|
||||
this.layerService.renderLayers();
|
||||
} else {
|
||||
// Tip: show 方法就是将相应的瓦片图片添加到渲染队列
|
||||
tile.imageLayer.show();
|
||||
t.current = true;
|
||||
t.retain = true;
|
||||
t.active = true;
|
||||
|
||||
this.pruneTiles();
|
||||
}
|
||||
}
|
||||
|
||||
public retainParent(x: number, y: number, z: number, minZoom: number): any {
|
||||
const x2 = Math.floor(x / 2);
|
||||
const y2 = Math.floor(y / 2);
|
||||
const z2 = z - 1;
|
||||
const tile = this.tileList[[x2, y2, z2].join('_')];
|
||||
if (tile && tile.active) {
|
||||
tile.retain = true;
|
||||
return true;
|
||||
} else if (tile && tile.loaded) {
|
||||
tile.retain = true;
|
||||
}
|
||||
if (z2 > minZoom) {
|
||||
return this.retainParent(x2, y2, z2, minZoom);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public retainChildren(x: number, y: number, z: number, maxZoom: number) {
|
||||
for (let i = 2 * x; i < 2 * x + 2; i++) {
|
||||
for (let j = 2 * y; j < 2 * y + 2; j++) {
|
||||
const key = [i, j, z + 1].join('_');
|
||||
const tile = this.tileList[key];
|
||||
if (tile && tile.active) {
|
||||
tile.retain = true;
|
||||
continue;
|
||||
} else if (tile && tile.loaded) {
|
||||
tile.retain = true;
|
||||
}
|
||||
|
||||
if (z + 1 < maxZoom) {
|
||||
this.retainChildren(i, j, z + 1, maxZoom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public destroyTile(tile: any) {
|
||||
const layerIndex = this.layer.layerChildren.indexOf(tile.imageLayer);
|
||||
if (layerIndex > -1) {
|
||||
this.layer.layerChildren.splice(layerIndex, 1);
|
||||
}
|
||||
|
||||
tile.imageLayer.emit('remove', null);
|
||||
tile.imageLayer.destroy();
|
||||
this.layerService.renderLayers();
|
||||
|
||||
// 清除 tileCache 中的存储 相当于 tileCache.setTile(tile, null)
|
||||
tile = null;
|
||||
}
|
||||
|
||||
public removeOutTiles() {
|
||||
for (const key in this.tileList) {
|
||||
if (!this.tileList[key].retain) {
|
||||
// Tip: 不需要显示的瓦片对象
|
||||
const tile = this.tileCache.getTile(key);
|
||||
// Tip: 若是网格对象存在
|
||||
if (tile) {
|
||||
// Tip: hide 方法就是将相应的瓦片图片从渲染队列中剔除
|
||||
tile.imageLayer.hide();
|
||||
}
|
||||
delete this.tileList[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public removeTiles() {
|
||||
this.layer.layerChildren.forEach((layer: any) => {
|
||||
layer.emit('remove', null);
|
||||
layer.destroy();
|
||||
});
|
||||
|
||||
this.layer.layerChildren = [];
|
||||
this.layerService.renderLayers();
|
||||
this.tileList = {};
|
||||
this.tileCache.destory();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* LRU Cache class with limit
|
||||
*
|
||||
* Update order for each get/set operation
|
||||
* Delete oldest when reach given limit
|
||||
*/
|
||||
|
||||
export default class LRUCache {
|
||||
public limit: number;
|
||||
public order: any[];
|
||||
public cache: any;
|
||||
public destroy: any;
|
||||
constructor(limit = 50, destroy = () => '') {
|
||||
this.limit = limit;
|
||||
this.destroy = destroy;
|
||||
this.order = [];
|
||||
this.clear();
|
||||
}
|
||||
|
||||
public clear() {
|
||||
this.order.forEach((key: any) => {
|
||||
this.delete(key);
|
||||
});
|
||||
this.cache = {};
|
||||
// access/update order, first item is oldest, last item is newest
|
||||
this.order = [];
|
||||
}
|
||||
|
||||
public get(key: string) {
|
||||
const value = this.cache[key];
|
||||
if (value) {
|
||||
// update order
|
||||
this.deleteOrder(key);
|
||||
this.appendOrder(key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public set(key: string, value: any) {
|
||||
if (!this.cache[key]) {
|
||||
// if reach limit, delete the oldest
|
||||
if (Object.keys(this.cache).length === this.limit) {
|
||||
this.delete(this.order[0]);
|
||||
}
|
||||
|
||||
this.cache[key] = value;
|
||||
this.appendOrder(key);
|
||||
} else {
|
||||
// if found in cache, delete the old one, insert new one to the first of list
|
||||
this.delete(key);
|
||||
|
||||
this.cache[key] = value;
|
||||
this.appendOrder(key);
|
||||
}
|
||||
}
|
||||
|
||||
public delete(key: string) {
|
||||
const value = this.cache[key];
|
||||
if (value) {
|
||||
this.deleteCache(key);
|
||||
this.deleteOrder(key);
|
||||
this.destroy(value, key);
|
||||
}
|
||||
}
|
||||
|
||||
public deleteCache(key: string) {
|
||||
delete this.cache[key];
|
||||
}
|
||||
|
||||
public deleteOrder(key: string) {
|
||||
const index = this.order.findIndex((o) => o === key);
|
||||
if (index >= 0) {
|
||||
this.order.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public appendOrder(key: string) {
|
||||
this.order.push(key);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import LRUCache from './lruCache';
|
||||
export default class TileCache {
|
||||
public cache: any;
|
||||
constructor(limit = 50, tileDestroy: any) {
|
||||
this.cache = new LRUCache(limit, tileDestroy);
|
||||
}
|
||||
|
||||
public getTile(key: string) {
|
||||
return this.cache.get(key);
|
||||
}
|
||||
|
||||
public setTile(tile: any, key: string) {
|
||||
this.cache.set(key, tile);
|
||||
}
|
||||
public destory() {
|
||||
this.cache.clear();
|
||||
}
|
||||
public setNeedUpdate() {
|
||||
this.cache.order.forEach((key: string) => {
|
||||
const tile = this.cache.get(key);
|
||||
tile.needUpdate = true;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import BaseLayer from './core/BaseLayer';
|
|||
import './glsl.d';
|
||||
import HeatmapLayer from './heatmap';
|
||||
import ImageLayer from './image';
|
||||
import ImageTileLayer from './imagetile';
|
||||
import LineLayer from './line/index';
|
||||
import PointLayer from './point';
|
||||
import PolygonLayer from './polygon';
|
||||
|
@ -25,6 +26,7 @@ import RegisterStyleAttributePlugin from './plugins/RegisterStyleAttributePlugin
|
|||
import ShaderUniformPlugin from './plugins/ShaderUniformPlugin';
|
||||
import UpdateModelPlugin from './plugins/UpdateModelPlugin';
|
||||
import UpdateStyleAttributePlugin from './plugins/UpdateStyleAttributePlugin';
|
||||
|
||||
/**
|
||||
* 校验传入参数配置项的正确性
|
||||
* @see /dev-docs/ConfigSchemaValidation.md
|
||||
|
@ -137,6 +139,7 @@ export {
|
|||
LineLayer,
|
||||
CityBuildingLayer,
|
||||
ImageLayer,
|
||||
ImageTileLayer,
|
||||
RasterLayer,
|
||||
HeatmapLayer,
|
||||
EarthLayer,
|
||||
|
|
|
@ -31,6 +31,7 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
|
|||
line: {},
|
||||
arc3d: { blend: 'additive' },
|
||||
arc: { blend: 'additive' },
|
||||
arcmini: { blend: 'additive' },
|
||||
greatcircle: { blend: 'additive' },
|
||||
};
|
||||
return defaultConfig[type];
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
import {
|
||||
AttributeType,
|
||||
gl,
|
||||
IAnimateOption,
|
||||
IEncodeFeature,
|
||||
ILayerConfig,
|
||||
IModel,
|
||||
IModelUniform,
|
||||
} from '@antv/l7-core';
|
||||
|
||||
import { rgb2arr } from '@antv/l7-utils';
|
||||
import { isNumber } from 'lodash';
|
||||
import BaseModel from '../../core/BaseModel';
|
||||
import { ILineLayerStyleOptions } from '../../core/interface';
|
||||
import { LineArcTriangulation } from '../../core/triangulation';
|
||||
import line_arcmini_frag from '../shaders/line_arcmini_frag.glsl';
|
||||
import line_arcmini_vert from '../shaders/line_arcmini_vert.glsl';
|
||||
|
||||
export default class ArcMiniModel extends BaseModel {
|
||||
public getUninforms(): IModelUniform {
|
||||
const {
|
||||
opacity,
|
||||
sourceColor,
|
||||
targetColor,
|
||||
forward = true,
|
||||
segmentNumber = 30,
|
||||
thetaOffset = 0.314,
|
||||
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
|
||||
|
||||
// 转化渐变色
|
||||
let useLinearColor = 0; // 默认不生效
|
||||
let sourceColorArr = [0, 0, 0, 0];
|
||||
let targetColorArr = [0, 0, 0, 0];
|
||||
if (sourceColor && targetColor) {
|
||||
sourceColorArr = rgb2arr(sourceColor);
|
||||
targetColorArr = rgb2arr(targetColor);
|
||||
useLinearColor = 1;
|
||||
}
|
||||
|
||||
return {
|
||||
u_thetaOffset: thetaOffset,
|
||||
|
||||
u_opacity: isNumber(opacity) ? opacity : 1.0,
|
||||
|
||||
segmentNumber,
|
||||
u_blur: 0.9,
|
||||
u_lineDir: forward ? 1 : -1,
|
||||
|
||||
// 渐变色支持参数
|
||||
u_linearColor: useLinearColor,
|
||||
u_sourceColor: sourceColorArr,
|
||||
u_targetColor: targetColorArr,
|
||||
};
|
||||
}
|
||||
|
||||
public getAnimateUniforms(): IModelUniform {
|
||||
const { animateOption } = this.layer.getLayerConfig() as ILayerConfig;
|
||||
return {
|
||||
u_aimate: this.animateOption2Array(animateOption as IAnimateOption),
|
||||
u_time: this.layer.getLayerAnimateTime(),
|
||||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
const {
|
||||
segmentNumber = 30,
|
||||
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
|
||||
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'arc2dminiline',
|
||||
vertexShader: line_arcmini_vert,
|
||||
fragmentShader: line_arcmini_frag,
|
||||
triangulation: LineArcTriangulation,
|
||||
depth: { enable: false },
|
||||
blend: this.getBlend(),
|
||||
segmentNumber,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
protected registerBuiltinAttributes() {
|
||||
// point layer size;
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'size',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Size',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 1,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
const { size = 1 } = feature;
|
||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'instance', // 弧线起始点信息
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Instance',
|
||||
buffer: {
|
||||
usage: gl.STATIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 4,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
return [vertex[3], vertex[4], vertex[5], vertex[6]];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,12 +1,19 @@
|
|||
import ArcModel from './arc';
|
||||
import Arc3DModel from './arc_3d';
|
||||
import ArcMiniModel from './arcmini';
|
||||
import GreatCircleModel from './great_circle';
|
||||
import LineModel from './line';
|
||||
|
||||
export type LineModelType = 'arc' | 'arc3d' | 'greatcircle' | 'line';
|
||||
export type LineModelType =
|
||||
| 'arc'
|
||||
| 'arcmini'
|
||||
| 'arc3d'
|
||||
| 'greatcircle'
|
||||
| 'line';
|
||||
|
||||
const LineModels: { [key in LineModelType]: any } = {
|
||||
arc: ArcModel,
|
||||
arcmini: ArcMiniModel,
|
||||
arc3d: Arc3DModel,
|
||||
greatcircle: GreatCircleModel,
|
||||
line: LineModel,
|
||||
|
|
|
@ -17,8 +17,6 @@ uniform vec2 u_textSize;
|
|||
varying float v_segmentIndex;
|
||||
uniform float segmentNumber;
|
||||
|
||||
varying vec4 v_dataset; // 数据集
|
||||
|
||||
varying vec2 v_iconMapUV;
|
||||
|
||||
uniform float u_time;
|
||||
|
@ -35,7 +33,7 @@ varying mat4 styleMappingMat;
|
|||
void main() {
|
||||
float opacity = styleMappingMat[0][0];
|
||||
float animateSpeed = 0.0; // 运动速度
|
||||
float d_distance_ratio = v_dataset.g; // 当前点位距离占线总长的比例
|
||||
float d_distance_ratio = styleMappingMat[3].g; // 当前点位距离占线总长的比例
|
||||
|
||||
if(u_linearColor == 1.0) { // 使用渐变颜色
|
||||
gl_FragColor = mix(u_sourceColor, u_targetColor, v_segmentIndex/segmentNumber);
|
||||
|
@ -68,7 +66,7 @@ void main() {
|
|||
if(u_line_texture == LineTexture && u_line_type != LineTypeDash) { // while load texture
|
||||
// float arcRadio = smoothstep( 0.0, 1.0, (v_segmentIndex / segmentNumber));
|
||||
float arcRadio = v_segmentIndex / (segmentNumber - 1.0);
|
||||
float count = v_dataset.b; // // 贴图在弧线上重复的数量
|
||||
float count = styleMappingMat[3].b; // // 贴图在弧线上重复的数量
|
||||
|
||||
float u = fract(arcRadio * count - animateSpeed * count);
|
||||
|
||||
|
@ -76,7 +74,7 @@ void main() {
|
|||
u = gl_FragColor.a/opacity;
|
||||
}
|
||||
|
||||
float v = v_dataset.a; // 线图层贴图部分的 v 坐标值
|
||||
float v = styleMappingMat[3].a; // 线图层贴图部分的 v 坐标值
|
||||
vec2 uv= v_iconMapUV / u_textSize + vec2(u, v) / u_textSize * 64.;
|
||||
vec4 pattern = texture2D(u_texture, uv);
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@ uniform float u_icon_step: 100;
|
|||
uniform float u_line_texture: 0.0;
|
||||
varying float v_segmentIndex;
|
||||
|
||||
varying vec4 v_dataset; // 数据集
|
||||
|
||||
attribute vec2 a_iconMapUV;
|
||||
varying vec2 v_iconMapUV;
|
||||
|
||||
|
@ -106,7 +104,7 @@ void main() {
|
|||
0.0, 0.0, 0.0, 0.0, // opacity - strokeOpacity - strokeWidth - empty
|
||||
0.0, 0.0, 0.0, 0.0, // strokeR - strokeG - strokeB - strokeA
|
||||
0.0, 0.0, 0.0, 0.0, // offsets[0] - offsets[1]
|
||||
0.0, 0.0, 0.0, 0.0
|
||||
0.0, 0.0, 0.0, 0.0 // dataset 数据集
|
||||
);
|
||||
|
||||
float rowCount = u_cellTypeLayout[0][0]; // 当前的数据纹理有几行
|
||||
|
@ -151,7 +149,7 @@ void main() {
|
|||
if(u_aimate.x == Animate) {
|
||||
d_distance_ratio = segmentIndex / segmentNumber;
|
||||
}
|
||||
v_dataset.g = d_distance_ratio; // 当前点位距离占线总长的比例
|
||||
styleMappingMat[3].g = d_distance_ratio; // 当前点位距离占线总长的比例
|
||||
|
||||
float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir);
|
||||
vec3 curr = getPos(source, target, segmentRatio);
|
||||
|
@ -165,12 +163,12 @@ void main() {
|
|||
|
||||
float arcDistrance = length(source - target);
|
||||
float pixelLen = project_pixel(u_icon_step);
|
||||
v_dataset.b = floor(arcDistrance/pixelLen); // 贴图在弧线上重复的数量
|
||||
styleMappingMat[3].b = floor(arcDistrance/pixelLen); // 贴图在弧线上重复的数量
|
||||
|
||||
vec2 projectOffset = project_pixel(offset);
|
||||
float lineOffsetWidth = length(projectOffset + projectOffset * sign(a_Position.y)); // 线横向偏移的距离
|
||||
float linePixelSize = project_pixel(a_Size); // 定点位置偏移,按地图等级缩放后的距离
|
||||
v_dataset.a = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
|
||||
styleMappingMat[3].a = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
|
||||
|
||||
v_iconMapUV = a_iconMapUV;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,6 @@ uniform vec2 u_textSize;
|
|||
uniform float segmentNumber;
|
||||
varying vec2 v_iconMapUV;
|
||||
|
||||
varying vec4 v_dataset; // 数据集 - 用于合并单个的 varying 变量
|
||||
|
||||
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
|
||||
|
||||
uniform float u_linearColor: 0;
|
||||
|
@ -34,8 +32,8 @@ uniform vec4 u_targetColor;
|
|||
void main() {
|
||||
float opacity = styleMappingMat[0][0];
|
||||
float animateSpeed = 0.0; // 运动速度
|
||||
float d_segmentIndex = v_dataset.r; // 当前顶点在弧线中所处的分段位置
|
||||
float d_distance_ratio = v_dataset.b; // 当前顶点在弧线中所处的分段比例
|
||||
float d_segmentIndex = styleMappingMat[3].r; // 当前顶点在弧线中所处的分段位置
|
||||
float d_distance_ratio = styleMappingMat[3].b; // 当前顶点在弧线中所处的分段比例
|
||||
|
||||
// 设置弧线的底色
|
||||
if(u_linearColor == 1.0) { // 使用渐变颜色
|
||||
|
@ -70,14 +68,14 @@ void main() {
|
|||
float arcRadio = smoothstep( 0.0, 1.0, (d_segmentIndex / segmentNumber));
|
||||
// float arcRadio = smoothstep( 0.0, 1.0, d_distance_ratio);
|
||||
|
||||
float d_texCount = v_dataset.g; // 贴图在弧线上重复的数量
|
||||
float d_texCount = styleMappingMat[3].g; // 贴图在弧线上重复的数量
|
||||
|
||||
float u = 1.0 - fract(arcRadio * d_texCount + animateSpeed);
|
||||
|
||||
if(u_aimate.x == Animate) {
|
||||
u = gl_FragColor.a/opacity;
|
||||
}
|
||||
float v = v_dataset.a; // 横向 v
|
||||
float v = styleMappingMat[3].a; // 横向 v
|
||||
vec2 uv= v_iconMapUV / u_textSize + vec2(u, v) / u_textSize * 64.;
|
||||
|
||||
vec4 pattern = texture2D(u_texture, uv);
|
||||
|
|
|
@ -20,8 +20,6 @@ uniform sampler2D u_texture;
|
|||
uniform vec2 u_textSize;
|
||||
uniform float segmentNumber;
|
||||
|
||||
varying vec4 v_dataset; // 数据集
|
||||
|
||||
varying vec2 v_iconMapUV;
|
||||
|
||||
uniform float u_linearColor: 0;
|
||||
|
@ -37,7 +35,7 @@ varying mat4 styleMappingMat;
|
|||
void main() {
|
||||
float opacity = styleMappingMat[0][0];
|
||||
float animateSpeed = 0.0;
|
||||
float d_segmentIndex = v_dataset.g;
|
||||
float d_segmentIndex = styleMappingMat[3].g;
|
||||
|
||||
// 设置弧线的底色
|
||||
if(u_linearColor == 1.0) { // 使用渐变颜色
|
||||
|
@ -71,14 +69,14 @@ void main() {
|
|||
if(LineTexture == u_line_texture && u_line_type != LineTypeDash) {
|
||||
float arcRadio = smoothstep( 0.0, 1.0, (d_segmentIndex / (segmentNumber - 1.0)));
|
||||
// float arcRadio = d_segmentIndex / (segmentNumber - 1.0);
|
||||
float count = v_dataset.b; // 贴图在弧线上重复的数量
|
||||
float count = styleMappingMat[3].b; // 贴图在弧线上重复的数量
|
||||
float u = fract(arcRadio * count - animateSpeed * count);
|
||||
// float u = fract(arcRadio * count - animateSpeed);
|
||||
if(u_aimate.x == Animate) {
|
||||
u = gl_FragColor.a/opacity;
|
||||
}
|
||||
|
||||
float v = v_dataset.a; // 线图层贴图部分的 v 坐标值
|
||||
float v = styleMappingMat[3].a; // 线图层贴图部分的 v 坐标值
|
||||
|
||||
vec2 uv= v_iconMapUV / u_textSize + vec2(u, v) / u_textSize * 64.;
|
||||
vec4 pattern = texture2D(u_texture, uv);
|
||||
|
|
|
@ -22,8 +22,6 @@ varying vec4 v_dash_array;
|
|||
uniform float u_icon_step: 100;
|
||||
uniform float u_line_texture: 0.0;
|
||||
|
||||
varying vec4 v_dataset; // 数据集
|
||||
|
||||
attribute vec2 a_iconMapUV;
|
||||
varying vec2 v_iconMapUV;
|
||||
|
||||
|
@ -131,7 +129,7 @@ void main() {
|
|||
0.0, 0.0, 0.0, 0.0, // opacity - strokeOpacity - strokeWidth - empty
|
||||
0.0, 0.0, 0.0, 0.0, // strokeR - strokeG - strokeB - strokeA
|
||||
0.0, 0.0, 0.0, 0.0, // offsets[0] - offsets[1]
|
||||
0.0, 0.0, 0.0, 0.0
|
||||
0.0, 0.0, 0.0, 0.0 // dataset 数据集
|
||||
);
|
||||
|
||||
float rowCount = u_cellTypeLayout[0][0]; // 当前的数据纹理有几行
|
||||
|
@ -185,7 +183,7 @@ void main() {
|
|||
// vec4 project_pos = project_position(vec4(curr.xy, 0, 1.0));
|
||||
// gl_Position = project_common_position_to_clipspace(vec4(curr.xy + offset, curr.z, 1.0));
|
||||
|
||||
v_dataset.g = a_Position.x; // 该顶点在弧线上的分段排序
|
||||
styleMappingMat[3].g = a_Position.x; // 该顶点在弧线上的分段排序
|
||||
if(LineTexture == u_line_texture) { // 开启贴图模式
|
||||
// float mapZoomScale = u_CoordinateSystem !== COORDINATE_SYSTEM_P20_2?10000000.0:1.0;
|
||||
float d_arcDistrance = length(source - target);
|
||||
|
@ -196,11 +194,11 @@ void main() {
|
|||
d_arcDistrance = project_pixel_allmap(d_arcDistrance);
|
||||
}
|
||||
float d_pixelLen = project_pixel(u_icon_step)/8.0;
|
||||
v_dataset.b = floor(d_arcDistrance/d_pixelLen); // 贴图在弧线上重复的数量
|
||||
styleMappingMat[3].b = floor(d_arcDistrance/d_pixelLen); // 贴图在弧线上重复的数量
|
||||
|
||||
float lineOffsetWidth = length(offset + offset * sign(a_Position.y)); // 线横向偏移的距离
|
||||
float linePixelSize = project_pixel(a_Size); // 定点位置偏移,按地图等级缩放后的距离
|
||||
v_dataset.a = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
|
||||
styleMappingMat[3].a = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
|
||||
|
||||
v_iconMapUV = a_iconMapUV;
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@ uniform float u_line_texture: 0.0;
|
|||
attribute vec2 a_iconMapUV;
|
||||
varying vec2 v_iconMapUV;
|
||||
|
||||
varying vec4 v_dataset; // 数据集 - 用于合并单个的 varying 变量
|
||||
|
||||
uniform float u_opacity: 1.0;
|
||||
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
|
||||
|
||||
|
@ -92,7 +90,7 @@ void main() {
|
|||
0.0, 0.0, 0.0, 0.0, // opacity - strokeOpacity - strokeWidth - empty
|
||||
0.0, 0.0, 0.0, 0.0, // strokeR - strokeG - strokeB - strokeA
|
||||
0.0, 0.0, 0.0, 0.0, // offsets[0] - offsets[1]
|
||||
0.0, 0.0, 0.0, 0.0
|
||||
0.0, 0.0, 0.0, 0.0 // dataset 数据集
|
||||
);
|
||||
|
||||
float rowCount = u_cellTypeLayout[0][0]; // 当前的数据纹理有几行
|
||||
|
@ -144,7 +142,7 @@ void main() {
|
|||
}
|
||||
}
|
||||
|
||||
v_dataset.b = d_distance_ratio;
|
||||
styleMappingMat[3].b = d_distance_ratio;
|
||||
|
||||
vec4 curr = project_position(vec4(interpolate(source, target, segmentRatio), 0.0, 1.0));
|
||||
vec4 next = project_position(vec4(interpolate(source, target, nextSegmentRatio), 0.0, 1.0));
|
||||
|
@ -155,7 +153,7 @@ void main() {
|
|||
|
||||
|
||||
float d_segmentIndex = a_Position.x + 1.0; // 当前顶点在弧线中所处的分段位置
|
||||
v_dataset.r = d_segmentIndex;
|
||||
styleMappingMat[3].r = d_segmentIndex;
|
||||
|
||||
if(LineTexture == u_line_texture) { // 开启贴图模式
|
||||
|
||||
|
@ -171,11 +169,11 @@ void main() {
|
|||
|
||||
float pixelLen = project_pixel(u_icon_step); // 贴图沿弧线方向的长度 - 随地图缩放改变
|
||||
float texCount = floor(arcDistrance/pixelLen); // 贴图在弧线上重复的数量
|
||||
v_dataset.g = texCount;
|
||||
styleMappingMat[3].g = texCount;
|
||||
|
||||
float lineOffsetWidth = length(offset + offset * sign(a_Position.y)); // 线横向偏移的距离
|
||||
float linePixelSize = project_pixel(a_Size); // 定点位置偏移
|
||||
v_dataset.a = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
|
||||
styleMappingMat[3].a = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#define LineTypeSolid 0.0
|
||||
#define Animate 0.0
|
||||
|
||||
uniform float u_opacity;
|
||||
uniform float u_blur : 0.9;
|
||||
// varying vec2 v_normal;
|
||||
varying vec4 v_color;
|
||||
|
||||
uniform float u_time;
|
||||
uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ];
|
||||
|
||||
uniform float segmentNumber;
|
||||
varying float v_distance_ratio;
|
||||
|
||||
uniform float u_linearColor: 0;
|
||||
uniform vec4 u_sourceColor;
|
||||
uniform vec4 u_targetColor;
|
||||
|
||||
#pragma include "picking"
|
||||
|
||||
void main() {
|
||||
|
||||
// 设置弧线的底色
|
||||
if(u_linearColor == 1.0) { // 使用渐变颜色
|
||||
gl_FragColor = mix(u_sourceColor, u_targetColor, v_distance_ratio);
|
||||
} else { // 使用 color 方法传入的颜色
|
||||
gl_FragColor = v_color;
|
||||
}
|
||||
|
||||
|
||||
gl_FragColor.a *= u_opacity;
|
||||
|
||||
if(u_aimate.x == Animate) {
|
||||
float animateSpeed = u_time / u_aimate.y; // 运动速度
|
||||
float alpha =1.0 - fract( mod(1.0- v_distance_ratio, u_aimate.z)* (1.0/ u_aimate.z) + u_time / u_aimate.y);
|
||||
alpha = (alpha + u_aimate.w -1.0) / u_aimate.w;
|
||||
// alpha = smoothstep(0., 1., alpha);
|
||||
alpha = clamp(alpha, 0.0, 1.0);
|
||||
gl_FragColor.a *= alpha;
|
||||
}
|
||||
gl_FragColor = filterColor(gl_FragColor);
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
#define LineTypeSolid 0.0
|
||||
#define LineTypeDash 1.0
|
||||
#define Animate 0.0
|
||||
|
||||
attribute vec4 a_Color;
|
||||
attribute vec3 a_Position;
|
||||
attribute vec4 a_Instance;
|
||||
attribute float a_Size;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_Mvp;
|
||||
uniform float segmentNumber;
|
||||
uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ];
|
||||
varying vec4 v_color;
|
||||
// varying vec2 v_normal;
|
||||
|
||||
uniform float u_lineDir: 1.0;
|
||||
|
||||
// 偏移量
|
||||
uniform float u_thetaOffset: 0.314;
|
||||
|
||||
uniform float u_opacity: 1.0;
|
||||
varying float v_distance_ratio;
|
||||
|
||||
#pragma include "projection"
|
||||
#pragma include "project"
|
||||
#pragma include "picking"
|
||||
|
||||
float bezier3(vec3 arr, float t) {
|
||||
float ut = 1. - t;
|
||||
return (arr.x * ut + arr.y * t) * ut + (arr.y * ut + arr.z * t) * t;
|
||||
}
|
||||
vec2 midPoint(vec2 source, vec2 target) {
|
||||
vec2 center = target - source;
|
||||
float r = length(center);
|
||||
float theta = atan(center.y, center.x);
|
||||
float thetaOffset = u_thetaOffset;
|
||||
float r2 = r / 2.0 / cos(thetaOffset);
|
||||
float theta2 = theta + thetaOffset;
|
||||
vec2 mid = vec2(r2*cos(theta2) + source.x, r2*sin(theta2) + source.y);
|
||||
if(u_lineDir == 1.0) { // 正向
|
||||
return mid;
|
||||
} else { // 逆向
|
||||
// (mid + vmin)/2 = (s + t)/2
|
||||
vec2 vmid = source + target - mid;
|
||||
return vmid;
|
||||
}
|
||||
// return mid;
|
||||
}
|
||||
float getSegmentRatio(float index) {
|
||||
return smoothstep(0.0, 1.0, index / (segmentNumber - 1.));
|
||||
}
|
||||
vec2 interpolate (vec2 source, vec2 target, float t) {
|
||||
// if the angularDist is PI, linear interpolation is applied. otherwise, use spherical interpolation
|
||||
vec2 mid = midPoint(source, target);
|
||||
vec3 x = vec3(source.x, mid.x, target.x);
|
||||
vec3 y = vec3(source.y, mid.y, target.y);
|
||||
return vec2(bezier3(x ,t), bezier3(y,t));
|
||||
}
|
||||
vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) {
|
||||
// normalized direction of the line
|
||||
vec2 dir_screenspace = normalize(line_clipspace);
|
||||
// rotate by 90 degrees
|
||||
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
|
||||
vec2 offset = dir_screenspace * offset_direction * setPickingSize(a_Size) / 2.0;
|
||||
return offset;
|
||||
}
|
||||
vec2 getNormal(vec2 line_clipspace, float offset_direction) {
|
||||
// normalized direction of the line
|
||||
vec2 dir_screenspace = normalize(line_clipspace);
|
||||
// rotate by 90 degrees
|
||||
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
|
||||
return reverse_offset_normal(vec3(dir_screenspace,1.0)).xy * sign(offset_direction);
|
||||
}
|
||||
|
||||
void main() {
|
||||
v_color = a_Color;
|
||||
|
||||
vec2 source = a_Instance.rg; // 起始点
|
||||
vec2 target = a_Instance.ba; // 终点
|
||||
float segmentIndex = a_Position.x;
|
||||
float segmentRatio = getSegmentRatio(segmentIndex);
|
||||
|
||||
float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0));
|
||||
float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir);
|
||||
|
||||
v_distance_ratio = segmentIndex / segmentNumber;
|
||||
|
||||
if(u_aimate.x == Animate && u_lineDir != 1.0) {
|
||||
v_distance_ratio = 1.0 - v_distance_ratio;
|
||||
}
|
||||
|
||||
vec4 curr = project_position(vec4(interpolate(source, target, segmentRatio), 0.0, 1.0));
|
||||
vec4 next = project_position(vec4(interpolate(source, target, nextSegmentRatio), 0.0, 1.0));
|
||||
// v_normal = getNormal((next.xy - curr.xy) * indexDir, a_Position.y);
|
||||
//unProjCustomCoord
|
||||
|
||||
vec2 offset = project_pixel(getExtrusionOffset((next.xy - curr.xy) * indexDir, a_Position.y));
|
||||
|
||||
if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x
|
||||
gl_Position = u_Mvp * (vec4(curr.xy + offset, 0, 1.0));
|
||||
} else {
|
||||
gl_Position = project_common_position_to_clipspace(vec4(curr.xy + offset, 0, 1.0));
|
||||
}
|
||||
setPickingColor(a_PickingColor);
|
||||
}
|
|
@ -7,7 +7,7 @@ uniform float u_line_type: 0.0;
|
|||
uniform float u_opacity : 1.0;
|
||||
uniform float u_textureBlend;
|
||||
varying vec4 v_color;
|
||||
varying vec2 v_normal;
|
||||
// varying vec2 v_normal;
|
||||
|
||||
// line texture
|
||||
uniform float u_line_texture;
|
||||
|
@ -19,8 +19,6 @@ uniform float u_dash_offset : 0.0;
|
|||
uniform float u_dash_ratio : 0.1;
|
||||
varying vec4 v_dash_array;
|
||||
|
||||
varying vec4 v_dataset; // 数据集 - distance_ratio/distance/pixelLen/texV
|
||||
|
||||
varying vec2 v_iconMapUV;
|
||||
|
||||
uniform float u_linearColor: 0;
|
||||
|
@ -37,7 +35,7 @@ varying mat4 styleMappingMat;
|
|||
void main() {
|
||||
float opacity = styleMappingMat[0][0];
|
||||
float animateSpeed = 0.0; // 运动速度
|
||||
float d_distance_ratio = v_dataset.r; // 当前点位距离占线总长的比例
|
||||
float d_distance_ratio = styleMappingMat[3].r; // 当前点位距离占线总长的比例
|
||||
|
||||
if(u_linearColor == 1.0) { // 使用渐变颜色
|
||||
gl_FragColor = mix(u_sourceColor, u_targetColor, d_distance_ratio);
|
||||
|
@ -66,13 +64,14 @@ void main() {
|
|||
}
|
||||
|
||||
if(u_line_texture == LineTexture && u_line_type != LineTypeDash) { // while load texture
|
||||
float aDistance = v_dataset.g; // 当前顶点的距离
|
||||
float d_texPixelLen = v_dataset.b; // 贴图的像素长度,根据地图层级缩放
|
||||
float aDistance = styleMappingMat[3].g; // 当前顶点的距离
|
||||
float d_texPixelLen = styleMappingMat[3].b; // 贴图的像素长度,根据地图层级缩放
|
||||
float u = fract(mod(aDistance, d_texPixelLen)/d_texPixelLen - animateSpeed);
|
||||
float v = v_dataset.a; // 线图层贴图部分的 v 坐标值
|
||||
float v = styleMappingMat[3].a; // 线图层贴图部分的 v 坐标值
|
||||
|
||||
v = max(smoothstep(0.95, 1.0, v), v);
|
||||
vec2 uv= v_iconMapUV / u_textSize + vec2(u, v) / u_textSize * 64.;
|
||||
|
||||
// gl_FragColor = filterColor(gl_FragColor + texture2D(u_texture, vec2(u, v)));
|
||||
// gl_FragColor = filterColor(gl_FragColor + texture2D(u_texture, uv));
|
||||
vec4 pattern = texture2D(u_texture, uv);
|
||||
|
@ -90,13 +89,14 @@ void main() {
|
|||
} else {
|
||||
gl_FragColor = filterColor(gl_FragColor);
|
||||
}
|
||||
// gl_FragColor = filterColor(vec4(1.0, 0.0, 0.0, 1.0));
|
||||
|
||||
// gl_FragColor = (vec4(1.0, 0.0, 0.0, 1.0));
|
||||
|
||||
// if(rV < r || rV > 1.0 - r) {
|
||||
// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
// }
|
||||
// if(v > 0.9) {
|
||||
// gl_FragColor = vec4(0.17647, 0.43921568, 0.2, 1.0);
|
||||
// gl_FragColor = vec4(0.17647, 0.43921568, 0.2, 1.0);
|
||||
// } else if(v < 0.1) {
|
||||
// gl_FragColor = vec4(0.17647, 0.43921568, 0.2, 1.0);
|
||||
// }
|
||||
|
|
|
@ -28,9 +28,10 @@ varying vec4 v_color;
|
|||
varying vec4 v_dash_array;
|
||||
varying vec2 v_normal;
|
||||
|
||||
varying vec4 v_dataset; // 数据集 - distance_ratio/distance/pixelLen/texV
|
||||
// texV 线图层 - 贴图部分的 v 坐标(线的宽度方向)
|
||||
varying vec2 v_iconMapUV;
|
||||
|
||||
|
||||
uniform float u_linearColor: 0;
|
||||
|
||||
uniform float u_opacity: 1.0;
|
||||
|
@ -45,7 +46,7 @@ void main() {
|
|||
0.0, 0.0, 0.0, 0.0, // opacity - strokeOpacity - strokeWidth - empty
|
||||
0.0, 0.0, 0.0, 0.0, // strokeR - strokeG - strokeB - strokeA
|
||||
0.0, 0.0, 0.0, 0.0, // offsets[0] - offsets[1]
|
||||
0.0, 0.0, 0.0, 0.0
|
||||
0.0, 0.0, 0.0, 0.0 // distance_ratio/distance/pixelLen/texV
|
||||
);
|
||||
|
||||
float rowCount = u_cellTypeLayout[0][0]; // 当前的数据纹理有几行
|
||||
|
@ -84,7 +85,6 @@ void main() {
|
|||
}
|
||||
v_normal = vec2(reverse_offset_normal(a_Normal) * sign(a_Miter));
|
||||
|
||||
|
||||
v_color = a_Color;
|
||||
|
||||
vec3 size = a_Miter * setPickingSize(a_Size.x) * reverse_offset_normal(a_Normal);
|
||||
|
@ -96,10 +96,10 @@ void main() {
|
|||
float texV = lineOffsetWidth/linePixelSize; // 线图层贴图部分的 v 坐标值
|
||||
|
||||
// 设置数据集的参数
|
||||
v_dataset.r = d_distance_ratio; // 当前点位距离占线总长的比例
|
||||
v_dataset.g = a_Distance; // 当前顶点的距离
|
||||
v_dataset.b = d_texPixelLen; // 贴图的像素长度,根据地图层级缩放
|
||||
v_dataset.a = texV; // 线图层贴图部分的 v 坐标值
|
||||
styleMappingMat[3][0] = d_distance_ratio; // 当前点位距离占线总长的比例
|
||||
styleMappingMat[3][1] = a_Distance; // 当前顶点的距离
|
||||
styleMappingMat[3][2] = d_texPixelLen; // 贴图的像素长度,根据地图层级缩放
|
||||
styleMappingMat[3][3] = texV; // 线图层贴图部分的 v 坐标值
|
||||
|
||||
vec4 project_pos = project_position(vec4(a_Position.xy, 0, 1.0));
|
||||
|
||||
|
|
|
@ -5,9 +5,8 @@ import {
|
|||
IMapService,
|
||||
TYPES,
|
||||
} from '@antv/l7-core';
|
||||
import Source from '@antv/l7-source';
|
||||
import Source, { DEFAULT_DATA, DEFAULT_PARSER } from '@antv/l7-source';
|
||||
import { injectable } from 'inversify';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import 'reflect-metadata';
|
||||
|
||||
@injectable()
|
||||
|
@ -18,7 +17,11 @@ export default class DataSourcePlugin implements ILayerPlugin {
|
|||
layer.hooks.init.tap('DataSourcePlugin', () => {
|
||||
const source = layer.getSource();
|
||||
if (!source) {
|
||||
const { data, options } = layer.sourceOption;
|
||||
// TODO: 允许用户不使用 layer 的 source 方法,在这里传入一个默认的替换的默认数据
|
||||
const { data, options } = layer.sourceOption || {
|
||||
data: DEFAULT_DATA,
|
||||
options: DEFAULT_PARSER,
|
||||
};
|
||||
layer.setSource(new Source(data, options));
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,8 @@ export default class ShaderUniformPlugin implements ILayerPlugin {
|
|||
// u_ModelMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
|
||||
u_ModelMatrix: this.cameraService.getModelMatrix(),
|
||||
u_PickingBuffer: layer.getLayerConfig().pickingBuffer || 0,
|
||||
// TODO: 当前地图是否在拖动
|
||||
u_Dragging: Number(this.mapService.dragging),
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
IModel,
|
||||
IModelUniform,
|
||||
} from '@antv/l7-core';
|
||||
import { rgb2arr } from '@antv/l7-utils';
|
||||
import BaseModel, {
|
||||
styleColor,
|
||||
styleOffset,
|
||||
|
@ -22,7 +21,7 @@ import {
|
|||
import pointFillFrag from '../shaders/fill_frag.glsl';
|
||||
import pointFillVert from '../shaders/fill_vert.glsl';
|
||||
|
||||
import { isNumber, isString } from 'lodash';
|
||||
import { isNumber } from 'lodash';
|
||||
|
||||
import { mat4, vec3 } from 'gl-matrix';
|
||||
|
||||
|
@ -32,7 +31,6 @@ interface IPointLayerStyleOptions {
|
|||
stroke: styleColor;
|
||||
strokeOpacity: styleSingle;
|
||||
offsets: styleOffset;
|
||||
isGlobel?: boolean;
|
||||
}
|
||||
// 判断当前使用的 style 中的变量属性是否需要进行数据映射
|
||||
export default class FillModel extends BaseModel {
|
||||
|
@ -43,8 +41,6 @@ export default class FillModel extends BaseModel {
|
|||
strokeWidth = 0,
|
||||
stroke = 'rgba(0,0,0,0)',
|
||||
offsets = [0, 0],
|
||||
// TODO: 判断当前图层是否为地球模式
|
||||
isGlobel = false,
|
||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||
|
||||
if (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-map",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "l7 map",
|
||||
"keywords": [],
|
||||
"author": "thinkinggis <lzx199065@gmail.com>",
|
||||
|
@ -37,7 +37,7 @@
|
|||
},
|
||||
"homepage": "https://github.com/antvis/L7#readme",
|
||||
"dependencies": {
|
||||
"@antv/l7-utils": "^2.5.30",
|
||||
"@antv/l7-utils": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@mapbox/point-geometry": "^0.1.0",
|
||||
"@mapbox/unitbezier": "^0.0.0",
|
||||
|
|
|
@ -307,7 +307,7 @@ class ScrollZoomHandler {
|
|||
private onTimeout(initialEvent: any) {
|
||||
this.type = 'wheel';
|
||||
this.delta -= this.lastValue;
|
||||
if (!this.active) {
|
||||
if (!this.active && this.start) {
|
||||
this.start(initialEvent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-maps",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -27,9 +27,9 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@amap/amap-jsapi-loader": "^0.0.3",
|
||||
"@antv/l7-core": "^2.5.30",
|
||||
"@antv/l7-map": "^2.5.30",
|
||||
"@antv/l7-utils": "^2.5.30",
|
||||
"@antv/l7-core": "^2.5.41",
|
||||
"@antv/l7-map": "^2.5.41",
|
||||
"@antv/l7-utils": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@types/amap-js-api": "^1.4.6",
|
||||
"@types/mapbox-gl": "^1.11.2",
|
||||
|
|
|
@ -61,6 +61,12 @@ export default class AMapService
|
|||
*/
|
||||
public map: AMap.Map & IAMapInstance;
|
||||
|
||||
// TODO: 判断地图是否正在拖拽
|
||||
public dragging: boolean = false;
|
||||
|
||||
// 背景色
|
||||
public bgColor: string = 'rgba(0, 0, 0, 0)';
|
||||
|
||||
@inject(TYPES.IGlobalConfigService)
|
||||
private readonly configService: IGlobalConfigService;
|
||||
|
||||
|
@ -79,6 +85,9 @@ export default class AMapService
|
|||
private viewport: Viewport;
|
||||
|
||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
||||
public setBgColor(color: string) {
|
||||
this.bgColor = color;
|
||||
}
|
||||
|
||||
public addMarkerContainer(): void {
|
||||
const mapContainer = this.map.getContainer();
|
||||
|
@ -397,6 +406,16 @@ export default class AMapService
|
|||
}
|
||||
});
|
||||
|
||||
// TODO: 判断地图是否正在被拖拽
|
||||
this.map.on('dragstart', () => {
|
||||
this.dragging = true;
|
||||
return '';
|
||||
});
|
||||
this.map.on('dragend', () => {
|
||||
this.dragging = false;
|
||||
return '';
|
||||
});
|
||||
|
||||
this.viewport = new Viewport();
|
||||
}
|
||||
|
||||
|
@ -453,6 +472,8 @@ export default class AMapService
|
|||
position,
|
||||
} = e.camera;
|
||||
const { lng, lat } = this.getCenter();
|
||||
// Tip: 触发地图变化事件
|
||||
this.emit('mapchange');
|
||||
if (this.cameraChangedCallback) {
|
||||
// resync viewport
|
||||
// console.log('cameraHeight', height)
|
||||
|
|
|
@ -64,12 +64,18 @@ export default class AMapService
|
|||
*/
|
||||
public map: AMap.Map & IAMapInstance;
|
||||
|
||||
// TODO: 判断地图是否正在拖拽
|
||||
public dragging: boolean = false;
|
||||
|
||||
/**
|
||||
* 用于 customCooords 数据的计算
|
||||
*/
|
||||
public sceneCenter!: [number, number]; // 一般使用用户数据的第一个
|
||||
public sceneCenterMKT!: [number, number]; // 莫卡托
|
||||
|
||||
// 背景色
|
||||
public bgColor: string = 'rgba(0, 0, 0, 0)';
|
||||
|
||||
@inject(TYPES.IGlobalConfigService)
|
||||
private readonly configService: IGlobalConfigService;
|
||||
|
||||
|
@ -88,6 +94,9 @@ export default class AMapService
|
|||
private viewport: Viewport;
|
||||
|
||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
||||
public setBgColor(color: string) {
|
||||
this.bgColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置数据的绘制中心 高德2.0
|
||||
|
@ -145,15 +154,17 @@ export default class AMapService
|
|||
}
|
||||
const mapContainer = this.map.getContainer();
|
||||
if (mapContainer !== null) {
|
||||
// const amap = mapContainer.getElementsByClassName(
|
||||
// 'amap-maps',
|
||||
// )[0] as HTMLElement;
|
||||
// this.markerContainer = DOM.create('div', 'l7-marker-container2', amap);
|
||||
this.markerContainer = DOM.create(
|
||||
'div',
|
||||
'l7-marker-container2',
|
||||
mapContainer,
|
||||
);
|
||||
const amap = mapContainer.getElementsByClassName(
|
||||
'amap-maps',
|
||||
)[0] as HTMLElement;
|
||||
// TODO: amap2 的 amap-maps 新增 z-index=0; 样式,让 marker 中 zIndex 失效
|
||||
amap.style.zIndex = 'auto';
|
||||
this.markerContainer = DOM.create('div', 'l7-marker-container2', amap);
|
||||
// this.markerContainer = DOM.create(
|
||||
// 'div',
|
||||
// 'l7-marker-container2',
|
||||
// mapContainer,
|
||||
// );
|
||||
// this.markerContainer = mapContainer;
|
||||
}
|
||||
}
|
||||
|
@ -486,6 +497,16 @@ export default class AMapService
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: 判断地图是否正在被拖拽
|
||||
this.map.on('dragstart', () => {
|
||||
this.dragging = true;
|
||||
return '';
|
||||
});
|
||||
this.map.on('dragend', () => {
|
||||
this.dragging = false;
|
||||
return '';
|
||||
});
|
||||
}
|
||||
|
||||
public exportMap(type: 'jpg' | 'png'): string {
|
||||
|
@ -550,6 +571,8 @@ export default class AMapService
|
|||
// left, right, bottom, top
|
||||
// @ts-ignore
|
||||
} = this.map.customCoords?.getCameraParams();
|
||||
// Tip: 统一触发地图变化事件
|
||||
this.emit('mapchange');
|
||||
// // @ts-ignore
|
||||
// console.log('this.map.customCoords.getCameraParams()', this.map.customCoords.getCameraParams())
|
||||
// const { left, right, bottom, top, near, far, position } = this.map.customCoords.getCameraParams();
|
||||
|
@ -612,6 +635,9 @@ export default class AMapService
|
|||
// left, right, bottom, top
|
||||
// @ts-ignore
|
||||
} = this.map.customCoords.getCameraParams();
|
||||
// Tip: 统一触发地图变化事件
|
||||
this.emit('mapchange');
|
||||
|
||||
const { zoom } = e;
|
||||
// @ts-ignore
|
||||
const center = this.map.customCoords.getCenter() as [number, number];
|
||||
|
|
|
@ -2,6 +2,11 @@ import { IMapCamera, IViewport } from '@antv/l7-core';
|
|||
import { mat4, vec3 } from 'gl-matrix';
|
||||
import WebMercatorViewport from 'viewport-mercator-project';
|
||||
|
||||
export interface IEarthCamera {
|
||||
viewportHeight: number;
|
||||
viewportWidth: number;
|
||||
}
|
||||
|
||||
export default class Viewport implements IViewport {
|
||||
// TODO: 初始化相机的姿态 看向地球
|
||||
private xzReg: number = -Math.PI * 0.6;
|
||||
|
@ -21,7 +26,7 @@ export default class Viewport implements IViewport {
|
|||
private ViewProjectionMatrixUncentered: mat4 = mat4.create();
|
||||
private viewUncenteredMatrix: mat4 = mat4.create();
|
||||
|
||||
public syncWithMapCamera(mapCamera: Partial<IMapCamera>) {
|
||||
public syncWithMapCamera(mapCamera: Partial<IEarthCamera>) {
|
||||
const { viewportHeight = 1, viewportWidth = 1 } = mapCamera;
|
||||
const aspect = viewportWidth / viewportHeight;
|
||||
const near = 0.1;
|
||||
|
|
|
@ -5,10 +5,10 @@ import {
|
|||
Bounds,
|
||||
CoordinateSystem,
|
||||
ICoordinateSystemService,
|
||||
IEarthService,
|
||||
IGlobalConfigService,
|
||||
ILngLat,
|
||||
IMapConfig,
|
||||
IMapService,
|
||||
IMercator,
|
||||
IPoint,
|
||||
IStatusOptions,
|
||||
|
@ -38,10 +38,16 @@ const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
|
|||
* AMapService
|
||||
*/
|
||||
@injectable()
|
||||
export default class L7MapService implements IMapService<Map> {
|
||||
export default class L7EarthService implements IEarthService<Map> {
|
||||
public version: string = Version.GLOBEL;
|
||||
public map: Map;
|
||||
|
||||
// TODO: 判断地图是否正在拖拽
|
||||
public dragging: boolean = false;
|
||||
|
||||
// 背景色
|
||||
public bgColor: string = '#000';
|
||||
|
||||
@inject(TYPES.MapConfig)
|
||||
private readonly config: Partial<IMapConfig>;
|
||||
|
||||
|
@ -60,7 +66,9 @@ export default class L7MapService implements IMapService<Map> {
|
|||
// T: 用于记录鼠标对相机的控制
|
||||
private handleCameraChanging: boolean;
|
||||
private handleCameraTimer: any;
|
||||
|
||||
public setBgColor(color: string) {
|
||||
this.bgColor = color;
|
||||
}
|
||||
// init
|
||||
public addMarkerContainer(): void {
|
||||
const container = this.map.getCanvasContainer();
|
||||
|
@ -323,18 +331,17 @@ export default class L7MapService implements IMapService<Map> {
|
|||
this.viewport.rotateY(reg);
|
||||
|
||||
this.viewport.syncWithMapCamera({
|
||||
bearing: this.map.getBearing(),
|
||||
viewportHeight: this.map.transform.height,
|
||||
pitch: this.map.getPitch(),
|
||||
viewportWidth: this.map.transform.width,
|
||||
zoom: this.map.getZoom(),
|
||||
// mapbox 中固定相机高度为 viewport 高度的 1.5 倍
|
||||
cameraHeight: 0,
|
||||
});
|
||||
|
||||
this.cameraChangedCallback(this.viewport);
|
||||
}
|
||||
}
|
||||
|
||||
private handleCameraChanged = (e: any) => {
|
||||
// Tip: 统一触发地图变化事件
|
||||
this.emit('mapchange');
|
||||
const DELAY_TIME = 2000;
|
||||
this.handleCameraChanging = true;
|
||||
if (this.handleCameraTimer) {
|
||||
|
@ -374,13 +381,8 @@ export default class L7MapService implements IMapService<Map> {
|
|||
|
||||
// resync
|
||||
this.viewport.syncWithMapCamera({
|
||||
bearing: this.map.getBearing(),
|
||||
viewportHeight: this.map.transform.height,
|
||||
pitch: this.map.getPitch(),
|
||||
viewportWidth: this.map.transform.width,
|
||||
zoom: this.map.getZoom(),
|
||||
// mapbox 中固定相机高度为 viewport 高度的 1.5 倍
|
||||
cameraHeight: 0,
|
||||
});
|
||||
// set coordinate system
|
||||
if (
|
||||
|
|
|
@ -43,6 +43,12 @@ export default class L7MapService implements IMapService<Map> {
|
|||
public version: string = Version.L7MAP;
|
||||
public map: Map;
|
||||
|
||||
// TODO: 判断地图是否正在拖拽
|
||||
public dragging: boolean = false;
|
||||
|
||||
// 背景色
|
||||
public bgColor: string = 'rgba(0.0, 0.0, 0.0, 0.0)';
|
||||
|
||||
@inject(TYPES.MapConfig)
|
||||
private readonly config: Partial<IMapConfig>;
|
||||
|
||||
|
@ -58,6 +64,9 @@ export default class L7MapService implements IMapService<Map> {
|
|||
private markerContainer: HTMLElement;
|
||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
||||
private $mapContainer: HTMLElement | null;
|
||||
public setBgColor(color: string) {
|
||||
this.bgColor = color;
|
||||
}
|
||||
|
||||
// init
|
||||
public addMarkerContainer(): void {
|
||||
|
@ -274,6 +283,16 @@ export default class L7MapService implements IMapService<Map> {
|
|||
this.map.on('load', this.handleCameraChanged);
|
||||
this.map.on('move', this.handleCameraChanged);
|
||||
|
||||
// TODO: 判断地图是否正在被拖拽
|
||||
this.map.on('dragstart', () => {
|
||||
this.dragging = true;
|
||||
return '';
|
||||
});
|
||||
this.map.on('dragend', () => {
|
||||
this.dragging = false;
|
||||
return '';
|
||||
});
|
||||
|
||||
// 不同于高德地图,需要手动触发首次渲染
|
||||
this.handleCameraChanged();
|
||||
}
|
||||
|
@ -314,7 +333,8 @@ export default class L7MapService implements IMapService<Map> {
|
|||
private handleCameraChanged = () => {
|
||||
const { lat, lng } = this.map.getCenter();
|
||||
const { offsetCoordinate = true } = this.config;
|
||||
|
||||
// Tip: 统一触发地图变化事件
|
||||
this.emit('mapchange');
|
||||
// resync
|
||||
this.viewport.syncWithMapCamera({
|
||||
bearing: this.map.getBearing(),
|
||||
|
|
|
@ -50,6 +50,12 @@ export default class MapboxService
|
|||
public version: string = Version.MAPBOX;
|
||||
public map: Map & IMapboxInstance;
|
||||
|
||||
// TODO: 判断地图是否正在拖拽
|
||||
public dragging: boolean = false;
|
||||
|
||||
// 背景色
|
||||
public bgColor: string = 'rgba(0.0, 0.0, 0.0, 0.0)';
|
||||
|
||||
@inject(TYPES.MapConfig)
|
||||
private readonly config: Partial<IMapConfig>;
|
||||
|
||||
|
@ -65,6 +71,9 @@ export default class MapboxService
|
|||
private markerContainer: HTMLElement;
|
||||
private cameraChangedCallback: (viewport: IViewport) => void;
|
||||
private $mapContainer: HTMLElement | null;
|
||||
public setBgColor(color: string) {
|
||||
this.bgColor = color;
|
||||
}
|
||||
|
||||
// init
|
||||
public addMarkerContainer(): void {
|
||||
|
@ -357,6 +366,16 @@ export default class MapboxService
|
|||
this.map.on('load', this.handleCameraChanged);
|
||||
this.map.on('move', this.handleCameraChanged);
|
||||
|
||||
// TODO: 判断地图是否正在被拖拽
|
||||
this.map.on('dragstart', () => {
|
||||
this.dragging = true;
|
||||
return '';
|
||||
});
|
||||
this.map.on('dragend', () => {
|
||||
this.dragging = false;
|
||||
return '';
|
||||
});
|
||||
|
||||
// 不同于高德地图,需要手动触发首次渲染
|
||||
this.handleCameraChanged();
|
||||
}
|
||||
|
@ -397,7 +416,8 @@ export default class MapboxService
|
|||
private handleCameraChanged = () => {
|
||||
// @see https://github.com/mapbox/mapbox-gl-js/issues/2572
|
||||
const { lat, lng } = this.map.getCenter().wrap();
|
||||
|
||||
// Tip: 统一触发地图变化事件
|
||||
this.emit('mapchange');
|
||||
// resync
|
||||
this.viewport.syncWithMapCamera({
|
||||
bearing: this.map.getBearing(),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-renderer",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -26,7 +26,7 @@
|
|||
"gl": "^4.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/l7-core": "^2.5.30",
|
||||
"@antv/l7-core": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"inversify": "^5.0.1",
|
||||
"l7regl": "^0.0.14",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-scene",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -23,12 +23,12 @@
|
|||
"author": "xiaoiver",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/l7-component": "^2.5.30",
|
||||
"@antv/l7-core": "^2.5.30",
|
||||
"@antv/l7-layers": "^2.5.30",
|
||||
"@antv/l7-maps": "^2.5.30",
|
||||
"@antv/l7-renderer": "^2.5.30",
|
||||
"@antv/l7-utils": "^2.5.30",
|
||||
"@antv/l7-component": "^2.5.41",
|
||||
"@antv/l7-core": "^2.5.41",
|
||||
"@antv/l7-layers": "^2.5.41",
|
||||
"@antv/l7-maps": "^2.5.41",
|
||||
"@antv/l7-renderer": "^2.5.41",
|
||||
"@antv/l7-utils": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"inversify": "^5.0.1",
|
||||
"mapbox-gl": "^1.2.1",
|
||||
|
|
|
@ -153,12 +153,16 @@ class Scene
|
|||
return this.mapService.map;
|
||||
}
|
||||
|
||||
public setBgColor(color: string) {
|
||||
this.mapService.setBgColor(color);
|
||||
}
|
||||
|
||||
// layer 管理
|
||||
public addLayer(layer: ILayer): void {
|
||||
// 为当前图层创建一个容器
|
||||
// TODO: 初始化的时候设置 容器
|
||||
const layerContainer = createLayerContainer(this.container);
|
||||
layer.setContainer(layerContainer);
|
||||
layer.setContainer(layerContainer, this.container);
|
||||
this.sceneService.addLayer(layer);
|
||||
}
|
||||
|
||||
|
@ -174,8 +178,8 @@ class Scene
|
|||
return this.layerService.getLayerByName(name);
|
||||
}
|
||||
|
||||
public removeLayer(layer: ILayer): void {
|
||||
this.layerService.remove(layer);
|
||||
public removeLayer(layer: ILayer, parentLayer?: ILayer): void {
|
||||
this.layerService.remove(layer, parentLayer);
|
||||
}
|
||||
|
||||
public removeAllLayer(): void {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-source",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -26,8 +26,8 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/async-hook": "^2.1.0",
|
||||
"@antv/l7-core": "^2.5.30",
|
||||
"@antv/l7-utils": "^2.5.30",
|
||||
"@antv/l7-core": "^2.5.41",
|
||||
"@antv/l7-utils": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@mapbox/geojson-rewind": "^0.4.0",
|
||||
"@turf/helpers": "^6.1.4",
|
||||
|
|
|
@ -2,7 +2,7 @@ import { registerParser, registerTransform } from './factory';
|
|||
import csv from './parser/csv';
|
||||
import geojson from './parser/geojson';
|
||||
import image from './parser/image';
|
||||
import json from './parser/json';
|
||||
import json, { defaultData, defaultParser } from './parser/json';
|
||||
import raster from './parser/raster';
|
||||
import Source from './source';
|
||||
import { cluster } from './transform/cluster';
|
||||
|
@ -31,3 +31,6 @@ export {
|
|||
} from './factory';
|
||||
|
||||
export * from './interface';
|
||||
|
||||
export const DEFAULT_DATA = defaultData;
|
||||
export const DEFAULT_PARSER = defaultParser;
|
||||
|
|
|
@ -7,7 +7,8 @@ export default function image(
|
|||
data: string | string[],
|
||||
cfg: IImageCfg,
|
||||
): IParserData {
|
||||
const { extent } = cfg;
|
||||
// TODO: 为 extent 赋默认值
|
||||
const { extent = [121.168, 30.2828, 121.384, 30.4219] } = cfg;
|
||||
const images = new Promise((resolve) => {
|
||||
loadData(data, (res: any) => {
|
||||
resolve(res);
|
||||
|
|
|
@ -47,3 +47,23 @@ export default function json(data: IJsonData, cfg: IParserCfg): IParserData {
|
|||
dataArray: resultData,
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: 提供默认数据和解析器
|
||||
export const defaultData = [
|
||||
{
|
||||
lng1: 100,
|
||||
lat1: 30.0,
|
||||
lng2: 130,
|
||||
lat2: 30,
|
||||
},
|
||||
];
|
||||
|
||||
export const defaultParser = {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng1',
|
||||
y: 'lat1',
|
||||
x1: 'lng2',
|
||||
y1: 'lat2',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -207,6 +207,14 @@ export default class Source extends EventEmitter implements ISource {
|
|||
private excuteParser(): void {
|
||||
const parser = this.parser;
|
||||
const type: string = parser.type || 'geojson';
|
||||
// TODO: 图片瓦片地图组件只需要使用 url 参数
|
||||
if (type === 'imagetile') {
|
||||
this.data = {
|
||||
tileurl: this.originData,
|
||||
dataArray: [],
|
||||
};
|
||||
return;
|
||||
}
|
||||
const sourceParser = getParser(type);
|
||||
this.data = sourceParser(this.originData, parser);
|
||||
// 计算范围
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-three",
|
||||
"version": "2.5.30",
|
||||
"version": "2.5.41",
|
||||
"description": "three for L7 ",
|
||||
"keywords": [
|
||||
"3D",
|
||||
|
@ -44,9 +44,9 @@
|
|||
},
|
||||
"homepage": "https://github.com/antvis/L7#readme",
|
||||
"dependencies": {
|
||||
"@antv/l7-core": "^2.5.30",
|
||||
"@antv/l7-layers": "^2.5.30",
|
||||
"@antv/l7-scene": "^2.5.30",
|
||||
"@antv/l7-core": "^2.5.41",
|
||||
"@antv/l7-layers": "^2.5.41",
|
||||
"@antv/l7-scene": "^2.5.41",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"inversify": "^5.0.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
|
|
|
@ -23,7 +23,7 @@ export default class ThreeJSLayer
|
|||
}>
|
||||
implements ILayer {
|
||||
public type: string = 'custom';
|
||||
protected threeRenderService: IThreeRenderService;
|
||||
public threeRenderService: IThreeRenderService;
|
||||
// 构建 threejs 的 scene
|
||||
private scene: Scene = new Scene();
|
||||
private renderer: WebGLRenderer;
|
||||
|
@ -198,6 +198,10 @@ export default class ThreeJSLayer
|
|||
return this;
|
||||
}
|
||||
|
||||
public getRenderCamera() {
|
||||
return this.threeRenderService.getRenderCamera();
|
||||
}
|
||||
|
||||
public addAnimateMixer(mixer: AnimationMixer) {
|
||||
this.animateMixer.push(mixer);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
} from './threeRenderService';
|
||||
|
||||
export default class ThreeRender {
|
||||
private threeRenderService: IThreeRenderService;
|
||||
public threeRenderService: IThreeRenderService;
|
||||
constructor(scene: Scene) {
|
||||
const sceneContainer = scene.getServiceContainer();
|
||||
sceneContainer
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue