mirror of https://gitee.com/antv-l7/antv-l7
chore(map): merge master
This commit is contained in:
commit
5d732176bf
|
@ -0,0 +1,97 @@
|
|||
# Contributing to L7
|
||||
|
||||
👍🎉 Welcome to contribute code to L7! 🎉👍
|
||||
|
||||
## Pre-installation
|
||||
|
||||
### Install Yarn
|
||||
|
||||
Since Yarn workspace is used, Yarn needs to be installed first: https://yarnpkg.com/en/docs/install#windows-stable
|
||||
|
||||
### Windows environment configuration
|
||||
|
||||
[The L7 test solution](https://github.com/antvis/L7/blob/master/dev-docs/%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E6%96%B9%E6%A1%88.md) relies on headless-gl, which requires node-gyp [to compile local dependencies](https://github.com/nodejs/node-gyp#on-windows).
|
||||
|
||||
1. Start PowerShell as an administrator
|
||||
2. Run `npm install --global --production windows-build-tools` to install Microsoft's windows-build-tools
|
||||
|
||||
See [other issues](https://github.com/antvis/L7/issues/101) during installation.
|
||||
|
||||
## Install dependencies
|
||||
|
||||
Install dependencies and complete Yarn workspace initialization:
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
```bash
|
||||
copy node_modules/gl/deps/windows/dll/x64/*.dll c:\windows\system32
|
||||
```
|
||||
|
||||
## Run DEMO
|
||||
|
||||
Start each package code change monitoring:
|
||||
```bash
|
||||
yarn watch
|
||||
```
|
||||
|
||||
Start Storybook, it will automatically open `http://localhost:6006/`:
|
||||
```bash
|
||||
yarn storybook
|
||||
```
|
||||
|
||||
## Run test
|
||||
|
||||
Run unit tests:
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
|
||||
Run unit tests and view code coverage:
|
||||
```bash
|
||||
yarn coveralls
|
||||
```
|
||||
|
||||
## Add Lerna package
|
||||
|
||||
Add a new lerna package:
|
||||
```bash
|
||||
lerna create my-pack -y
|
||||
```
|
||||
|
||||
Use ui-lib as a dependency of my-pack:
|
||||
```bash
|
||||
yarn workspace my-pack add ui-lib/1.0.0
|
||||
```
|
||||
|
||||
Add lodash as a dependency of all packages (excluding root)
|
||||
```bash
|
||||
yarn workspaces run add lodash
|
||||
```
|
||||
|
||||
Set typescript to root development dependency:
|
||||
```bash
|
||||
yarn add -W -D typescript jest
|
||||
```
|
||||
|
||||
## Submit code
|
||||
Instead of `git commit`:
|
||||
|
||||
```bash
|
||||
yarn commit
|
||||
```
|
||||
|
||||
## release
|
||||
|
||||
### Set the version number
|
||||
|
||||
```bash
|
||||
yarn run version:prerelease
|
||||
```
|
||||
After setting, you need to commit the code
|
||||
|
||||
### release
|
||||
|
||||
yarn run release
|
|
@ -37,7 +37,7 @@ module.exports = ({ config }) => {
|
|||
}
|
||||
);
|
||||
config.resolve.alias = {
|
||||
'@antv/l7-district': path.resolve(__dirname, '../packages/boundry/src'),
|
||||
'@antv/l7-district': path.resolve(__dirname, '../packages/boundary/src'),
|
||||
}
|
||||
|
||||
config.resolve.extensions.push('.ts', '.tsx', 'css', '.js', '.glsl');
|
||||
|
|
|
@ -40,7 +40,8 @@ scene.addMarkerLayer(markerLayer);
|
|||
- field `string` 聚合统计字段
|
||||
- method `sum| max| min| mean`
|
||||
- element `function` 通过回调函数设置聚合 Marker 的样式,返回 dom 元素
|
||||
参数:feature
|
||||
|
||||
回调函数包含以下参数
|
||||
point_count 默认 聚合元素个数
|
||||
clusterData `Array` 聚合节点的原始数据
|
||||
point_sum 聚合求和 根据 field 和 method 计算
|
||||
|
|
|
@ -41,9 +41,7 @@ scene.addMarkerLayer(markerLayer);
|
|||
- field `string` 聚合统计字段
|
||||
- method `sum| max| min| mean`
|
||||
- element `function` 通过回调函数设置聚合 Marker 的样式,返回 dom 元素
|
||||
|
||||
参数:feature
|
||||
|
||||
回调函数包含以下参数
|
||||
- point_count 默认 聚合元素个数
|
||||
- clusterData `Array` 聚合节点的原始数据
|
||||
- point_sum 聚合求和 根据 field 和 method 计算
|
||||
|
|
|
@ -24,6 +24,8 @@ order: 2
|
|||
- joinBy 数据关联,属性数据如何内部空间数据关联绑定 目前支持 NAME_CHN,adcode 字段连接
|
||||
对照表 `Array [string, string]` 第一个值为空间数据字段,第二个为传入数据字段名
|
||||
- depth 数据显示层级 0:国家级,1:省级,2: 市级,3:线级
|
||||
- showBorder `boolean` 是否显示国界线,默认显示,不建议不显示
|
||||
- simplifyTolerance 数据抽稀容差,默认不抽稀 `boolean | number` 单位为度,一度约 111km,数字越大精度越低。参考设置数据 0.01
|
||||
- label 标注配置项 支持常量,不支持数据映射
|
||||
|
||||
- enable `boolean` 是否显示标注
|
||||
|
@ -91,6 +93,8 @@ District 提供 polygon 数据需要跟用户的属性数据,通过关系字
|
|||
|
||||
#### fillLayer
|
||||
|
||||
图层事件可以通过该属性进行设置
|
||||
|
||||
### 方法
|
||||
|
||||
#### updateData(data, joinBy)
|
||||
|
@ -102,6 +106,10 @@ District 提供 polygon 数据需要跟用户的属性数据,通过关系字
|
|||
- data 需要更新的数据
|
||||
- joinBy 关联字段 可选,如果不设置保持和初始化一致。
|
||||
|
||||
### getFillData
|
||||
|
||||
获取填充数据,可用于绘制独立的边界线
|
||||
|
||||
#### show
|
||||
|
||||
显示图层
|
||||
|
|
|
@ -22,6 +22,7 @@ order: 2
|
|||
- data `Array` 属性数据用于可视化渲染
|
||||
- visible 地图是否可见
|
||||
- joinBy 数据关联,属性数据如何内部空间数据关联绑定 目前支持 NAME_CHN,adcode 字段连接
|
||||
- simplifyTolerance 数据抽稀容差,默认不抽稀 `boolean | number` 单位为度,一度约 111km,数字越大精度越低。参考设置数据 0.01
|
||||
对照表 `Array [string, string]` 第一个值为空间数据字段,第二个为传入数据字段名
|
||||
- depth 数据显示层级 0:国家级,1:省级,2: 市级,3:线级
|
||||
- label 标注配置项 支持常量,不支持数据映射
|
||||
|
@ -34,6 +35,9 @@ order: 2
|
|||
- strokeWidth 文字描边宽度
|
||||
- textAllowOverlap 是否允许文字压盖
|
||||
- opacity 标注透明度
|
||||
- spacing: `number` 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
|
||||
- padding: `[number, number]` 文本相对锚点的偏移量 [x, y]
|
||||
其他包括 text [style 的配置](../layer/point_layer/text#style)
|
||||
|
||||
- fill 填充配置项 支持数据映射
|
||||
- color 图层填充颜色,支持常量和数据映射
|
||||
|
@ -41,14 +45,17 @@ order: 2
|
|||
数据映射
|
||||
- field 填充映射字段
|
||||
- values 映射值,同 color 方法第二个参数数组,回调函数
|
||||
- filter 图层过滤方法,支持常量和数据映射 同 layer.filter 方法
|
||||
数据映射 - field 填充映射字段 - values 回调函数 `false` 返回值将会被过滤掉
|
||||
- style 同 polygonLayer 的 style 方法
|
||||
- activeColor 鼠标滑过高亮颜色
|
||||
- activeColor 鼠标滑过高亮颜色, `string | boolean` 如果设置为 `false`取消高亮
|
||||
- bubble 气泡图
|
||||
- enable `boolean` 是否显示气泡 default false
|
||||
- color 气泡颜色 支持常量、数据映射
|
||||
- size 气泡大小 支持常量、数据映射
|
||||
- shape 气泡形状 支持常量、数据映射
|
||||
- style 气泡图样式 同 PointLayer
|
||||
- showBorder `boolean` 是否显示国界线,默认显示,不建议不显示
|
||||
- stroke 填充描边颜色 `ProvinceLayer, CityLayer, CountyLayer`
|
||||
- strokeWidth 填充描边宽度 `ProvinceLayer, CityLayer, CountyLayer`
|
||||
- autoFit 是否自动缩放到图层范围 `boolean`
|
||||
|
@ -91,6 +98,8 @@ District 提供 polygon 数据需要跟用户的属性数据,通过关系字
|
|||
|
||||
#### fillLayer
|
||||
|
||||
图层事件可以通过该属性进行设置
|
||||
|
||||
### 方法
|
||||
|
||||
#### updateData(data, joinBy)
|
||||
|
@ -102,6 +111,10 @@ District 提供 polygon 数据需要跟用户的属性数据,通过关系字
|
|||
- data 需要更新的数据
|
||||
- joinBy 关联字段 可选,如果不设置保持和初始化一致。
|
||||
|
||||
### getFillData
|
||||
|
||||
获取填充数据,可用于绘制独立的边界线
|
||||
|
||||
#### show
|
||||
|
||||
显示图层
|
||||
|
|
|
@ -70,6 +70,9 @@ DrillDownLayer 提供默认提供通过 Layer 的交互事件,实现上钻下
|
|||
- strokeWidth `number` 描边宽度 `2`
|
||||
- textAllowOverlap: `boolean` 文字是否允许压盖 `true`
|
||||
- opacity `number` 透明度 `1`
|
||||
- spacing: `number` 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
|
||||
- padding: `[number, number]` 文本相对锚点的偏移量 [x, y]
|
||||
其他包括 text [style 的配置](../layer/point_layer/text#style)
|
||||
|
||||
#### bubbleOption
|
||||
|
||||
|
|
|
@ -27,7 +27,21 @@ layer.shape('name','text')
|
|||
### style
|
||||
|
||||
- opacity `number`
|
||||
- textAnchor `string` 文本相对锚点的位置 center|left|right|top|bottom|top-left
|
||||
- textAnchor `string` 文本相对锚点的位置
|
||||
`'right'
|
||||
| 'top-right'
|
||||
| 'left'
|
||||
| 'bottom-right'
|
||||
| 'left'
|
||||
| 'top-left'
|
||||
| 'bottom-left'
|
||||
| 'bottom'
|
||||
| 'bottom-right'
|
||||
| 'bottom-left'
|
||||
| 'top'
|
||||
| 'top-right'
|
||||
| 'top-left'
|
||||
| 'center';`
|
||||
- spacing: `number` 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
|
||||
- padding: `[number, number]` 文本相对锚点的偏移量 [x, y]
|
||||
- stroke: `string`; 描边颜色
|
||||
|
|
|
@ -3,11 +3,30 @@ title: Layer Component
|
|||
order: 2
|
||||
---
|
||||
|
||||
## Layer 类型
|
||||
|
||||
React 各个组件名称和 L7 名称保持一致
|
||||
|
||||
- PointLayer
|
||||
- PolygonLayer
|
||||
- LineLayer
|
||||
- HeatmapLayer
|
||||
- RasterLayer
|
||||
- ImageLayer
|
||||
- CityBuildingLayer
|
||||
|
||||
### 使用方式
|
||||
|
||||
```jsx
|
||||
import { PointLayer } '@antv/l7-react';
|
||||
|
||||
```
|
||||
|
||||
## Layer Props
|
||||
|
||||
| prop name | Type | Default | Description |
|
||||
| ------------- | ------------------------------ | --------------------------------------------------------- | --------------------------------------- |
|
||||
| option | `layer option` | | layer 配置项 |
|
||||
| options | `layer options` | | layer 配置项 |
|
||||
| source | `sourceOption` | | 数据源配置项 |
|
||||
| color | `attributeOption` | | 颜色通道 |
|
||||
| shape | `attributeOption` | | 图层形状属性 |
|
||||
|
@ -17,17 +36,21 @@ order: 2
|
|||
| filter | `Function` | | 图层数据过滤方法 |
|
||||
| select | `boolean` `interaction option` | | 图层选中高亮 |
|
||||
| active | `boolean` `interaction option` | `false` | 图层 hover 高亮 |
|
||||
| animate | `animate Option` | `null` | 图层动画配置 |
|
||||
| onLayerLoaded | `Function` | | 图层添加完成后回调,用于获取 layer 对象 |
|
||||
|
||||
### layer option
|
||||
### layer options
|
||||
|
||||
| prop name | Type | Default | Description |
|
||||
| --------- | --------- | ----------------------- | ---------------------------------------- |
|
||||
| name | `string` | | 图层名字,可根据名称获取 layer |
|
||||
| visible | `boolean` | `true` | 图层是否可见 |
|
||||
| zIndex | `number` | 0 | 图层绘制顺序, |
|
||||
| minZoom | `number` | 0 | 设置 layer 最小可见等级,小于则不显示 |
|
||||
| maxZoom | `number` | 与 map 最大缩放等级一致 | 设置 layerd 的最大可见等级,大于则不显示 |
|
||||
| prop name | Type | Default | Description |
|
||||
| ------------- | --------- | ----------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| name | `string` | | 图层名字,可根据名称获取 layer |
|
||||
| visible | `boolean` | `true` | 图层是否可见 |
|
||||
| zIndex | `number` | 0 | 图层绘制顺序, |
|
||||
| minZoom | `number` | 0 | 设置 layer 最小可见等级,小于则不显示 |
|
||||
| maxZoom | `number` | 与 map 最大缩放等级一致 | 设置 layerd 的最大可见等级,大于则不显示 |
|
||||
| aotoFit | `boolean` | `false` | 是否缩放到图层范围 |
|
||||
| blend | 'string' | 'normal' | 图层元素混合效果 [详情](../layer/layer/#blend) |
|
||||
| pickingBuffer | 'number' | '0' | 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围 {number} default 0 |
|
||||
|
||||
### attribute Option
|
||||
|
||||
|
@ -71,19 +94,25 @@ const scales = {
|
|||
|
||||
### interaction option
|
||||
|
||||
active,select 配置项
|
||||
|
||||
**option**
|
||||
|
||||
- color 设置交互的颜色,指滑过或者选中的
|
||||
|
||||
```jsx
|
||||
<>
|
||||
```
|
||||
|
||||
### 获取 layer 对象
|
||||
|
||||
#### onLayerLoaded
|
||||
|
||||
回调函数获取 layer, scene 对象
|
||||
|
||||
onLayerLoaded=(layer, scene) =>{
|
||||
|
||||
}
|
||||
```javascript
|
||||
onLayerLoaded = (layer, scene) => {};
|
||||
```
|
||||
|
||||
#### Context API
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ import { PointLayer } '@antv/l7-react';
|
|||
| minZoom | `number` | 0 | 设置 layer 最小可见等级,小于则不显示 |
|
||||
| maxZoom | `number` | 与 map 最大缩放等级一致 | 设置 layerd 的最大可见等级,大于则不显示 |
|
||||
| aotoFit | `boolean` | `false` | 是否缩放到图层范围 |
|
||||
| blend | 'string' | 'normal' | 图层元素混合效果 [详情]('../layer/layer/#blend') |
|
||||
| blend | 'string' | 'normal' | 图层元素混合效果 [详情](../layer/layer/#blend) |
|
||||
| pickingBuffer | 'number' | '0' | 图层拾取缓存机制,如 1px 宽度的线鼠标很难拾取(点击)到, 通过设置该参数可扩大拾取的范围 {number} default 0 |
|
||||
|
||||
### attribute Option
|
||||
|
|
|
@ -3,15 +3,23 @@ title: Scene
|
|||
order: 1
|
||||
---
|
||||
|
||||
## 使用
|
||||
|
||||
在 React 版本中 Mapbox 和高德地图作为两个组件封装的。
|
||||
|
||||
```javascript
|
||||
import { MapboxScene, AmapScene } from '@antv/l7-react';
|
||||
```
|
||||
|
||||
## Scene Props
|
||||
|
||||
| prop name | Type | Default | Description |
|
||||
| ------------- | ---------- | ---------- | -------------------------------------- |
|
||||
| style | `Object` | `null` | scene css 样式 |
|
||||
| className | `string` | `null` | 样式名称 |
|
||||
| map | `Object` | `Required` | map option [地图配置项]() |
|
||||
| option | `Object` | `void` | scene option 配置项 [详情](#map-props) |
|
||||
| onSceneLoaded | `Function` | `void` | scene 加载回调函数 |
|
||||
| prop name | Type | Default | Description |
|
||||
| ------------- | -------------- | ---------- | ----------------------------------------- |
|
||||
| style | `Object` | `null` | scene css 样式 |
|
||||
| className | `string` | `null` | 样式名称 |
|
||||
| map | `map option` | `Required` | map option [地图配置项](#map-option) |
|
||||
| option | `scene option` | `void` | scene option 配置项 [详情](#scene-option) |
|
||||
| onSceneLoaded | `Function` | `void` | scene 加载回调函数 |
|
||||
|
||||
### 高德地图场景
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@ import { MapboxScene, AmapScene } from '@antv/l7-react';
|
|||
|
||||
## Scene Props
|
||||
|
||||
| prop name | Type | Default | Description |
|
||||
| ------------- | -------------- | ---------- | -------------------------------------- |
|
||||
| style | `Object` | `null` | scene css 样式 |
|
||||
| className | `string` | `null` | 样式名称 |
|
||||
| map | `map option` | `Required` | map option [地图配置项]() |
|
||||
| option | `scene option` | `void` | scene option 配置项 [详情](#map-props) |
|
||||
| onSceneLoaded | `Function` | `void` | scene 加载回调函数 |
|
||||
| prop name | Type | Default | Description |
|
||||
| ------------- | -------------- | ---------- | ----------------------------------------- |
|
||||
| style | `Object` | `null` | scene css 样式 |
|
||||
| className | `string` | `null` | 样式名称 |
|
||||
| map | `map option` | `Required` | map option [地图配置项](#map-option) |
|
||||
| option | `scene option` | `void` | scene option 配置项 [详情](#scene-option) |
|
||||
| onSceneLoaded | `Function` | `void` | scene 加载回调函数 |
|
||||
|
||||
### 高德地图场景
|
||||
|
||||
|
|
|
@ -134,5 +134,4 @@ const scene = new Scene({
|
|||
});
|
||||
```
|
||||
|
||||
离线,无token使用mapbox [demo](https://codesandbox.io/embed/frosty-architecture-tv6uv?fontsize=14&hidenavigation=1&theme=dark)<br />![image.png](https://cdn.nlark.com/yuque/0/2019/png/104251/1575463410498-0784ce76-743d-4cc4-8d68-964dfd010925.png#align=left&display=inline&height=514&name=image.png&originHeight=514&originWidth=824&size=156914&status=done&style=none&width=824)
|
||||
|
||||
[d离线,无token使用mapbox demo](https://codesandbox.io/embed/frosty-architecture-tv6uv?fontsize=14&hidenavigation=1&theme=dark)<br />
|
||||
|
|
|
@ -132,5 +132,4 @@ const scene = new Scene({
|
|||
});
|
||||
```
|
||||
|
||||
离线,无token使用mapbox [demo](https://codesandbox.io/embed/frosty-architecture-tv6uv?fontsize=14&hidenavigation=1&theme=dark)<br />![image.png](https://cdn.nlark.com/yuque/0/2019/png/104251/1575463410498-0784ce76-743d-4cc4-8d68-964dfd010925.png#align=left&display=inline&height=514&name=image.png&originHeight=514&originWidth=824&size=156914&status=done&style=none&width=824)
|
||||
|
||||
离线,无token使用mapbox [demo](https://codesandbox.io/embed/frosty-architecture-tv6uv?fontsize=14&hidenavigation=1&theme=dark)
|
||||
|
|
|
@ -86,79 +86,6 @@ const scene = new Scene({
|
|||
});
|
||||
|
||||
```
|
||||
|
||||
### React中使用
|
||||
|
||||
React 组件待开发,期待和大家共建l7-react 目前可以暂时以 Submodule 方式使用
|
||||
|
||||
```
|
||||
import { Scene, PolygonLayer } from '@antv/l7';
|
||||
import { AMap } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class AMapExample extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/d2e0e930-fd44-4fca-8872-c1037b0fee7b.json',
|
||||
);
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new AMap({
|
||||
center: [110.19382669582967, 50.258134],
|
||||
pitch: 0,
|
||||
style: 'dark',
|
||||
zoom: 3,
|
||||
token: 'pg.xxx', // 高德或者 Mapbox 的 token
|
||||
}),
|
||||
});
|
||||
const layer = new PolygonLayer({});
|
||||
|
||||
layer
|
||||
.source(await response.json())
|
||||
.size('name', [0, 10000, 50000, 30000, 100000])
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.style({
|
||||
opacity: 0.8,
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
⚠️组件 Unmount 时需要通过 scene.destroy() 手动销毁场景。
|
||||
|
||||
更多React使用 [示例查看](https://github.com/antvis/L7/tree/master/stories)
|
||||
|
||||
## 不同项目使用模板
|
||||
|
||||
不同项目模板在CodeSandbox你可以预览,也可以下载到本地
|
||||
|
|
|
@ -43,6 +43,8 @@ District 支持下面几种图
|
|||
- joinBy 数据关联,属性数据如何内部空间数据关联绑定 目前支持 NAME_CHN,adcode 字段连接
|
||||
对照表 `Array [string, string]` 第一个值为空间数据字段,第二个为传入数据字段名
|
||||
- depth 数据显示层级 0:国家级,1:省级,2: 市级,3:线级
|
||||
- showBorder `boolean` 是否显示国界线,默认显示,不建议不显示
|
||||
- simplifyTolerance 数据抽稀容差,默认不抽稀 `boolean | number` 单位为度,一度约111km,数字越大精度越低。参考设置数据 0.01
|
||||
- label 标注配置项 支持常量,不支持数据映射
|
||||
- enable `boolean` 是否显示标注
|
||||
- color 标注字体颜色 常量
|
||||
|
@ -52,6 +54,9 @@ District 支持下面几种图
|
|||
- strokeWidth 文字描边宽度
|
||||
- textAllowOverlap 是否允许文字压盖
|
||||
- opacity 标注透明度
|
||||
- spacing: `number` 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
|
||||
- padding: `[number, number]` 文本相对锚点的偏移量 [x, y]
|
||||
其他包括 text [style 的配置](../layer/point_layer/text#style)
|
||||
- fill 填充配置项 支持数据映射
|
||||
- color 图层填充颜色,支持常量和数据映射
|
||||
常量:统一设置成一样的颜色
|
||||
|
@ -66,6 +71,7 @@ District 支持下面几种图
|
|||
- size 气泡大小 支持常量、数据映射
|
||||
- shape 气泡形状 支持常量、数据映射
|
||||
- style 气泡图样式 同 PointLayer
|
||||
|
||||
- stroke 填充描边颜色
|
||||
- strokeWidth 填充描边宽度
|
||||
- autoFit 是否自动缩放到图层范围 `boolean`
|
||||
|
@ -101,6 +107,8 @@ District 提供polygon数据需要跟用户的属性数据,通过关系字段
|
|||
行政区划组件每个图层有多个子图层组成,如标注层,国界线、省界线等等,
|
||||
|
||||
#### fillLayer
|
||||
|
||||
图层事件可以通过该属性进行设置
|
||||
|
||||
### 方法
|
||||
|
||||
|
@ -111,6 +119,10 @@ District 提供polygon数据需要跟用户的属性数据,通过关系字段
|
|||
- data 需要更新的数据
|
||||
- joinBy 关联字段 可选,如果不设置保持和初始化一致。
|
||||
|
||||
### getFillData
|
||||
|
||||
获取填充数据,可用于绘制独立的边界线
|
||||
|
||||
#### show
|
||||
|
||||
显示图层
|
||||
|
|
|
@ -19,7 +19,6 @@ import { WorldLayer } from '@antv/l7-district';
|
|||
<script src="https://unpkg.com/@antv/l7-district"></script>
|
||||
</head>
|
||||
```
|
||||
⚠️⚠️⚠️ District 相关配置和接口还在完善中,你可以适用体验,某些配置和接口可能会进行调整
|
||||
|
||||
## 简介
|
||||
|
||||
|
@ -41,6 +40,8 @@ District 支持下面几种图
|
|||
- visible 地图是否可见
|
||||
- joinBy 数据关联,属性数据如何内部空间数据关联绑定 目前支持 NAME_CHN,adcode 字段连接
|
||||
对照表 `Array [string, string]` 第一个值为空间数据字段,第二个为传入数据字段名
|
||||
- showBorder `boolean` 是否显示国界线,默认显示,不建议不显示
|
||||
- simplifyTolerance 数据抽稀容差,默认不抽稀 `boolean | number` 单位为度,一度约111km,数字越大精度越低。参考设置数据 0.01
|
||||
- depth 数据显示层级 0:国家级,1:省级,2: 市级,3:线级
|
||||
- label 标注配置项 支持常量,不支持数据映射
|
||||
- enable `boolean` 是否显示标注
|
||||
|
@ -51,19 +52,31 @@ District 支持下面几种图
|
|||
- strokeWidth 文字描边宽度
|
||||
- textAllowOverlap 是否允许文字压盖
|
||||
- opacity 标注透明度
|
||||
- spacing: `number` 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
|
||||
- padding: `[number, number]` 文本相对锚点的偏移量 [x, y]
|
||||
其他包括 text [style 的配置](../layer/point_layer/text#style)
|
||||
- fill 填充配置项 支持数据映射
|
||||
- color 图层填充颜色,支持常量和数据映射
|
||||
常量:统一设置成一样的颜色
|
||||
数据映射
|
||||
- field 填充映射字段
|
||||
- values 映射值,同color方法第二个参数数组,回调函数
|
||||
- filter 图层过滤方法,支持常量和数据映射 同layer.filter方法
|
||||
数据映射
|
||||
- field 填充映射字段
|
||||
- values 回调函数 `false` 返回值将会被过滤掉
|
||||
- style 同 polygonLayer的style方法
|
||||
- activeColor 鼠标滑过高亮颜色
|
||||
- activeColor 鼠标滑过高亮颜色, `string | boolean` 如果设置为 `false`取消高亮
|
||||
|
||||
- bubble 气泡图
|
||||
- enable `boolean` 是否显示气泡 default false
|
||||
- color 气泡颜色 支持常量、数据映射
|
||||
- size 气泡大小 支持常量、数据映射
|
||||
- shape 气泡形状 支持常量、数据映射
|
||||
- filter 图层过滤方法,支持常量和数据映射 同layer.filter方法
|
||||
数据映射
|
||||
- field 填充映射字段
|
||||
- values 回调函数 `false` 返回值将会被过滤掉
|
||||
- style 气泡图样式 同 PointLayer
|
||||
- stroke 填充描边颜色 `ProvinceLayer, CityLayer, CountyLayer`
|
||||
- strokeWidth 填充描边宽度 `ProvinceLayer, CityLayer, CountyLayer`
|
||||
|
@ -102,6 +115,7 @@ District 提供polygon数据需要跟用户的属性数据,通过关系字段
|
|||
行政区划组件每个图层有多个子图层组成,如标注层,国界线、省界线等等,
|
||||
|
||||
#### fillLayer
|
||||
图层事件可以通过该属性进行设置
|
||||
|
||||
### 方法
|
||||
|
||||
|
@ -112,6 +126,10 @@ District 提供polygon数据需要跟用户的属性数据,通过关系字段
|
|||
- data 需要更新的数据
|
||||
- joinBy 关联字段 可选,如果不设置保持和初始化一致。
|
||||
|
||||
### getFillData
|
||||
|
||||
获取填充数据,可用于绘制独立的边界线
|
||||
|
||||
#### show
|
||||
|
||||
显示图层
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
import { Scene } from '@antv/l7';
|
||||
import { CountryLayer } from '@antv/l7-district';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Mapbox({
|
||||
center: [ 116.2825, 39.9 ],
|
||||
pitch: 0,
|
||||
style: 'blank',
|
||||
zoom: 3,
|
||||
minZoom: 0,
|
||||
maxZoom: 10
|
||||
})
|
||||
});
|
||||
const attachMapContainer = document.createElement('div');
|
||||
attachMapContainer.id = 'attach';
|
||||
attachMapContainer.style.cssText = `position: absolute;
|
||||
height: 125px;
|
||||
width: 98px;
|
||||
right: 50px;
|
||||
bottom: 20px;
|
||||
border: 1px solid #333;`;
|
||||
document.getElementById('map').parentElement.append(attachMapContainer);
|
||||
|
||||
scene.on('loaded', () => {
|
||||
new CountryLayer(scene, {
|
||||
data: [],
|
||||
joinBy: [ 'NAME_CHN', 'name' ],
|
||||
depth: 1,
|
||||
provinceStroke: '#783D2D',
|
||||
cityStroke: '#EBCCB4',
|
||||
cityStrokeWidth: 1,
|
||||
label: {
|
||||
enable: false
|
||||
},
|
||||
fill: {
|
||||
color: {
|
||||
field: 'NAME_CHN',
|
||||
values: [
|
||||
'#feedde',
|
||||
'#fdd0a2',
|
||||
'#fdae6b',
|
||||
'#fd8d3c',
|
||||
'#e6550d',
|
||||
'#a63603'
|
||||
]
|
||||
}
|
||||
},
|
||||
popup: {
|
||||
enable: true,
|
||||
Html: props => {
|
||||
return `<span>${props.NAME_CHN}</span>`;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 添加附图,附图需要和主图保持一致
|
||||
|
||||
const scene2 = new Scene({
|
||||
id: 'attach',
|
||||
logoVisible: false,
|
||||
map: new Mapbox({
|
||||
center: [ 113.60540108435657, 12.833692637803168 ],
|
||||
pitch: 0,
|
||||
style: 'blank',
|
||||
zoom: 1.93,
|
||||
minZoom: 0,
|
||||
maxZoom: 3,
|
||||
interactive: false
|
||||
})
|
||||
});
|
||||
scene2.on('loaded', () => {
|
||||
new CountryLayer(scene2, {
|
||||
data: [],
|
||||
label: {
|
||||
enable: false
|
||||
},
|
||||
popup: {
|
||||
enable: false
|
||||
},
|
||||
autoFit: false,
|
||||
depth: 1,
|
||||
fill: {
|
||||
color: {
|
||||
field: 'NAME_CHN',
|
||||
values: [
|
||||
'#feedde',
|
||||
'#fdd0a2',
|
||||
'#fdae6b',
|
||||
'#fd8d3c',
|
||||
'#e6550d',
|
||||
'#a63603'
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,106 @@
|
|||
import { Scene } from '@antv/l7';
|
||||
import { ProvinceLayer, CountryLayer } from '@antv/l7-district';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
async function initMap() {
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Mapbox({
|
||||
center: [ 109.803, 19.347 ],
|
||||
pitch: 0,
|
||||
style: 'blank',
|
||||
zoom: 7,
|
||||
minZoom: 6,
|
||||
maxZoom: 11
|
||||
})
|
||||
});
|
||||
const attachMapContainer = document.createElement('div');
|
||||
attachMapContainer.id = 'attach';
|
||||
attachMapContainer.style.cssText = `position: absolute;
|
||||
height: 125px;
|
||||
width: 98px;
|
||||
right: 50px;
|
||||
bottom: 20px;
|
||||
border: 1px solid #333;`;
|
||||
document.getElementById('map').parentElement.append(attachMapContainer);
|
||||
scene.on('loaded', () => {
|
||||
new ProvinceLayer(scene, {
|
||||
data: [],
|
||||
geoDataLevel: 1,
|
||||
autoFit: false,
|
||||
joinBy: [ 'adcode', 'code' ],
|
||||
adcode: [ '460000' ],
|
||||
depth: 2,
|
||||
stroke: '#aaa',
|
||||
label: {
|
||||
enable: false,
|
||||
field: 'NAME_CHN',
|
||||
textAllowOverlap: false
|
||||
},
|
||||
fill: {
|
||||
color: '#A3d7FF'
|
||||
},
|
||||
popup: {
|
||||
enable: false,
|
||||
Html: props => {
|
||||
return `<span>${props.NAME_CHN}:</span><span>${props.pop}</span>`;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const scene2 = new Scene({
|
||||
id: 'attach',
|
||||
logoVisible: false,
|
||||
map: new Mapbox({
|
||||
center: [ 113.60540108435657, 12.833692637803168 ],
|
||||
pitch: 0,
|
||||
style: 'blank',
|
||||
zoom: 1.93,
|
||||
// zoom: 3,
|
||||
minZoom: 0,
|
||||
maxZoom: 3,
|
||||
interactive: false
|
||||
})
|
||||
});
|
||||
scene2.on('loaded', () => {
|
||||
new CountryLayer(scene2, {
|
||||
data: [],
|
||||
label: {
|
||||
enable: false
|
||||
},
|
||||
popup: {
|
||||
enable: false
|
||||
},
|
||||
autoFit: false,
|
||||
provinceStroke: '#aaa',
|
||||
depth: 1,
|
||||
fill: {
|
||||
color: '#A3d7FF'
|
||||
}
|
||||
});
|
||||
new ProvinceLayer(scene2, {
|
||||
data: [],
|
||||
autoFit: false,
|
||||
adcode: [ '460000' ],
|
||||
depth: 2,
|
||||
zIndex: 2,
|
||||
stroke: '#aaa',
|
||||
strokeWidth: 0.1,
|
||||
label: {
|
||||
enable: false,
|
||||
field: 'NAME_CHN',
|
||||
textAllowOverlap: false
|
||||
},
|
||||
fill: {
|
||||
color: '#A3d7ff'
|
||||
},
|
||||
popup: {
|
||||
enable: false,
|
||||
Html: props => {
|
||||
return `<span>${props.NAME_CHN}:</span><span>${props.pop}</span>`;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
initMap();
|
|
@ -28,6 +28,16 @@
|
|||
"filename": "county.js",
|
||||
"title": "中国县地图",
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_8e1672/afts/img/A*iVwLSpIf_ckAAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "attach_map.js",
|
||||
"title": "中国地图附图",
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_855bab/afts/img/A*bGX-Tbw5uVAAAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "hainan.js",
|
||||
"title": "海南省地图",
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_855bab/afts/img/A*nHOTQ61hFbYAAAAAAAAAAABkARQnAQ"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ class Province extends React.Component {
|
|||
const { province } = this.state;
|
||||
this.provinceLayer = new ProvinceLayer(scene, {
|
||||
adcode: ['230000'],
|
||||
depth: 3,
|
||||
depth: 1,
|
||||
label: {
|
||||
field: 'NAME_CHN',
|
||||
textAllowOverlap: false,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { Scene, HeatmapLayer } from '@antv/l7';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
import { GaodeMap } from '@antv/l7-maps';
|
||||
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Mapbox({
|
||||
map: new GaodeMap({
|
||||
style: 'dark',
|
||||
pitch: 58.5,
|
||||
center: [ 111.8759, 30.6942 ],
|
||||
|
|
|
@ -7,7 +7,7 @@ const World = React.memo(function Map() {
|
|||
React.useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/68dc6756-627b-4e9e-a5ba-e834f6ba48f8.json'
|
||||
'https://gw.alipayobjects.com/os/antvdemo/assets/data/world.geo.json'
|
||||
);
|
||||
const data = await response.json();
|
||||
setData(data);
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import { PolygonLayer, LineLayer, Scene } from '@antv/l7';
|
||||
import { GaodeMap } from '@antv/l7-maps';
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
style: 'light',
|
||||
pitch: 0,
|
||||
center: [ 118.7368, 32.0560 ],
|
||||
zoom: 9
|
||||
})
|
||||
});
|
||||
scene.on('loaded', () => {
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/91247d10-585b-4406-b1e2-93b001e3a0e4.json'
|
||||
)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
const filllayer = new PolygonLayer({
|
||||
name: 'fill'
|
||||
})
|
||||
.source(data)
|
||||
.shape('fill')
|
||||
.color('unit_price', [ '#f0f9e8', '#ccebc5', '#a8ddb5', '#7bccc4', '#43a2ca', '#0868ac' ])
|
||||
.style({
|
||||
opacity: 1
|
||||
});
|
||||
const linelayer = new LineLayer({
|
||||
zIndex: 1,
|
||||
name: 'line'
|
||||
})
|
||||
.source(data)
|
||||
.shape('line')
|
||||
.size(0.5)
|
||||
.color('#fff')
|
||||
.style({
|
||||
opacity: 0.5
|
||||
});
|
||||
const hightLayer = new LineLayer({
|
||||
zIndex: 4, // 设置显示层级
|
||||
name: 'hightlight'
|
||||
})
|
||||
.source({
|
||||
type: 'FeatureCollection',
|
||||
features: [ ]
|
||||
})
|
||||
.shape('line')
|
||||
.size(2)
|
||||
.color('red')
|
||||
.style({
|
||||
opacity: 1
|
||||
});
|
||||
scene.addLayer(filllayer);
|
||||
scene.addLayer(linelayer);
|
||||
scene.addLayer(hightLayer);
|
||||
filllayer.on('click', feature => {
|
||||
console.log(feature);
|
||||
hightLayer.setData({
|
||||
type: 'FeatureCollection',
|
||||
features: [ feature.feature ]
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
import { Scale, Zoom, Scene } from '@antv/l7';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new Mapbox({
|
||||
style: 'light',
|
||||
pitch: 0,
|
||||
center: [ 107.054293, 35.246265 ],
|
||||
zoom: 4.056
|
||||
})
|
||||
});
|
||||
scene.on('loaded', () => {
|
||||
const zoomControl = new Zoom();
|
||||
const scaleControl = new Scale();
|
||||
scene.addControl(zoomControl);
|
||||
scene.addControl(scaleControl);
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"title": {
|
||||
"zh": "地图",
|
||||
"en": "Category"
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "amap.js",
|
||||
"title": "高德底图组件",
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*yXzQRYcGTyoAAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "mapbox.js",
|
||||
"title": "MapBox底图组件",
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/antv_site/afts/img/A*_SIYR50bbcoAAAAAAAAAAABkARQnAQ"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Layer
|
||||
order: 2
|
||||
---
|
||||
How to use the map control
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: 图层
|
||||
order: 2
|
||||
---
|
||||
图层初始化与交互
|
|
@ -21,6 +21,6 @@ exports.onCreateWebpackConfig = ({ getConfig }) => {
|
|||
'@antv/l7-utils': path.resolve(__dirname, 'packages/utils/src'),
|
||||
'@antv/l7-react': path.resolve(__dirname, 'packages/react/src'),
|
||||
'@antv/l7-draw': path.resolve(__dirname, 'packages/draw/src'),
|
||||
'@antv/l7-district': path.resolve(__dirname, 'packages/boundry/src')
|
||||
'@antv/l7-district': path.resolve(__dirname, 'packages/boundary/src')
|
||||
};
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"message": "chore: publish"
|
||||
}
|
||||
},
|
||||
"version": "2.2.14",
|
||||
"version": "2.2.21",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"publishConfig": {
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// import { WorldLayer } from '@antv/l7-district';
|
||||
describe('baseLayer', () => {
|
||||
it('set option', () => {
|
||||
const option = {
|
||||
adcode: [],
|
||||
data: [
|
||||
{
|
||||
name: 1,
|
||||
code: 2,
|
||||
},
|
||||
{
|
||||
name: 2,
|
||||
code: 3,
|
||||
},
|
||||
{
|
||||
name: 3,
|
||||
code: 4,
|
||||
},
|
||||
],
|
||||
};
|
||||
// @ts-ignore
|
||||
// const layer = new WorldLayer(null, option);
|
||||
// layer.setOption({
|
||||
// data: [
|
||||
// {
|
||||
// name: 1,
|
||||
// code: 4,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
// // @ts-ignore
|
||||
// expect(layer.options.data.length).toBe(1);
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-district",
|
||||
"version": "2.2.14",
|
||||
"version": "2.2.21",
|
||||
"description": "L7 district moudules",
|
||||
"keywords": [],
|
||||
"author": "thinkinggis <lzx199065@gmail.com>",
|
||||
|
@ -34,7 +34,7 @@
|
|||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/l7": "2.2.14",
|
||||
"@antv/l7": "2.2.21",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@turf/circle": "^6.0.1",
|
||||
"@turf/distance": "^6.0.1",
|
||||
|
@ -44,7 +44,8 @@
|
|||
"eventemitter3": "^4.0.0",
|
||||
"geobuf": "^3.0.1",
|
||||
"lodash": "^4.6.2",
|
||||
"pbf": "^3.2.1"
|
||||
"pbf": "^3.2.1",
|
||||
"simplify-geojson": "^1.0.3"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/antvis/L7/issues"
|
||||
|
@ -55,5 +56,6 @@
|
|||
"postcss-url": "^8.0.0",
|
||||
"rollup": "^2.3.3",
|
||||
"rollup-plugin-less": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0"
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
// tslint:disable-next-line:no-submodule-imports
|
||||
import merge from 'lodash/merge';
|
||||
|
||||
let DataLevel = 2;
|
||||
let DataLevel = 2; // d
|
||||
const dataLevel2: { [key: string]: any } = {
|
||||
world: {
|
||||
fill: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/e66cdd3f-cd41-4533-9746-d8fdbe0a0056.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/ad26cd25-96ea-40fd-935d-7e21a5c08893.bin',
|
||||
},
|
||||
line: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/f1b0fd97-ac90-4adb-b99c-01709e0e52c8.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/62f61f5f-cca7-4137-845d-13c8f9969664.bin',
|
||||
},
|
||||
label: {
|
||||
type: 'pbf',
|
||||
|
@ -127,17 +127,17 @@ const dataLevel1: { [key: string]: any } = {
|
|||
fill: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/56cb34eb-cf61-4512-a6f3-fe4a45a7b1a3.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/35bb8365-1926-471c-b357-db2c02ff3a81.bin',
|
||||
},
|
||||
line: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/76914518-e04c-42c9-8c4b-1ae71aabb024.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/8ec671c3-a4f9-4fdf-8e88-85d2ab1d8930.bin',
|
||||
},
|
||||
label: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/90c51eb3-04d7-402f-bd05-95e4bd27dd62.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/90c51eb3-04d7-402f-bd05-95e4bd27dd62.bin',
|
||||
parser: {
|
||||
type: 'geojson',
|
||||
},
|
||||
|
@ -145,7 +145,7 @@ const dataLevel1: { [key: string]: any } = {
|
|||
nationalBoundaries: {
|
||||
type: 'json',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
|
||||
},
|
||||
},
|
||||
country: {
|
||||
|
@ -154,29 +154,29 @@ const dataLevel1: { [key: string]: any } = {
|
|||
fill: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/70ec087e-c48a-4b76-8825-6452f17bae7a.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/380370e0-76aa-4240-8874-5732de77e71d.bin',
|
||||
},
|
||||
line: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/70ec087e-c48a-4b76-8825-6452f17bae7a.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/70ec087e-c48a-4b76-8825-6452f17bae7a.bin',
|
||||
},
|
||||
provinceLine: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
|
||||
},
|
||||
label: {
|
||||
type: 'json',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/36832a45-68f8-4b51-b006-9dec71f92a23.json',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/36832a45-68f8-4b51-b006-9dec71f92a23.json',
|
||||
},
|
||||
},
|
||||
2: {
|
||||
fill: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/561e2cfe-9460-42d1-a2f8-3fd2e1274c52.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/feeb1f06-11c6-4495-84c9-f41ea6f77123.bin',
|
||||
},
|
||||
line: {
|
||||
type: 'pbf',
|
||||
|
@ -198,43 +198,43 @@ const dataLevel1: { [key: string]: any } = {
|
|||
fill: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/516b2703-d692-44e6-80dd-b3f5df0186e7.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/24a9ee83-2be1-4fc1-b187-769ac939269d.bin',
|
||||
},
|
||||
line: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
|
||||
},
|
||||
countryLine: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
|
||||
},
|
||||
cityLine: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/8bfbfe7e-bd0e-4bbe-84d8-629f4dc7abc4.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/8bfbfe7e-bd0e-4bbe-84d8-629f4dc7abc4.bin',
|
||||
},
|
||||
provinceLine: {
|
||||
type: 'pbf',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
|
||||
},
|
||||
},
|
||||
nationalBoundaries: {
|
||||
type: 'json',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
|
||||
},
|
||||
nationalBoundaries2: {
|
||||
type: 'json',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/f2189cc4-662b-4358-8573-36f0f918b7ca.json',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/f2189cc4-662b-4358-8573-36f0f918b7ca.json',
|
||||
},
|
||||
island: {
|
||||
type: 'json',
|
||||
url:
|
||||
'//gw.alipayobjects.com/os/bmw-prod/fe49b393-1147-4769-94ed-70471f4ff15d.json',
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/fe49b393-1147-4769-94ed-70471f4ff15d.json',
|
||||
},
|
||||
},
|
||||
},
|
|
@ -17,6 +17,8 @@ import isObject from 'lodash/isObject';
|
|||
import mergeWith from 'lodash/mergeWith';
|
||||
// @ts-ignore
|
||||
import Pbf from 'pbf';
|
||||
// @ts-ignore
|
||||
import simplify from 'simplify-geojson';
|
||||
import { setDataLevel } from '../config';
|
||||
import { AttributeType, IDistrictLayerOption } from './interface';
|
||||
|
||||
|
@ -56,7 +58,11 @@ export default class BaseLayer extends EventEmitter {
|
|||
}
|
||||
|
||||
public setOption(newOption: { [key: string]: any }) {
|
||||
this.options = mergeWith(this.options, newOption);
|
||||
this.options = mergeWith(this.options, newOption, mergeCustomizer);
|
||||
}
|
||||
|
||||
public getFillData() {
|
||||
return this.fillData;
|
||||
}
|
||||
|
||||
public updateData(
|
||||
|
@ -85,7 +91,10 @@ export default class BaseLayer extends EventEmitter {
|
|||
protected async fetchData(data: { url: any; type: string }) {
|
||||
if (data.type === 'pbf') {
|
||||
const buffer = await (await fetch(data.url)).arrayBuffer();
|
||||
const geojson = geobuf.decode(new Pbf(buffer));
|
||||
let geojson = geobuf.decode(new Pbf(buffer));
|
||||
if (this.options.simplifyTolerance !== false) {
|
||||
geojson = simplify(geojson, this.options.simplifyTolerance);
|
||||
}
|
||||
return geojson;
|
||||
} else {
|
||||
return isObject(data.url) ? data.url : (await fetch(data.url)).json();
|
||||
|
@ -99,15 +108,18 @@ export default class BaseLayer extends EventEmitter {
|
|||
depth: 1,
|
||||
adcode: [],
|
||||
joinBy: ['name', 'name'],
|
||||
simplifyTolerance: false,
|
||||
label: {
|
||||
enable: true,
|
||||
color: '#000',
|
||||
field: 'name',
|
||||
size: 8,
|
||||
size: 10,
|
||||
stroke: '#fff',
|
||||
strokeWidth: 2,
|
||||
textAllowOverlap: true,
|
||||
opacity: 1,
|
||||
textOffset: [0, 0],
|
||||
padding: [5, 5],
|
||||
},
|
||||
bubble: {
|
||||
enable: false,
|
||||
|
@ -126,16 +138,19 @@ export default class BaseLayer extends EventEmitter {
|
|||
style: {
|
||||
opacity: 1.0,
|
||||
},
|
||||
activeColor: 'rgba(0,0,255,0.3)',
|
||||
activeColor: false,
|
||||
},
|
||||
autoFit: true,
|
||||
showBorder: true,
|
||||
stroke: '#bdbdbd',
|
||||
strokeVisible: true,
|
||||
strokeWidth: 0.6,
|
||||
cityStroke: '#636363',
|
||||
cityStrokeWidth: 0.6,
|
||||
countyStrokeWidth: 0.6,
|
||||
provinceStrokeWidth: 0.6,
|
||||
provinceStroke: '#f0f0f0',
|
||||
provinceStrokeVisible: true,
|
||||
countyStroke: '#525252',
|
||||
coastlineStroke: '#4190da',
|
||||
coastlineWidth: 0.6,
|
||||
|
@ -176,18 +191,20 @@ export default class BaseLayer extends EventEmitter {
|
|||
],
|
||||
});
|
||||
this.setLayerAttribute(fillLayer, 'color', fill.color as AttributeType);
|
||||
this.setLayerAttribute(fillLayer, 'filter', fill.filter as AttributeType);
|
||||
if (fill.scale && isObject(fill.color)) {
|
||||
fillLayer.scale('color', {
|
||||
type: fill.scale,
|
||||
field: fill.color.field as string,
|
||||
});
|
||||
}
|
||||
fillLayer
|
||||
.shape('fill')
|
||||
.active({
|
||||
fillLayer.shape('fill').style(fill.style);
|
||||
|
||||
if (fill.activeColor) {
|
||||
fillLayer.active({
|
||||
color: fill.activeColor as string,
|
||||
})
|
||||
.style(fill.style);
|
||||
});
|
||||
}
|
||||
this.fillLayer = fillLayer;
|
||||
this.layers.push(fillLayer);
|
||||
this.scene.addLayer(fillLayer);
|
||||
|
@ -256,6 +273,11 @@ export default class BaseLayer extends EventEmitter {
|
|||
this.setLayerAttribute(bubbleLayer, 'color', bubble.color as AttributeType);
|
||||
this.setLayerAttribute(bubbleLayer, 'size', bubble.size as AttributeType);
|
||||
this.setLayerAttribute(bubbleLayer, 'shape', bubble.shape as AttributeType);
|
||||
this.setLayerAttribute(
|
||||
bubbleLayer,
|
||||
'filter',
|
||||
bubble.filter as AttributeType,
|
||||
);
|
||||
if (bubble.scale) {
|
||||
bubbleLayer.scale(bubble.scale.field, {
|
||||
type: bubble.scale.type,
|
||||
|
@ -271,7 +293,7 @@ export default class BaseLayer extends EventEmitter {
|
|||
protected addLabel(labelData: any, type: string = 'json') {
|
||||
const { label, zIndex, visible } = this.options;
|
||||
const labelLayer = new PointLayer({
|
||||
zIndex: zIndex + 0.4,
|
||||
zIndex: zIndex + 5,
|
||||
visible,
|
||||
})
|
||||
.source(labelData, {
|
||||
|
@ -280,15 +302,11 @@ export default class BaseLayer extends EventEmitter {
|
|||
coordinates: 'center',
|
||||
},
|
||||
})
|
||||
.color(label.color as StyleAttrField)
|
||||
.shape(label.field as StyleAttrField, 'text')
|
||||
.size(10)
|
||||
.style({
|
||||
opacity: label.opacity,
|
||||
stroke: label.stroke,
|
||||
strokeWidth: label.strokeWidth,
|
||||
textAllowOverlap: label.textAllowOverlap,
|
||||
});
|
||||
.style(label);
|
||||
this.setLayerAttribute(labelLayer, 'color', label.color as AttributeType);
|
||||
this.setLayerAttribute(labelLayer, 'size', label.size as AttributeType);
|
||||
this.setLayerAttribute(labelLayer, 'filter', label.filter);
|
||||
return labelLayer;
|
||||
}
|
||||
|
||||
|
@ -325,12 +343,17 @@ export default class BaseLayer extends EventEmitter {
|
|||
|
||||
private setLayerAttribute(
|
||||
layer: ILayer,
|
||||
type: 'color' | 'size' | 'shape',
|
||||
attr: AttributeType,
|
||||
type: 'color' | 'size' | 'shape' | 'filter',
|
||||
attr: AttributeType | undefined,
|
||||
) {
|
||||
if (!attr) {
|
||||
return;
|
||||
}
|
||||
if (isObject(attr)) {
|
||||
// @ts-ignore
|
||||
layer[type](attr.field, attr.values);
|
||||
} else {
|
||||
// @ts-ignore
|
||||
layer[type](attr);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { LineLayer, PointLayer, Scene, StyleAttrField } from '@antv/l7';
|
||||
import { AttributeType, LineLayer, PointLayer, Scene } from '@antv/l7';
|
||||
import { getDataConfig } from '../index';
|
||||
import BaseLayer from './baseLayer';
|
||||
import { IDistrictLayerOption } from './interface';
|
||||
|
@ -6,20 +6,20 @@ import { IDistrictLayerOption } from './interface';
|
|||
export default class CountryLayer extends BaseLayer {
|
||||
constructor(scene: Scene, option: Partial<IDistrictLayerOption> = {}) {
|
||||
super(scene, option);
|
||||
const { depth } = this.options;
|
||||
const { depth, showBorder } = this.options;
|
||||
this.addProvinceFill();
|
||||
this.addProvinceLabel();
|
||||
const countryConfig = getDataConfig(this.options.geoDataLevel).country.CHN[
|
||||
depth
|
||||
];
|
||||
|
||||
this.addProvinceLine(countryConfig.provinceLine);
|
||||
|
||||
if (depth === 2 * 1) {
|
||||
this.addCityBorder(countryConfig.fill);
|
||||
}
|
||||
if (depth === 3 * 1) {
|
||||
this.addCountyBorder(countryConfig.fill);
|
||||
if (showBorder) {
|
||||
this.addProvinceLine(countryConfig.provinceLine);
|
||||
if (depth === 2 * 1) {
|
||||
this.addCityBorder(countryConfig.fill);
|
||||
}
|
||||
if (depth === 3 * 1) {
|
||||
this.addCountyBorder(countryConfig.fill);
|
||||
}
|
||||
}
|
||||
}
|
||||
protected async addProvinceFill() {
|
||||
|
@ -127,6 +127,7 @@ export default class CountryLayer extends BaseLayer {
|
|||
chinaNationalWidth,
|
||||
coastlineStroke,
|
||||
coastlineWidth,
|
||||
showBorder,
|
||||
stroke,
|
||||
strokeWidth,
|
||||
visible,
|
||||
|
@ -135,7 +136,7 @@ export default class CountryLayer extends BaseLayer {
|
|||
// 添加国界线
|
||||
const lineLayer = new LineLayer({
|
||||
zIndex: zIndex + 0.1,
|
||||
visible,
|
||||
visible: visible && showBorder,
|
||||
})
|
||||
.source(boundaries)
|
||||
.size('type', (v: string) => {
|
||||
|
@ -152,11 +153,11 @@ export default class CountryLayer extends BaseLayer {
|
|||
.shape('line')
|
||||
.color('type', (v: string) => {
|
||||
if (v === '3') {
|
||||
return provinceStroke;
|
||||
return provinceStroke; // 省界
|
||||
} else if (v === '2') {
|
||||
return coastlineStroke;
|
||||
return coastlineStroke; // 海岸线
|
||||
} else if (v === '0') {
|
||||
return chinaNationalStroke;
|
||||
return chinaNationalStroke; // 中国国界线
|
||||
} else {
|
||||
return '#fff';
|
||||
}
|
||||
|
@ -164,7 +165,7 @@ export default class CountryLayer extends BaseLayer {
|
|||
// 添加未定国界
|
||||
const lineLayer2 = new LineLayer({
|
||||
zIndex: zIndex + 0.1,
|
||||
visible,
|
||||
visible: visible && showBorder,
|
||||
})
|
||||
.source(boundaries2)
|
||||
.size(chinaNationalWidth)
|
||||
|
@ -178,7 +179,7 @@ export default class CountryLayer extends BaseLayer {
|
|||
// 添加澳门香港界限
|
||||
const lineLayer3 = new LineLayer({
|
||||
zIndex: zIndex + 0.1,
|
||||
visible,
|
||||
visible: visible && showBorder,
|
||||
})
|
||||
.source(boundaries3)
|
||||
.size(provinceStrokeWidth)
|
||||
|
@ -262,9 +263,9 @@ export default class CountryLayer extends BaseLayer {
|
|||
coordinates: 'center',
|
||||
},
|
||||
})
|
||||
.color(label.color as StyleAttrField)
|
||||
.color(label.color as AttributeType)
|
||||
.shape('name', 'text')
|
||||
.size(10)
|
||||
.size(label.size as AttributeType)
|
||||
.style({
|
||||
opacity: label.opacity,
|
||||
stroke: label.stroke,
|
|
@ -184,7 +184,7 @@ export default class DrillDownLayer {
|
|||
}
|
||||
|
||||
private getLayerOption(type: 'province' | 'city' | 'county') {
|
||||
const { joinBy, label, bubble, fill, popup, province } = this.options;
|
||||
const { joinBy, label, bubble, fill, popup, geoDataLevel } = this.options;
|
||||
const datatype = (type + 'Data') as
|
||||
| 'provinceData'
|
||||
| 'cityData'
|
||||
|
@ -196,6 +196,7 @@ export default class DrillDownLayer {
|
|||
bubble,
|
||||
fill,
|
||||
popup,
|
||||
geoDataLevel,
|
||||
...this.options[type],
|
||||
};
|
||||
}
|
|
@ -4,15 +4,37 @@ import {
|
|||
StyleAttributeField,
|
||||
StyleAttributeOption,
|
||||
} from '@antv/l7';
|
||||
export type anchorType =
|
||||
| 'right'
|
||||
| 'top-right'
|
||||
| 'left'
|
||||
| 'bottom-right'
|
||||
| 'left'
|
||||
| 'top-left'
|
||||
| 'bottom-left'
|
||||
| 'bottom'
|
||||
| 'bottom-right'
|
||||
| 'bottom-left'
|
||||
| 'top'
|
||||
| 'top-right'
|
||||
| 'top-left'
|
||||
| 'center';
|
||||
export interface ILabelOption {
|
||||
enable: boolean;
|
||||
color: string;
|
||||
color: AttributeType;
|
||||
field: string;
|
||||
size: number;
|
||||
size: AttributeType;
|
||||
stroke: string;
|
||||
strokeWidth: number;
|
||||
textAllowOverlap: boolean;
|
||||
padding: [number, number];
|
||||
strokeOpacity: number;
|
||||
fontWeight: number;
|
||||
spacing: number;
|
||||
textAnchor: anchorType;
|
||||
textOffset: [number, number];
|
||||
opacity: number;
|
||||
filter: AttributeType;
|
||||
}
|
||||
|
||||
export interface IAttributeOption {
|
||||
|
@ -36,7 +58,8 @@ export interface IFillOptions {
|
|||
color: AttributeType;
|
||||
values: StyleAttributeOption;
|
||||
style: any;
|
||||
activeColor: string;
|
||||
activeColor: string | boolean;
|
||||
filter: AttributeType;
|
||||
}
|
||||
export type TriggeEventType =
|
||||
| 'mousemove'
|
||||
|
@ -60,6 +83,7 @@ export interface IBubbleOption {
|
|||
shape: AttributeType;
|
||||
size: AttributeType;
|
||||
color: AttributeType;
|
||||
filter: AttributeType;
|
||||
scale: {
|
||||
field: string;
|
||||
type: ScaleTypeName;
|
||||
|
@ -78,14 +102,18 @@ export interface IDistrictLayerOption {
|
|||
data?: Array<{ [key: string]: any }>;
|
||||
joinBy: [string, string];
|
||||
adcode: adcodeType;
|
||||
simplifyTolerance: number | boolean;
|
||||
depth: 0 | 1 | 2 | 3;
|
||||
label: Partial<ILabelOption>;
|
||||
bubble: Partial<IBubbleOption>;
|
||||
fill: Partial<IFillOptions>;
|
||||
showBorder: boolean;
|
||||
autoFit: boolean;
|
||||
stroke: string;
|
||||
strokeVisible: boolean;
|
||||
strokeWidth: number;
|
||||
provinceStroke: string;
|
||||
provinceStrokeVisible: boolean;
|
||||
cityStroke: string;
|
||||
provinceStrokeWidth: number;
|
||||
cityStrokeWidth: number;
|
||||
|
@ -107,6 +135,7 @@ interface IDrawOption {
|
|||
}
|
||||
export interface IDrillDownOption {
|
||||
drillDepth: 0 | 1 | 2;
|
||||
geoDataLevel: 1 | 2;
|
||||
customTrigger: boolean;
|
||||
drillDownTriggerEvent: TriggeEventType;
|
||||
drillUpTriggerEvent: TriggeEventType & DrillUpTriggeEventType;
|
|
@ -34,6 +34,7 @@ export default class ProvinceLayer extends BaseLayer {
|
|||
this.hide();
|
||||
return;
|
||||
}
|
||||
const { label, showBorder } = this.options;
|
||||
this.setOption({ adcode });
|
||||
const fillData = this.filterData(this.fillRawData, adcode);
|
||||
const lineData = this.filterData(this.lineRawData, adcode);
|
||||
|
@ -49,8 +50,13 @@ export default class ProvinceLayer extends BaseLayer {
|
|||
}
|
||||
this.fillData = fillData;
|
||||
this.updateData(newData, joinByField);
|
||||
this.lineLayer.setData(lineData);
|
||||
this.labelLayer.setData(labelData);
|
||||
if (showBorder) {
|
||||
this.lineLayer.setData(lineData);
|
||||
}
|
||||
if (label.enable) {
|
||||
this.labelLayer.setData(labelData);
|
||||
}
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
|
@ -96,7 +102,8 @@ export default class ProvinceLayer extends BaseLayer {
|
|||
return features;
|
||||
}
|
||||
private async addProvinceFillLayer() {
|
||||
const { depth, adcode } = this.options as IProvinceLayerOption;
|
||||
const { depth, adcode, label, showBorder } = this
|
||||
.options as IProvinceLayerOption;
|
||||
const countryConfig = getDataConfig(this.options.geoDataLevel).country.CHN[
|
||||
depth
|
||||
];
|
||||
|
@ -109,12 +116,17 @@ export default class ProvinceLayer extends BaseLayer {
|
|||
};
|
||||
});
|
||||
const data = this.filterData(fillData, adcode);
|
||||
this.fillData = data;
|
||||
const labelData = this.filterLabelData(this.labelRawData, adcode);
|
||||
this.fillRawData = fillData;
|
||||
this.addFillLayer(data);
|
||||
this.addLabelLayer(labelData);
|
||||
if (label.enable) {
|
||||
this.addLabelLayer(labelData);
|
||||
}
|
||||
this.lineRawData = fillData;
|
||||
this.addFillLine(data);
|
||||
if (showBorder) {
|
||||
this.addFillLine(data);
|
||||
}
|
||||
}
|
||||
|
||||
private async addProvinceLineLayer() {
|
|
@ -14,7 +14,9 @@ export default class WorldLayer extends BaseLayer {
|
|||
super(scene, option);
|
||||
this.loadData().then(([fillData, lineData, fillLabel]) => {
|
||||
this.addFillLayer(fillData);
|
||||
this.addFillLine(lineData);
|
||||
if (this.options.showBorder) {
|
||||
this.addFillLine(lineData);
|
||||
}
|
||||
if (this.options.label?.enable) {
|
||||
this.addLabelLayer(fillLabel, 'json');
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
import BaseLayer from '../src/layer/baseLayer';
|
||||
describe('baseLayer', () => {
|
||||
it('set option', () => {
|
||||
const option = {
|
||||
adcode: [],
|
||||
};
|
||||
// const layer = new BaseLayer(null, option);
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-component",
|
||||
"version": "2.2.14",
|
||||
"version": "2.2.21",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -24,14 +24,14 @@
|
|||
"author": "lzxue",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/l7-core": "2.2.14",
|
||||
"@antv/l7-utils": "2.2.14",
|
||||
"@antv/l7-core": "2.2.21",
|
||||
"@antv/l7-utils": "2.2.21",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"eventemitter3": "^4.0.0",
|
||||
"inversify": "^5.0.1",
|
||||
"load-styles": "^2.0.0"
|
||||
},
|
||||
"gitHead": "532ade40831b35b04a677b351d092e54c00613d8",
|
||||
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-core",
|
||||
"version": "2.2.14",
|
||||
"version": "2.2.21",
|
||||
"description": "",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -23,7 +23,7 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/async-hook": "^2.1.0",
|
||||
"@antv/l7-utils": "2.2.14",
|
||||
"@antv/l7-utils": "2.2.21",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@mapbox/tiny-sdf": "^1.1.1",
|
||||
"ajv": "^6.10.2",
|
||||
|
@ -46,7 +46,7 @@
|
|||
"@types/lodash": "^4.14.138",
|
||||
"@types/viewport-mercator-project": "^6.1.0"
|
||||
},
|
||||
"gitHead": "532ade40831b35b04a677b351d092e54c00613d8",
|
||||
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ export interface IICONMap {
|
|||
export interface IIconService {
|
||||
canvasHeight: number;
|
||||
on(event: string, fn: EventEmitter.ListenerFn, context?: any): this;
|
||||
off(event: string, fn: EventEmitter.ListenerFn, context?: any): this;
|
||||
init(): void;
|
||||
addImage(id: string, image: IImage): void;
|
||||
hasImage(id: string): boolean;
|
||||
|
|
|
@ -57,7 +57,9 @@ export interface ILayerModel {
|
|||
getDefaultStyle(): unknown;
|
||||
getAnimateUniforms(): IModelUniform;
|
||||
buildModels(): IModel[];
|
||||
initModels(): IModel[];
|
||||
needUpdate(): boolean;
|
||||
clearModels(): void;
|
||||
}
|
||||
export interface IModelUniform {
|
||||
[key: string]: IUniform;
|
||||
|
@ -82,6 +84,7 @@ export interface ILayer {
|
|||
zIndex: number;
|
||||
plugins: ILayerPlugin[];
|
||||
layerModelNeedUpdate: boolean;
|
||||
styleNeedUpdate: boolean;
|
||||
layerModel: ILayerModel;
|
||||
dataState: IDataState; // 数据流状态
|
||||
pickedFeatureID: number | null;
|
||||
|
@ -117,6 +120,7 @@ export interface ILayer {
|
|||
prepareBuildModel(): void;
|
||||
renderModels(): void;
|
||||
buildModels(): void;
|
||||
rebuildModels(): void;
|
||||
buildLayerModel(
|
||||
options: ILayerModelInitializationOptions &
|
||||
Partial<IModelInitializationOptions>,
|
||||
|
@ -154,6 +158,8 @@ export interface ILayer {
|
|||
setBlend(type: keyof typeof BlendType): void;
|
||||
// animate(field: string, option: any): ILayer;
|
||||
render(): ILayer;
|
||||
clear(): void;
|
||||
clearModels(): void;
|
||||
destroy(): void;
|
||||
source(data: any, option?: ISourceCFG): ILayer;
|
||||
setData(data: any, option?: ISourceCFG): ILayer;
|
||||
|
|
|
@ -92,7 +92,6 @@ export default class LayerService implements ILayerService {
|
|||
this.layers.sort((pre: ILayer, next: ILayer) => {
|
||||
return pre.zIndex - next.zIndex;
|
||||
});
|
||||
this.renderLayers();
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
|
|
|
@ -18,6 +18,10 @@ import {
|
|||
} from './IStyleAttributeService';
|
||||
import StyleAttribute from './StyleAttribute';
|
||||
|
||||
function sleep(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
const bytesPerElementMap = {
|
||||
[gl.FLOAT]: 4,
|
||||
[gl.UNSIGNED_BYTE]: 1,
|
||||
|
@ -216,27 +220,18 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
indicesForCurrentFeature.forEach((i) => {
|
||||
indices.push(i + verticesNum);
|
||||
});
|
||||
verticesForCurrentFeature.forEach((index) => {
|
||||
vertices.push(index);
|
||||
});
|
||||
// fix Maximum call stack size exceeded https://stackoverflow.com/questions/22123769/rangeerror-maximum-call-stack-size-exceeded-why
|
||||
if (normalsForCurrentFeature) {
|
||||
normalsForCurrentFeature.forEach((normal) => {
|
||||
normals.push(normal);
|
||||
});
|
||||
}
|
||||
size = vertexSize;
|
||||
const verticesNumForCurrentFeature =
|
||||
verticesForCurrentFeature.length / vertexSize;
|
||||
|
||||
// 记录三角化结果,用于后续精确更新指定 feature
|
||||
this.featureLayout.sizePerElement = size;
|
||||
this.featureLayout.elements.push({
|
||||
featureIdx,
|
||||
vertices: verticesForCurrentFeature,
|
||||
normals: normalsForCurrentFeature as number[],
|
||||
offset: verticesNum,
|
||||
});
|
||||
// this.featureLayout.sizePerElement = size;
|
||||
// this.featureLayout.elements.push({
|
||||
// featureIdx,
|
||||
// vertices: verticesForCurrentFeature,
|
||||
// normals: normalsForCurrentFeature as number[],
|
||||
// offset: verticesNum,
|
||||
// });
|
||||
|
||||
verticesNum += verticesNumForCurrentFeature;
|
||||
// 根据 position 顶点生成其他顶点数据
|
||||
|
@ -245,21 +240,20 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
vertexIdx < verticesNumForCurrentFeature;
|
||||
vertexIdx++
|
||||
) {
|
||||
const normal =
|
||||
normalsForCurrentFeature?.slice(vertexIdx * 3, vertexIdx * 3 + 3) ||
|
||||
[];
|
||||
const vertice = verticesForCurrentFeature.slice(
|
||||
vertexIdx * vertexSize,
|
||||
vertexIdx * vertexSize + vertexSize,
|
||||
);
|
||||
descriptors.forEach((descriptor, attributeIdx) => {
|
||||
if (descriptor && descriptor.update) {
|
||||
const normal =
|
||||
normalsForCurrentFeature?.slice(
|
||||
vertexIdx * 3,
|
||||
vertexIdx * 3 + 3,
|
||||
) || [];
|
||||
(descriptor.buffer.data as number[]).push(
|
||||
...descriptor.update(
|
||||
feature,
|
||||
featureIdx,
|
||||
verticesForCurrentFeature.slice(
|
||||
vertexIdx * vertexSize,
|
||||
vertexIdx * vertexSize + vertexSize,
|
||||
),
|
||||
vertice,
|
||||
vertexIdx, // 当前顶点所在feature索引
|
||||
normal,
|
||||
// TODO: 传入顶点索引 vertexIdx
|
||||
|
@ -313,6 +307,8 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
attribute.vertexAttribute.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
this.attributesAndIndices.elements.destroy();
|
||||
this.attributes = [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-draw",
|
||||
"version": "2.2.14",
|
||||
"version": "2.2.21",
|
||||
"description": "L7 Draw moudules",
|
||||
"keywords": [],
|
||||
"author": "thinkinggis <lzx199065@gmail.com>",
|
||||
|
@ -35,7 +35,7 @@
|
|||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/l7": "2.2.14",
|
||||
"@antv/l7": "2.2.21",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@turf/circle": "^6.0.1",
|
||||
"@turf/distance": "^6.0.1",
|
||||
|
@ -55,5 +55,5 @@
|
|||
"rollup": "^2.3.3",
|
||||
"rollup-plugin-less": "^1.1.2"
|
||||
},
|
||||
"gitHead": "532ade40831b35b04a677b351d092e54c00613d8"
|
||||
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0"
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* @Author: lzxue
|
||||
* @Date: 2020-04-03 19:24:16
|
||||
* @Last Modified by: lzxue
|
||||
* @Last Modified time: 2020-05-13 11:58:01
|
||||
* @Last Modified time: 2020-06-22 17:33:14
|
||||
*/
|
||||
import { Control, DOM, IControlOption, PositionType, Scene } from '@antv/l7';
|
||||
import './css/draw.less';
|
||||
|
|
|
@ -243,6 +243,7 @@ export default abstract class DrawFeature extends DrawMode {
|
|||
if (this.drawStatus === 'DrawSelected') {
|
||||
this.clear();
|
||||
this.source.removeFeature(this.currentFeature as Feature);
|
||||
|
||||
this.normalLayer.update(this.source.data);
|
||||
this.drawLayer.disableSelect();
|
||||
this.selectMode.disable();
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.8.3/polyfill.min.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
||||
|
||||
<script src="../dist/l7.js"></script>
|
||||
<script src="../dist/l7-dev.js"></script>
|
||||
<script>
|
||||
console.log(L7);
|
||||
const scene = new L7.Scene({
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<!-- <script src="https://cdn.jsdelivr.net/npm/symbol-es6@0.1.2/symbol-es6.min.js"></script> -->
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
||||
|
||||
<script src="../dist/l7.js"></script>
|
||||
<script src="../dist/l7-dev.js"></script>
|
||||
<script>
|
||||
console.log(L7);
|
||||
const scene = new L7.Scene({
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<div id="map"></div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.8.3/polyfill.min.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.js"></script>
|
||||
<script src="../dist/l7.js"></script>
|
||||
<script src="../dist/l7-dev.js"></script>
|
||||
<script>
|
||||
const data =
|
||||
{"type":"FeatureCollection","features":[
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7",
|
||||
"version": "2.2.14",
|
||||
"version": "2.2.21",
|
||||
"description": "A Large-scale WebGL-powered Geospatial Data Visualization",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -24,15 +24,15 @@
|
|||
"author": "antv",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@antv/l7-component": "2.2.14",
|
||||
"@antv/l7-core": "2.2.14",
|
||||
"@antv/l7-layers": "2.2.14",
|
||||
"@antv/l7-maps": "2.2.14",
|
||||
"@antv/l7-scene": "2.2.14",
|
||||
"@antv/l7-utils": "2.2.14",
|
||||
"@antv/l7-component": "2.2.21",
|
||||
"@antv/l7-core": "2.2.21",
|
||||
"@antv/l7-layers": "2.2.21",
|
||||
"@antv/l7-maps": "2.2.21",
|
||||
"@antv/l7-scene": "2.2.21",
|
||||
"@antv/l7-utils": "2.2.21",
|
||||
"@babel/runtime": "^7.7.7"
|
||||
},
|
||||
"gitHead": "532ade40831b35b04a677b351d092e54c00613d8",
|
||||
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
const version = '2.2.14';
|
||||
const version = '2.2.21';
|
||||
export { version };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@antv/l7-layers",
|
||||
"version": "2.2.14",
|
||||
"version": "2.2.21",
|
||||
"description": "L7's collection of built-in layers",
|
||||
"main": "lib/index.js",
|
||||
"module": "es/index.js",
|
||||
|
@ -23,9 +23,9 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@antv/async-hook": "^2.1.0",
|
||||
"@antv/l7-core": "2.2.14",
|
||||
"@antv/l7-source": "2.2.14",
|
||||
"@antv/l7-utils": "2.2.14",
|
||||
"@antv/l7-core": "2.2.21",
|
||||
"@antv/l7-source": "2.2.21",
|
||||
"@antv/l7-utils": "2.2.21",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@mapbox/martini": "^0.2.0",
|
||||
"@turf/meta": "^6.0.2",
|
||||
|
@ -34,6 +34,7 @@
|
|||
"d3-scale": "2",
|
||||
"earcut": "^2.2.1",
|
||||
"eventemitter3": "^4.0.0",
|
||||
"extrude-polyline": "^1.0.6",
|
||||
"gl-matrix": "^3.1.0",
|
||||
"gl-vec2": "^1.3.0",
|
||||
"inversify": "^5.0.1",
|
||||
|
@ -50,7 +51,7 @@
|
|||
"@types/gl-matrix": "^2.4.5",
|
||||
"@types/lodash": "^4.14.138"
|
||||
},
|
||||
"gitHead": "532ade40831b35b04a677b351d092e54c00613d8",
|
||||
"gitHead": "20154fe30d512024b03ac5e40f77731bc0580bb0",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@ export default class CityBuildingLayer extends BaseLayer {
|
|||
public type: string = 'PolygonLayer';
|
||||
public buildModels() {
|
||||
this.layerModel = new CityBuildModel(this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
this.models = this.layerModel.buildModels();
|
||||
}
|
||||
public setLight(t: number) {
|
||||
|
|
|
@ -29,7 +29,7 @@ export default class CityBuildModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
public initModels(): IModel[] {
|
||||
this.startModelAnimate();
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -70,6 +70,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
public layerModelNeedUpdate: boolean = false;
|
||||
public pickedFeatureID: number | null = null;
|
||||
public selectedFeatureID: number | null = null;
|
||||
public styleNeedUpdate: boolean = false;
|
||||
|
||||
public dataState: IDataState = {
|
||||
dataSourceNeedUpdate: false,
|
||||
|
@ -469,6 +470,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
|
||||
if (this.container) {
|
||||
this.updateLayerConfig(this.rawConfig);
|
||||
this.styleNeedUpdate = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -495,7 +497,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
// } else {
|
||||
// this.renderModels();
|
||||
// }
|
||||
|
||||
this.renderModels();
|
||||
// this.multiPassRenderer.render();
|
||||
// this.renderModels();
|
||||
|
@ -708,7 +709,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
// 清除所有属性以及关联的 vao
|
||||
this.styleAttributeService.clearAllAttributes();
|
||||
// 销毁所有 model
|
||||
this.models.forEach((model) => model.destroy());
|
||||
// this.models.forEach((model) => model.destroy());
|
||||
|
||||
this.hooks.afterDestroy.call();
|
||||
|
||||
|
@ -725,7 +726,10 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
public clear() {
|
||||
this.styleAttributeService.clearAllAttributes();
|
||||
// 销毁所有 model
|
||||
}
|
||||
public clearModels() {
|
||||
this.models.forEach((model) => model.destroy());
|
||||
this.layerModel.clearModels();
|
||||
}
|
||||
|
||||
public isDirty() {
|
||||
|
@ -886,6 +890,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
public buildModels() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public rebuildModels() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public renderModels() {
|
||||
if (this.layerModelNeedUpdate && this.layerModel) {
|
||||
|
|
|
@ -97,6 +97,12 @@ export default class BaseModel<ChildLayerStyleOptions = {}>
|
|||
public buildModels(): IModel[] {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public initModels(): IModel[] {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
public clearModels() {
|
||||
return;
|
||||
}
|
||||
public getAttribute(): {
|
||||
attributes: {
|
||||
[attributeName: string]: IAttribute;
|
||||
|
|
|
@ -2,8 +2,8 @@ import { IEncodeFeature } from '@antv/l7-core';
|
|||
import { aProjectFlat, lngLatToMeters } from '@antv/l7-utils';
|
||||
import earcut from 'earcut';
|
||||
import { vec3 } from 'gl-matrix';
|
||||
import ExtrudePolyline from '../utils/extrude_polyline';
|
||||
import { calculteCentroid } from '../utils/geo';
|
||||
import getNormals from '../utils/polylineNormal';
|
||||
import extrudePolygon, {
|
||||
extrude_PolygonNormal,
|
||||
fillPolygon,
|
||||
|
@ -74,11 +74,16 @@ export function LineTriangulation(feature: IEncodeFeature) {
|
|||
if (Array.isArray(path[0][0])) {
|
||||
path = coordinates[0] as number[][];
|
||||
}
|
||||
const line = getNormals(path as number[][], false, 0);
|
||||
const line = new ExtrudePolyline({
|
||||
dash: true,
|
||||
join: 'bevel', //
|
||||
});
|
||||
|
||||
const linebuffer = line.extrude(path as number[][]);
|
||||
return {
|
||||
vertices: line.attrPos, // [ x,y,z, distance, miter,total ]
|
||||
indices: line.attrIndex,
|
||||
normals: line.normals,
|
||||
vertices: linebuffer.positions, // [ x,y,z, distance, miter,total ]
|
||||
indices: linebuffer.indices,
|
||||
normals: linebuffer.normals,
|
||||
size: 6,
|
||||
};
|
||||
}
|
||||
|
@ -87,7 +92,6 @@ export function polygonTriangulation(feature: IEncodeFeature) {
|
|||
const { coordinates } = feature;
|
||||
const flattengeo = earcut.flatten(coordinates as number[][][]);
|
||||
const { vertices, dimensions, holes } = flattengeo;
|
||||
|
||||
return {
|
||||
indices: earcut(vertices, holes, dimensions),
|
||||
vertices,
|
||||
|
|
|
@ -10,6 +10,9 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
|
|||
public buildModels() {
|
||||
const shape = this.getModelType();
|
||||
this.layerModel = new HeatMapModels[shape](this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
this.models = this.layerModel.buildModels();
|
||||
}
|
||||
public renderModels() {
|
||||
|
|
|
@ -32,6 +32,10 @@ export default class GridModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -33,6 +33,10 @@ export default class Grid3DModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -45,6 +45,9 @@ export default class HeatMapModel extends BaseModel {
|
|||
});
|
||||
this.drawIntensityMode();
|
||||
});
|
||||
if (this.layer.styleNeedUpdate) {
|
||||
this.updateColorTexture();
|
||||
}
|
||||
this.shapeType === 'heatmap' ? this.drawColorMode() : this.draw3DHeatMap();
|
||||
}
|
||||
|
||||
|
@ -52,7 +55,7 @@ export default class HeatMapModel extends BaseModel {
|
|||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
public initModels(): IModel[] {
|
||||
const {
|
||||
createFramebuffer,
|
||||
clear,
|
||||
|
@ -92,20 +95,15 @@ export default class HeatMapModel extends BaseModel {
|
|||
depth: false,
|
||||
});
|
||||
|
||||
// 初始化颜色纹理
|
||||
this.colorTexture = createTexture2D({
|
||||
data: new Uint8Array(imageData.data),
|
||||
width: imageData.width,
|
||||
height: imageData.height,
|
||||
wrapS: gl.CLAMP_TO_EDGE,
|
||||
wrapT: gl.CLAMP_TO_EDGE,
|
||||
min: gl.NEAREST,
|
||||
mag: gl.NEAREST,
|
||||
flipY: false,
|
||||
});
|
||||
this.updateColorTexture();
|
||||
|
||||
return [this.intensityModel, this.colorModel];
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return this.initModels();
|
||||
}
|
||||
|
||||
protected registerBuiltinAttributes() {
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'dir',
|
||||
|
@ -335,4 +333,29 @@ export default class HeatMapModel extends BaseModel {
|
|||
}),
|
||||
});
|
||||
}
|
||||
private updateStyle() {
|
||||
this.updateColorTexture();
|
||||
}
|
||||
|
||||
private updateColorTexture() {
|
||||
const { createTexture2D } = this.rendererService;
|
||||
if (this.texture) {
|
||||
this.texture.destroy();
|
||||
}
|
||||
|
||||
const {
|
||||
rampColors,
|
||||
} = this.layer.getLayerConfig() as IHeatMapLayerStyleOptions;
|
||||
const imageData = generateColorRamp(rampColors as IColorRamp);
|
||||
this.colorTexture = createTexture2D({
|
||||
data: new Uint8Array(imageData.data),
|
||||
width: imageData.width,
|
||||
height: imageData.height,
|
||||
wrapS: gl.CLAMP_TO_EDGE,
|
||||
wrapT: gl.CLAMP_TO_EDGE,
|
||||
min: gl.NEAREST,
|
||||
mag: gl.NEAREST,
|
||||
flipY: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@ export default class HexagonModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -8,6 +8,9 @@ export default class ImageLayer extends BaseLayer<IImageLayerStyleOptions> {
|
|||
public buildModels() {
|
||||
const modelType = this.getModelType();
|
||||
this.layerModel = new ImageModels[modelType](this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
this.models = this.layerModel.buildModels();
|
||||
}
|
||||
protected getConfigSchema() {
|
||||
|
|
|
@ -31,7 +31,7 @@ export default class ImageModel extends BaseModel {
|
|||
u_texture: this.texture,
|
||||
};
|
||||
}
|
||||
public buildModels() {
|
||||
public initModels() {
|
||||
const source = this.layer.getSource();
|
||||
const { createTexture2D } = this.rendererService;
|
||||
this.texture = createTexture2D({
|
||||
|
@ -58,6 +58,9 @@ export default class ImageModel extends BaseModel {
|
|||
}),
|
||||
];
|
||||
}
|
||||
public buildModels() {
|
||||
return this.initModels();
|
||||
}
|
||||
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
|
|
|
@ -8,6 +8,9 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
|
|||
public buildModels() {
|
||||
const shape = this.getModelType();
|
||||
this.layerModel = new LineModels[shape](this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
this.models = this.layerModel.buildModels();
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ export default class ArcModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -41,6 +41,10 @@ export default class Arc3DModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -43,6 +43,10 @@ export default class GreatCircleModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -41,6 +41,10 @@ export default class LineModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
@ -48,7 +52,9 @@ export default class LineModel extends BaseModel {
|
|||
vertexShader: line_vert,
|
||||
fragmentShader: line_frag,
|
||||
triangulation: LineTriangulation,
|
||||
primitive: gl.TRIANGLES,
|
||||
blend: this.getBlend(),
|
||||
depth: { enable: false },
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
@ -66,7 +72,7 @@ export default class LineModel extends BaseModel {
|
|||
name: 'a_Distance',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
usage: gl.STATIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
|
@ -88,7 +94,7 @@ export default class LineModel extends BaseModel {
|
|||
name: 'a_Total_Distance',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
usage: gl.STATIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
|
@ -141,6 +147,7 @@ export default class LineModel extends BaseModel {
|
|||
type: gl.FLOAT,
|
||||
},
|
||||
size: 3,
|
||||
// @ts-ignore
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
|
@ -160,7 +167,7 @@ export default class LineModel extends BaseModel {
|
|||
name: 'a_Miter',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
usage: gl.STATIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
|
|
|
@ -24,8 +24,8 @@ uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ];
|
|||
void main() {
|
||||
gl_FragColor = v_color;
|
||||
// anti-alias
|
||||
// float blur = 1.- smoothstep(u_blur, 1., length(v_normal.xy));
|
||||
gl_FragColor.a *= u_opacity;
|
||||
float blur = 1.- smoothstep(u_blur, 1., length(v_normal.xy));
|
||||
gl_FragColor.a *= u_opacity * blur ;
|
||||
|
||||
if(u_aimate.x == Animate) {
|
||||
float alpha =1.0 - fract( mod(1.0- v_distance_ratio, u_aimate.z)* (1.0/ u_aimate.z) + u_time / u_aimate.y);
|
||||
|
|
|
@ -39,6 +39,9 @@ export default class DataMappingPlugin implements ILayerPlugin {
|
|||
|
||||
// remapping before render
|
||||
layer.hooks.beforeRender.tap('DataMappingPlugin', () => {
|
||||
if (layer.layerModelNeedUpdate) {
|
||||
return;
|
||||
}
|
||||
const attributes = styleAttributeService.getLayerStyleAttributes() || [];
|
||||
const filter = styleAttributeService.getLayerStyleAttribute('filter');
|
||||
const { dataArray } = layer.getSource().data;
|
||||
|
|
|
@ -72,14 +72,18 @@ export default class FeatureScalePlugin implements ILayerPlugin {
|
|||
this.scaleOptions = layer.getScaleOptions();
|
||||
const attributes = styleAttributeService.getLayerStyleAttributes();
|
||||
const { dataArray } = layer.getSource().data;
|
||||
if (dataArray.length === 0) {
|
||||
return;
|
||||
}
|
||||
// if (dataArray.length === 0) {
|
||||
// return;
|
||||
// }
|
||||
this.caculateScalesForAttributes(attributes || [], dataArray);
|
||||
layer.layerModelNeedUpdate = true;
|
||||
return true;
|
||||
});
|
||||
|
||||
layer.hooks.beforeRender.tap('FeatureScalePlugin', () => {
|
||||
if (layer.layerModelNeedUpdate) {
|
||||
return;
|
||||
}
|
||||
this.scaleOptions = layer.getScaleOptions();
|
||||
const attributes = styleAttributeService.getLayerStyleAttributes();
|
||||
if (attributes) {
|
||||
|
|
|
@ -11,11 +11,14 @@ export default class LayerModelPlugin implements ILayerPlugin {
|
|||
layer.prepareBuildModel();
|
||||
// 初始化 Model
|
||||
layer.buildModels();
|
||||
layer.styleNeedUpdate = false;
|
||||
});
|
||||
|
||||
layer.hooks.beforeRenderData.tap('DataSourcePlugin', () => {
|
||||
// 更新Model 配置项
|
||||
layer.prepareBuildModel();
|
||||
|
||||
layer.clearModels();
|
||||
// 初始化 Model
|
||||
layer.buildModels();
|
||||
layer.layerModelNeedUpdate = false;
|
||||
|
|
|
@ -25,10 +25,10 @@ export default class UpdateStyleAttributePlugin implements ILayerPlugin {
|
|||
this.initStyleAttribute(layer, { styleAttributeService });
|
||||
});
|
||||
|
||||
layer.hooks.beforeRenderData.tap('styleAttributeService', () => {
|
||||
layer.layerModelNeedUpdate = true;
|
||||
return true;
|
||||
});
|
||||
// layer.hooks.beforeRenderData.tap('styleAttributeService', () => {
|
||||
// // layer.layerModelNeedUpdate = true;
|
||||
// return true;
|
||||
// });
|
||||
|
||||
layer.hooks.beforeRender.tap('UpdateStyleAttributePlugin', () => {
|
||||
if (layer.layerModelNeedUpdate) {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import PointLayer from '../';
|
||||
import { Mapbox } from '../../../../maps/src';
|
||||
import { Scene } from '../../../../scene/src';
|
||||
describe('pointLayer', () => {
|
||||
const el = document.createElement('div');
|
||||
el.id = 'test-div-id';
|
||||
el.style.width = '500px';
|
||||
el.style.height = '500px';
|
||||
document.querySelector('body')?.appendChild(el);
|
||||
|
||||
const pointdata = {
|
||||
type: 'FeatureCollection',
|
||||
features: [],
|
||||
};
|
||||
it('init', () => {
|
||||
const scene = new Scene({
|
||||
id: 'test-div-id',
|
||||
map: new Mapbox({
|
||||
style: 'dark',
|
||||
center: [110.19382669582967, 30.258134],
|
||||
pitch: 0,
|
||||
zoom: 3,
|
||||
}),
|
||||
});
|
||||
scene.on('loaded', () => {
|
||||
const layer = new PointLayer()
|
||||
.source(pointdata)
|
||||
.color('red')
|
||||
.shape('circle')
|
||||
.size(5);
|
||||
scene.addLayer(layer);
|
||||
scene.render();
|
||||
layer.setData({
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: [99.84374999999999, 32.54681317351514],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(layer.getEncodedData().length).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -11,6 +11,9 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
public buildModels() {
|
||||
const modelType = this.getModelType();
|
||||
this.layerModel = new PointModels[modelType](this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
this.models = this.layerModel.buildModels();
|
||||
}
|
||||
protected getConfigSchema() {
|
||||
|
|
|
@ -14,6 +14,9 @@ export default class ExtrudeModel extends BaseModel {
|
|||
u_opacity: opacity || 1.0,
|
||||
};
|
||||
}
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
|
|
|
@ -54,6 +54,9 @@ export default class FillModel extends BaseModel {
|
|||
PointFillTriangulation,
|
||||
);
|
||||
}
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -29,7 +29,7 @@ export default class IconeModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
public initModels(): IModel[] {
|
||||
this.initIconFontGlyphs();
|
||||
this.registerBuiltinAttributes();
|
||||
this.updateTexture();
|
||||
|
|
|
@ -30,13 +30,18 @@ export default class ImageModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
public initModels(): IModel[] {
|
||||
this.registerBuiltinAttributes();
|
||||
this.updateTexture();
|
||||
this.iconService.on('imageUpdate', () => {
|
||||
this.updateTexture();
|
||||
this.layer.render(); // TODO 调用全局render
|
||||
});
|
||||
this.iconService.on('imageUpdate', this.updateTexture);
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public clearModels() {
|
||||
this.iconService.off('imageUpdate', this.updateTexture);
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'pointImage',
|
||||
|
@ -49,7 +54,6 @@ export default class ImageModel extends BaseModel {
|
|||
}),
|
||||
];
|
||||
}
|
||||
|
||||
protected registerBuiltinAttributes() {
|
||||
// point layer size;
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
|
@ -105,8 +109,11 @@ export default class ImageModel extends BaseModel {
|
|||
});
|
||||
}
|
||||
|
||||
private updateTexture() {
|
||||
private updateTexture = () => {
|
||||
const { createTexture2D } = this.rendererService;
|
||||
if (this.texture) {
|
||||
this.texture.destroy();
|
||||
}
|
||||
this.texture = createTexture2D({
|
||||
data: this.iconService.getCanvas(),
|
||||
mag: gl.LINEAR,
|
||||
|
@ -114,5 +121,6 @@ export default class ImageModel extends BaseModel {
|
|||
width: 1024,
|
||||
height: this.iconService.canvasHeight || 128,
|
||||
});
|
||||
}
|
||||
this.layer.render();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -45,6 +45,11 @@ export default class NormalModel extends BaseModel {
|
|||
u_stroke_color: rgb2arr(stroke),
|
||||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -14,6 +14,7 @@ import BaseModel from '../../core/BaseModel';
|
|||
import CollisionIndex from '../../utils/collision-index';
|
||||
import { calculteCentroid } from '../../utils/geo';
|
||||
import {
|
||||
anchorType,
|
||||
getGlyphQuads,
|
||||
IGlyphQuad,
|
||||
shapeText,
|
||||
|
@ -22,7 +23,7 @@ import textFrag from '../shaders/text_frag.glsl';
|
|||
import textVert from '../shaders/text_vert.glsl';
|
||||
interface IPointTextLayerStyleOptions {
|
||||
opacity: number;
|
||||
textAnchor: string;
|
||||
textAnchor: anchorType;
|
||||
spacing: number;
|
||||
padding: [number, number];
|
||||
stroke: string;
|
||||
|
@ -140,12 +141,8 @@ export default class TextModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
this.layer.on('remapping', () => {
|
||||
this.initGlyph();
|
||||
this.updateTexture();
|
||||
this.reBuildModel();
|
||||
});
|
||||
public initModels(): IModel[] {
|
||||
this.layer.on('remapping', this.buildModels);
|
||||
this.extent = this.textExtent();
|
||||
const {
|
||||
textAnchor = 'center',
|
||||
|
@ -155,6 +152,10 @@ export default class TextModel extends BaseModel {
|
|||
textAnchor,
|
||||
textAllowOverlap,
|
||||
};
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels = () => {
|
||||
this.initGlyph();
|
||||
this.updateTexture();
|
||||
this.filterGlyphs();
|
||||
|
@ -168,7 +169,7 @@ export default class TextModel extends BaseModel {
|
|||
blend: this.getBlend(),
|
||||
}),
|
||||
];
|
||||
}
|
||||
};
|
||||
public needUpdate() {
|
||||
const {
|
||||
textAllowOverlap = false,
|
||||
|
@ -188,6 +189,9 @@ export default class TextModel extends BaseModel {
|
|||
return false;
|
||||
}
|
||||
|
||||
public clearModels() {
|
||||
this.layer.off('remapping', this.buildModels);
|
||||
}
|
||||
protected registerBuiltinAttributes() {
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'textOffsets',
|
||||
|
@ -390,6 +394,9 @@ export default class TextModel extends BaseModel {
|
|||
const { createTexture2D } = this.rendererService;
|
||||
const { canvas } = this.fontService;
|
||||
this.textureHeight = canvas.height;
|
||||
if (this.texture) {
|
||||
this.texture.destroy();
|
||||
}
|
||||
this.texture = createTexture2D({
|
||||
data: canvas,
|
||||
mag: gl.LINEAR,
|
||||
|
|
|
@ -12,9 +12,11 @@ export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
|
|||
public buildModels() {
|
||||
const shape = this.getModelType();
|
||||
this.layerModel = new PolygonModels[shape](this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
this.models = this.layerModel.buildModels();
|
||||
}
|
||||
|
||||
protected getConfigSchema() {
|
||||
return {
|
||||
properties: {
|
||||
|
|
|
@ -16,6 +16,10 @@ export default class ExtrudeModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -29,6 +29,10 @@ export default class FillModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
|
|
|
@ -14,6 +14,9 @@ export default class RaterLayer extends BaseLayer<IRasterLayerStyleOptions> {
|
|||
public buildModels() {
|
||||
const modelType = this.getModelType();
|
||||
this.layerModel = new RasterModels[modelType](this);
|
||||
this.models = this.layerModel.initModels();
|
||||
}
|
||||
public rebuildModels() {
|
||||
this.models = this.layerModel.buildModels();
|
||||
}
|
||||
protected getConfigSchema() {
|
||||
|
|
|
@ -50,7 +50,7 @@ export default class RasterModel extends BaseModel {
|
|||
};
|
||||
}
|
||||
|
||||
public buildModels() {
|
||||
public initModels() {
|
||||
const source = this.layer.getSource();
|
||||
const { createTexture2D } = this.rendererService;
|
||||
const parserDataItem = source.data.dataArray[0];
|
||||
|
@ -85,6 +85,9 @@ export default class RasterModel extends BaseModel {
|
|||
];
|
||||
}
|
||||
|
||||
public buildModels() {
|
||||
return this.initModels();
|
||||
}
|
||||
protected registerBuiltinAttributes() {
|
||||
// point layer size;
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import { aProjectFlat } from '@antv/l7-utils';
|
||||
|
||||
import ExtrudePolyLine from '../extrude_polyline';
|
||||
|
||||
describe('extrude polyline', () => {
|
||||
const coords = [
|
||||
[57.65624999999999, 55.178867663281984],
|
||||
[74.8828125, 54.77534585936447],
|
||||
[74.8828125, 49.83798245308484],
|
||||
];
|
||||
const extrude = new ExtrudePolyLine({
|
||||
thickness: 1,
|
||||
});
|
||||
it('extrude line', () => {
|
||||
coords.forEach((coord) => {
|
||||
const [lng, lat] = aProjectFlat(coord);
|
||||
coord[0] = lng;
|
||||
coord[1] = lat;
|
||||
});
|
||||
const mesh = extrude.extrude(coords);
|
||||
expect(mesh.indices.length).toBe(12);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,332 @@
|
|||
import { aProjectFlat } from '@antv/l7-utils';
|
||||
import { vec2 } from 'gl-matrix';
|
||||
const tmp = vec2.create();
|
||||
const capEnd = vec2.create();
|
||||
const lineA = vec2.create();
|
||||
const lineB = vec2.create();
|
||||
const tangent = vec2.create();
|
||||
|
||||
export function computeMiter(
|
||||
lineTangent: vec2,
|
||||
miter: vec2,
|
||||
start: vec2,
|
||||
end: vec2,
|
||||
halfThick: number,
|
||||
): [number, vec2] {
|
||||
vec2.add(lineTangent, start, end);
|
||||
vec2.normalize(lineTangent, lineTangent);
|
||||
miter = vec2.fromValues(-lineTangent[1], lineTangent[0]);
|
||||
const tmpvec = vec2.fromValues(-start[1], start[0]);
|
||||
return [halfThick / vec2.dot(miter, tmpvec), miter];
|
||||
}
|
||||
export function computeNormal(out: vec2, dir: vec2) {
|
||||
return vec2.set(out, -dir[1], dir[0]);
|
||||
}
|
||||
export function direction(out: vec2, a: vec2, b: vec2) {
|
||||
vec2.sub(out, a, b);
|
||||
vec2.normalize(out, out);
|
||||
return out;
|
||||
}
|
||||
function isPointEqual(a: vec2, b: vec2) {
|
||||
return a[0] === b[0] && a[1] === b[1];
|
||||
}
|
||||
|
||||
export interface IExtrudeLineOption {
|
||||
join: string;
|
||||
cap: string;
|
||||
dash: boolean;
|
||||
closed: boolean;
|
||||
indexOffset: number;
|
||||
miterLimit: number;
|
||||
thickness: number;
|
||||
}
|
||||
export default class ExtrudePolyline {
|
||||
private join: string;
|
||||
private cap: string;
|
||||
private miterLimit: number;
|
||||
private thickness: number;
|
||||
private normal: vec2 | null;
|
||||
private lastFlip: number = -1;
|
||||
private miter: vec2 = vec2.fromValues(0, 0);
|
||||
private started: boolean = false;
|
||||
private dash: boolean = false;
|
||||
private totalDistance: number = 0;
|
||||
|
||||
constructor(opts: Partial<IExtrudeLineOption> = {}) {
|
||||
this.join = opts.join || 'miter';
|
||||
this.cap = opts.cap || 'butt';
|
||||
this.miterLimit = opts.miterLimit || 10;
|
||||
this.thickness = opts.thickness || 1;
|
||||
this.dash = opts.dash || false;
|
||||
}
|
||||
public extrude(points: number[][]) {
|
||||
const complex: {
|
||||
positions: number[];
|
||||
indices: number[];
|
||||
normals: number[];
|
||||
} = {
|
||||
positions: [],
|
||||
indices: [],
|
||||
normals: [],
|
||||
};
|
||||
if (points.length <= 1) {
|
||||
return complex;
|
||||
}
|
||||
this.lastFlip = -1;
|
||||
this.started = false;
|
||||
this.normal = null;
|
||||
this.totalDistance = 0;
|
||||
const total = points.length;
|
||||
for (let i = 1, count = 0; i < total; i++) {
|
||||
const last = points[i - 1] as vec2;
|
||||
const cur = points[i] as vec2;
|
||||
const next = i < points.length - 1 ? points[i + 1] : null;
|
||||
// 如果当前点和前一点相同,跳过
|
||||
if (isPointEqual(last, cur)) {
|
||||
continue;
|
||||
}
|
||||
const amt = this.segment(complex, count, last, cur, next as vec2);
|
||||
count += amt;
|
||||
}
|
||||
if (this.dash) {
|
||||
for (let i = 0; i < complex.positions.length / 6; i++) {
|
||||
complex.positions[i * 6 + 5] = this.totalDistance;
|
||||
}
|
||||
}
|
||||
|
||||
return complex;
|
||||
}
|
||||
private segment(
|
||||
complex: any,
|
||||
index: number,
|
||||
last: vec2,
|
||||
cur: vec2,
|
||||
next: vec2,
|
||||
) {
|
||||
let count = 0;
|
||||
const indices = complex.indices;
|
||||
const positions = complex.positions;
|
||||
const normals = complex.normals;
|
||||
const capSquare = this.cap === 'square';
|
||||
const joinBevel = this.join === 'bevel';
|
||||
const flatCur = aProjectFlat([cur[0], cur[1]]) as [number, number];
|
||||
const flatLast = aProjectFlat([last[0], last[1]]) as [number, number];
|
||||
direction(lineA, flatCur, flatLast);
|
||||
let segmentDistance = 0;
|
||||
if (this.dash) {
|
||||
segmentDistance = this.lineSegmentDistance(flatCur, flatLast);
|
||||
this.totalDistance += segmentDistance;
|
||||
}
|
||||
|
||||
if (!this.normal) {
|
||||
this.normal = vec2.create();
|
||||
computeNormal(this.normal, lineA);
|
||||
}
|
||||
if (!this.started) {
|
||||
this.started = true;
|
||||
|
||||
// if the end cap is type square, we can just push the verts out a bit
|
||||
if (capSquare) {
|
||||
// vec2.scaleAndAdd(capEnd, last, lineA, -this.thickness);
|
||||
const out1 = vec2.create();
|
||||
const out2 = vec2.create();
|
||||
vec2.add(out1, this.normal, lineA);
|
||||
vec2.add(out2, this.normal, lineA);
|
||||
normals.push(out2[0], out2[1], 0);
|
||||
normals.push(out1[0], out1[1], 0);
|
||||
positions.push(
|
||||
last[0],
|
||||
last[1],
|
||||
0,
|
||||
this.totalDistance - segmentDistance,
|
||||
-this.thickness,
|
||||
0,
|
||||
);
|
||||
positions.push(
|
||||
last[0],
|
||||
last[1],
|
||||
0,
|
||||
this.totalDistance - segmentDistance,
|
||||
this.thickness,
|
||||
0,
|
||||
);
|
||||
|
||||
// this.extrusions(positions, normals, last, out, this.thickness);
|
||||
// last = capEnd;
|
||||
} else {
|
||||
this.extrusions(
|
||||
positions,
|
||||
normals,
|
||||
last,
|
||||
this.normal,
|
||||
this.thickness,
|
||||
this.totalDistance - segmentDistance,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
indices.push(index + 0, index + 1, index + 2);
|
||||
|
||||
if (!next) {
|
||||
computeNormal(this.normal, lineA);
|
||||
if (capSquare) {
|
||||
// vec2.scaleAndAdd(capEnd, cur, lineA, this.thickness);
|
||||
// cur = capEnd;
|
||||
const out1 = vec2.create();
|
||||
const out2 = vec2.create();
|
||||
vec2.sub(out2, lineA, this.normal);
|
||||
vec2.add(out1, lineA, this.normal);
|
||||
// this.extrusions(positions, normals, cur, out, this.thickness);
|
||||
normals.push(out2[0], out2[1], 0);
|
||||
normals.push(out1[0], out1[1], 0);
|
||||
positions.push(
|
||||
cur[0],
|
||||
cur[1],
|
||||
0,
|
||||
this.totalDistance,
|
||||
this.thickness,
|
||||
0,
|
||||
);
|
||||
positions.push(
|
||||
cur[0],
|
||||
cur[1],
|
||||
0,
|
||||
this.totalDistance,
|
||||
this.thickness,
|
||||
0,
|
||||
);
|
||||
} else {
|
||||
this.extrusions(
|
||||
positions,
|
||||
normals,
|
||||
cur,
|
||||
this.normal,
|
||||
this.thickness,
|
||||
this.totalDistance,
|
||||
);
|
||||
}
|
||||
|
||||
// this.extrusions(positions, normals, cur, this.normal, this.thickness);
|
||||
indices.push(
|
||||
...(this.lastFlip === 1
|
||||
? [index, index + 2, index + 3]
|
||||
: [index + 2, index + 1, index + 3]),
|
||||
);
|
||||
count += 2;
|
||||
} else {
|
||||
const flatNext = aProjectFlat([next[0], next[1]]) as [number, number];
|
||||
if (isPointEqual(flatCur, flatNext)) {
|
||||
vec2.add(
|
||||
flatNext,
|
||||
flatCur,
|
||||
vec2.normalize(flatNext, vec2.subtract(flatNext, flatCur, flatLast)),
|
||||
);
|
||||
}
|
||||
direction(lineB, flatNext, flatCur);
|
||||
|
||||
// stores tangent & miter
|
||||
|
||||
const [miterLen, miter] = computeMiter(
|
||||
tangent,
|
||||
vec2.create(),
|
||||
lineA,
|
||||
lineB,
|
||||
this.thickness,
|
||||
);
|
||||
// normal(tmp, lineA)
|
||||
|
||||
// get orientation
|
||||
let flip = vec2.dot(tangent, this.normal) < 0 ? -1 : 1;
|
||||
let bevel = joinBevel;
|
||||
if (!bevel && this.join === 'miter') {
|
||||
const limit = miterLen;
|
||||
if (limit > this.miterLimit) {
|
||||
bevel = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bevel) {
|
||||
normals.push(this.normal[0], this.normal[1], 0);
|
||||
normals.push(miter[0], miter[1], 0);
|
||||
positions.push(
|
||||
cur[0],
|
||||
cur[1],
|
||||
0,
|
||||
this.totalDistance,
|
||||
-this.thickness * flip,
|
||||
0,
|
||||
);
|
||||
positions.push(
|
||||
cur[0],
|
||||
cur[1],
|
||||
0,
|
||||
this.totalDistance,
|
||||
this.thickness * flip,
|
||||
0,
|
||||
);
|
||||
indices.push(
|
||||
...(this.lastFlip !== -flip
|
||||
? [index, index + 2, index + 3]
|
||||
: [index + 2, index + 1, index + 3]),
|
||||
);
|
||||
|
||||
// now add the bevel triangle
|
||||
indices.push(index + 2, index + 3, index + 4);
|
||||
|
||||
computeNormal(tmp, lineB);
|
||||
vec2.copy(this.normal, tmp); // store normal for next round
|
||||
normals.push(this.normal[0], this.normal[1], 0);
|
||||
positions.push(
|
||||
cur[0],
|
||||
cur[1],
|
||||
0,
|
||||
this.totalDistance,
|
||||
-this.thickness * flip,
|
||||
0,
|
||||
);
|
||||
count += 3;
|
||||
} else {
|
||||
this.extrusions(
|
||||
positions,
|
||||
normals,
|
||||
cur,
|
||||
miter,
|
||||
miterLen,
|
||||
this.totalDistance,
|
||||
);
|
||||
indices.push(
|
||||
...(this.lastFlip === 1
|
||||
? [index, index + 2, index + 3]
|
||||
: [index + 2, index + 1, index + 3]),
|
||||
);
|
||||
|
||||
flip = -1;
|
||||
|
||||
// the miter is now the normal for our next join
|
||||
vec2.copy(this.normal, miter);
|
||||
count += 2;
|
||||
}
|
||||
this.lastFlip = flip;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private extrusions(
|
||||
positions: number[],
|
||||
normals: number[],
|
||||
point: vec2, // 顶点
|
||||
normal: vec2, // 法向量
|
||||
thickness: number, // 高度
|
||||
distanceRadio: number,
|
||||
) {
|
||||
normals.push(normal[0], normal[1], 0);
|
||||
normals.push(normal[0], normal[1], 0);
|
||||
positions.push(point[0], point[1], 0, distanceRadio, -thickness, 0);
|
||||
positions.push(point[0], point[1], 0, distanceRadio, thickness, 0);
|
||||
}
|
||||
private lineSegmentDistance(b1: vec2, a1: vec2) {
|
||||
const dx = a1[0] - b1[0];
|
||||
const dy = a1[1] - b1[1];
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
}
|
|
@ -71,7 +71,7 @@ export default function(
|
|||
let lineNormal = null;
|
||||
const tmp = vec2.create();
|
||||
let count = indexOffset || 0;
|
||||
const miterLimit = 3;
|
||||
const miterLimit = 4;
|
||||
|
||||
const out: number[] = [];
|
||||
const attrPos: number[] = [];
|
||||
|
@ -172,7 +172,6 @@ export default function(
|
|||
count += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bevel) {
|
||||
miterLen = miterLimit;
|
||||
|
||||
|
@ -232,7 +231,7 @@ export default function(
|
|||
return {
|
||||
normals: out,
|
||||
attrIndex,
|
||||
attrPos: pickData, // [x,y,z, distance, miter ,tatal ]
|
||||
attrPos: pickData, // [x,y,z, distance, miter ,t0tal ]
|
||||
};
|
||||
}
|
||||
// [x,y,z, distance, miter ]
|
||||
|
|
|
@ -1,7 +1,24 @@
|
|||
import { type } from 'os';
|
||||
|
||||
interface IPoint {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
export type anchorType =
|
||||
| 'right'
|
||||
| 'top-right'
|
||||
| 'left'
|
||||
| 'bottom-right'
|
||||
| 'left'
|
||||
| 'top-left'
|
||||
| 'bottom-left'
|
||||
| 'bottom'
|
||||
| 'bottom-right'
|
||||
| 'bottom-left'
|
||||
| 'top'
|
||||
| 'top-right'
|
||||
| 'top-left'
|
||||
| 'center';
|
||||
export interface IGlyphQuad {
|
||||
tr: IPoint;
|
||||
tl: IPoint;
|
||||
|
@ -22,10 +39,9 @@ export interface IGlyphQuad {
|
|||
* @param {string} anchor 锚点位置
|
||||
* @return {alignment} alignment
|
||||
*/
|
||||
function getAnchorAlignment(anchor: string) {
|
||||
function getAnchorAlignment(anchor: anchorType) {
|
||||
let horizontalAlign = 0.5;
|
||||
let verticalAlign = 0.5;
|
||||
|
||||
switch (anchor) {
|
||||
case 'right':
|
||||
case 'top-right':
|
||||
|
@ -109,7 +125,7 @@ function shapeLines(
|
|||
glyphMap: any,
|
||||
lines: any[],
|
||||
lineHeight: number,
|
||||
textAnchor: string,
|
||||
textAnchor: anchorType,
|
||||
textJustify: string,
|
||||
spacing: number,
|
||||
) {
|
||||
|
@ -197,7 +213,7 @@ export function shapeText(
|
|||
text: string,
|
||||
glyphs: any,
|
||||
lineHeight: number,
|
||||
textAnchor: string,
|
||||
textAnchor: anchorType,
|
||||
textJustify: string,
|
||||
spacing: number,
|
||||
translate: [number, number] = [0, 0],
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue