├── .commitlintrc.js
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .fatherrc.ts
├── .github
├── ISSUE_TEMPLATE
│ ├── ----bug-report.md
│ ├── ---ask-for-question.md
│ └── ---feature-request.md
├── PULL_REQUEST_TEMPLATE.md
├── release.yaml
└── workflows
│ ├── lint.yml
│ ├── preview.yml
│ ├── release-label.yml
│ └── release.yml
├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .prettierignore
├── .prettierrc
├── .prettierrc.js
├── .umirc.ts
├── CHANGELOG.md
├── LICENSE
├── README.md
├── docs
├── CNAME
├── docs
│ ├── control.md
│ ├── draw
│ │ ├── circle.md
│ │ ├── line.md
│ │ ├── point.md
│ │ ├── polygon.md
│ │ └── rect.md
│ ├── event.md
│ ├── method.md
│ ├── pointEvent.md
│ └── super
│ │ ├── adsorb.md
│ │ ├── area.md
│ │ ├── distance.md
│ │ ├── history.md
│ │ ├── keyboard.md
│ │ ├── style.md
│ │ └── style.tsx
└── example
│ ├── circle
│ ├── area.md
│ ├── area.tsx
│ ├── autoActive.md
│ ├── autoActive.tsx
│ ├── createByDrag.md
│ ├── createByDrag.tsx
│ ├── edges.md
│ ├── edges.tsx
│ ├── editable.md
│ ├── editable.tsx
│ ├── event.md
│ ├── event.tsx
│ ├── initialData.md
│ ├── initialData.tsx
│ ├── mock.ts
│ ├── multiple.md
│ ├── multiple.tsx
│ ├── start.md
│ └── start.tsx
│ ├── common
│ ├── adsorb.md
│ ├── adsorb.tsx
│ ├── bbox.md
│ ├── bbox.tsx
│ ├── helper.md
│ └── helper.tsx
│ ├── control
│ ├── add.md
│ ├── add.tsx
│ ├── common.md
│ ├── common.tsx
│ ├── custom.md
│ ├── custom.tsx
│ ├── draw.md
│ ├── draw.tsx
│ ├── enable-by-click.md
│ ├── enable-by-click.tsx
│ ├── event.md
│ ├── event.tsx
│ ├── start.md
│ └── start.tsx
│ ├── line
│ ├── adsorb.md
│ ├── adsorb.tsx
│ ├── autoActive.md
│ ├── autoActive.tsx
│ ├── createByDrag.md
│ ├── createByDrag.tsx
│ ├── distance.md
│ ├── distance.tsx
│ ├── editable.md
│ ├── editable.tsx
│ ├── event.md
│ ├── event.tsx
│ ├── initialData.md
│ ├── initialData.tsx
│ ├── initialData1.tsx
│ ├── midPoint.md
│ ├── midPoint.tsx
│ ├── mock.ts
│ ├── multiple.md
│ ├── multiple.tsx
│ ├── start.md
│ └── start.tsx
│ ├── map
│ ├── baidu.md
│ ├── baidu.tsx
│ ├── gaode.md
│ ├── gaode.tsx
│ ├── mapbox.md
│ ├── mapbox.tsx
│ ├── tencent.md
│ ├── tencent.tsx
│ ├── tianditu.md
│ └── tianditu.tsx
│ ├── point
│ ├── autoActive.md
│ ├── autoActive.tsx
│ ├── editable.md
│ ├── editable.tsx
│ ├── event.md
│ ├── event.tsx
│ ├── image.md
│ ├── image.tsx
│ ├── initialData.md
│ ├── initialData.tsx
│ ├── initialData1.tsx
│ ├── mock.ts
│ ├── multiple.md
│ ├── multiple.tsx
│ ├── start.md
│ ├── start.tsx
│ ├── style.md
│ └── style.tsx
│ ├── polygon
│ ├── adsorb.md
│ ├── adsorb.tsx
│ ├── area.md
│ ├── area.tsx
│ ├── autoActive.md
│ ├── autoActive.tsx
│ ├── createByDrag.md
│ ├── createByDrag.tsx
│ ├── editable.md
│ ├── editable.tsx
│ ├── event.md
│ ├── event.tsx
│ ├── initialData.md
│ ├── initialData.tsx
│ ├── initialData1.tsx
│ ├── midPoint.md
│ ├── midPoint.tsx
│ ├── mock.ts
│ ├── multiple.md
│ ├── multiple.tsx
│ ├── start.md
│ ├── start.tsx
│ ├── style.md
│ └── style.tsx
│ ├── rect
│ ├── area.md
│ ├── area.tsx
│ ├── autoActive.md
│ ├── autoActive.tsx
│ ├── createByDrag.md
│ ├── createByDrag.tsx
│ ├── editable.md
│ ├── editable.tsx
│ ├── event.md
│ ├── event.tsx
│ ├── initialData.md
│ ├── initialData.tsx
│ ├── mock.ts
│ ├── multiple.md
│ ├── multiple.tsx
│ ├── start.md
│ └── start.tsx
│ └── usage
│ ├── bus.md
│ ├── bus.tsx
│ ├── tilMap.md
│ └── tileMap.tsx
├── package.json
├── src
├── constant
│ ├── default.ts
│ ├── drawer.ts
│ ├── event.ts
│ ├── helper.ts
│ ├── index.ts
│ ├── render.ts
│ └── style.ts
├── control
│ ├── constant.ts
│ ├── iconfont.js
│ ├── index.css
│ ├── index.less
│ ├── index.ts
│ └── types.ts
├── drawer
│ ├── circle-drawer.ts
│ ├── index.ts
│ ├── line-drawer.ts
│ ├── point-drawer.ts
│ ├── polygon-drawer.ts
│ └── rect-drawer.ts
├── index.ts
├── interactive
│ ├── cursor.ts
│ ├── index.ts
│ └── popup.ts
├── mode
│ ├── base-mode.ts
│ ├── drag-polygon-mode.ts
│ ├── index.ts
│ ├── line-mode.ts
│ ├── mid-point-mode.ts
│ ├── point-mode.ts
│ └── polygon-mode.ts
├── render
│ ├── dash-line-render.ts
│ ├── index.ts
│ ├── layer-render.ts
│ ├── line-render.ts
│ ├── mid-point-render.ts
│ ├── point-render.ts
│ ├── polygon-render.ts
│ ├── scene-render.ts
│ └── text-render.ts
├── source
│ ├── history.ts
│ ├── index.ts
│ └── source.ts
├── typings
│ ├── dom.ts
│ ├── drawer.ts
│ ├── feature.ts
│ ├── helper.ts
│ ├── index.ts
│ ├── render.ts
│ ├── scene.ts
│ ├── source.ts
│ ├── style.ts
│ └── utils.ts
└── utils
│ ├── adsorb.ts
│ ├── calc.ts
│ ├── common.ts
│ ├── event.ts
│ ├── feature.ts
│ ├── index.ts
│ └── style.ts
├── tsconfig.json
└── typings.d.ts
/.commitlintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@commitlint/config-conventional'],
3 | rules: {
4 | 'type-enum': [
5 | 2,
6 | 'always',
7 | [
8 | 'build',
9 | 'chore',
10 | 'ci',
11 | 'docs',
12 | 'feat',
13 | 'fix',
14 | 'perf',
15 | 'refactor',
16 | 'revert',
17 | 'style',
18 | 'test',
19 | 'deps',
20 | ],
21 | ],
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [Makefile]
16 | indent_style = tab
17 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | coverage
4 | scripts
5 | dist
6 | es
7 | lib
8 | docs-dist
9 | iconfont.js
10 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: '@typescript-eslint/parser',
4 | plugins: ['@typescript-eslint', 'jest', 'prettier'],
5 | extends: [
6 | 'eslint:recommended',
7 | 'plugin:@typescript-eslint/recommended',
8 | 'prettier',
9 | 'plugin:jest/recommended',
10 | ],
11 | rules: {
12 | 'prettier/prettier': 'warn',
13 | '@typescript-eslint/no-explicit-any': 'off',
14 | '@typescript-eslint/explicit-module-boundary-types': 'off',
15 | '@typescript-eslint/ban-ts-comment': 'off',
16 | '@typescript-eslint/no-non-null-assertion': 'off',
17 | '@typescript-eslint/no-empty-function': 'off',
18 | },
19 | env: {
20 | node: true,
21 | jest: true,
22 | },
23 | };
24 |
--------------------------------------------------------------------------------
/.fatherrc.ts:
--------------------------------------------------------------------------------
1 | import { optimizeLodashImports } from '@optimize-lodash/rollup-plugin';
2 | import nodePolyfills from 'rollup-plugin-node-polyfills';
3 | // import analyze from 'rollup-plugin-analyzer';
4 |
5 | export default {
6 | esm: 'babel',
7 | cjs: 'babel',
8 | umd: {
9 | name: 'L7.Draw',
10 | file: 'l7-draw',
11 | minFile: true,
12 | sourcemap: true,
13 | globals: {
14 | '@antv/l7': 'L7',
15 | },
16 | },
17 | extraRollupPlugins: [optimizeLodashImports(), nodePolyfills()], //analyze()
18 | lessInBabelMode: true,
19 | };
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/----bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F41B Bug report"
3 | about: Create a report to help us improve
4 | title: "\U0001F41B [BUG]"
5 | labels: Bug
6 | assignees: ''
7 | ---
8 |
9 |
10 |
11 | ### 🐛 Bug description [Please make everyone to understand it]
12 |
13 | > Please provide a link by forking these links [L7 Draw](https://codesandbox.io/s/l7draw-issue-template-df75t7) or GitHub repo, a minimal reproduction.
14 |
15 | - _Required_ **Link to minimal reproduction**:
16 |
17 | ### 📷 Step to reproduce
18 |
19 | ### 🏞 Expected result
20 |
21 | ### 🚑 Any additional [like screenshots]
22 |
23 | - **L7Draw Version**:
24 | - **Platform**:
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/---ask-for-question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F914 Ask for question"
3 | about: Look for some help or ask question
4 | title: "\U0001F914 [QUESTION]"
5 | labels: Question
6 | assignees: ''
7 | ---
8 |
9 | ### 🐛 Question description [Please make everyone to understand it]
10 |
11 | ### 💻 Link to minimal reproduction
12 |
13 | Please provide a link by forking these links [L7 Draw](https://codesandbox.io/s/l7draw-issue-template-df75t7) or GitHub repo. What is a minimal reproduction, and why is it required?
14 |
15 | ### 🏞 Expected result
16 |
17 | ### 🚑 Any additional [like screenshots]
18 |
19 | - **L7Draw Version**:
20 | - **Platform**:
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/---feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F970 Feature request"
3 | about: Suggest an idea for this project
4 | title: "\U0001F970 [FEATURE]"
5 | labels: Feature
6 | assignees: ''
7 | ---
8 |
9 | ### 💻 Features description [Please make everyone to understand it]
10 |
11 | ### 🏞 What problem does this feature solve
12 |
13 | ### 🧐 What does the proposed API look like
14 |
15 | ### 🚑 Any additional [like screenshots]
16 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### PR includes
2 |
3 |
4 |
5 | - [ ] fixed #0
6 | - [ ] add / modify test cases
7 | - [ ] documents, demos
8 |
9 | ### Screenshot
10 |
11 | | Before | After |
12 | | ------ | ----- |
13 | | ❌ | ✅ |
14 |
--------------------------------------------------------------------------------
/.github/release.yaml:
--------------------------------------------------------------------------------
1 | # for .github/workflows/release-label.yml
2 |
3 | changelog:
4 | exclude:
5 | labels:
6 | - ignore-for-release
7 | - chore
8 | categories:
9 | - title: 🎉 New Features
10 | labels:
11 | - feature
12 | - enhancement
13 | - title: 📖 Documentation Changes
14 | labels:
15 | - documentation
16 | - title: 🐛 Bug Fixes
17 | labels:
18 | - bugfix
19 | - title: 🛠 Breaking Changes
20 | labels:
21 | - breaking
22 | - title: Other Changes
23 | labels:
24 | - "*"
25 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: lint
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | lint:
7 | runs-on: ubuntu-latest
8 | strategy:
9 | matrix:
10 | node-version: [16.x]
11 | steps:
12 | - uses: actions/checkout@v2
13 | - name: Use Node.js ${{ matrix.node-version }}
14 | uses: actions/setup-node@v2
15 | with:
16 | node-version: ${{ matrix.node-version }}
17 | - run: npm install
18 | - run: npm run ci
19 | # - name: coverall
20 | # if: success()
21 | # uses: coverallsapp/github-action@master
22 | # with:
23 | # github-token: ${{ secrets.GITHUB_TOKEN }}
24 |
--------------------------------------------------------------------------------
/.github/workflows/preview.yml:
--------------------------------------------------------------------------------
1 | name: Surge PR Preview
2 |
3 | on: pull_request
4 |
5 | jobs:
6 | preview:
7 | runs-on: ubuntu-latest
8 | strategy:
9 | matrix:
10 | node-version: [16.x]
11 | steps:
12 | - uses: actions/checkout@v2
13 | - name: Use Node.js ${{ matrix.node-version }}
14 | uses: actions/setup-node@v2
15 | with:
16 | node-version: ${{ matrix.node-version }}
17 | - uses: afc163/surge-preview@v1
18 | with:
19 | surge_token: ${{ secrets.SURGE_TOKEN }}
20 | github_token: ${{ secrets.GITHUB_TOKEN }}
21 | dist: docs-dist
22 | build: |
23 | npm install
24 | npm run docs:build
25 |
--------------------------------------------------------------------------------
/.github/workflows/release-label.yml:
--------------------------------------------------------------------------------
1 | # Warning, do not check out untrusted code with
2 | # the pull_request_target event.
3 | on:
4 | pull_request_target:
5 | types: [ opened, edited ]
6 | name: conventional-release-labels
7 | jobs:
8 | label:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: bcoe/conventional-release-labels@v1
12 | with:
13 | token: ${{ secrets.GITHUB_TOKEN }}
14 | type_labels: '{"feat": "feature", "fix": "bugfix", "breaking": "breaking", "docs": "documentation", "chore": "chore"}'
15 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: release
2 |
3 | on:
4 | release:
5 | types: [created, edited]
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | - uses: actions/setup-node@v2
13 | with:
14 | node-version: 16
15 | - run: npm install
16 | - run: npm run ci
17 |
18 | publish-site:
19 | needs: build
20 | runs-on: ubuntu-latest
21 | steps:
22 | - uses: actions/checkout@v2
23 | - uses: actions/setup-node@v2
24 | with:
25 | node-version: 16
26 | - run: npm install
27 | - run: npm run docs:build
28 | - run: |
29 | cd docs-dist
30 | git init
31 | git config --local user.name antv
32 | git config --local user.email antv@antfin.com
33 | git add .
34 | git commit -m "update by release action"
35 | - uses: ad-m/github-push-action@master
36 | with:
37 | github_token: ${{secrets.GITHUB_TOKEN}}
38 | directory: docs-dist
39 | branch: gh-pages
40 | force: true
41 |
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /npm-debug.log*
6 | /yarn-error.log
7 | /yarn.lock
8 | /package-lock.json
9 |
10 | # production
11 | /es
12 | /docs-dist
13 | /dist
14 | /lib
15 | # misc
16 | .DS_Store
17 | /coverage
18 |
19 | # umi
20 | .umi
21 | .umi-production
22 | .umi-test
23 | .env.local
24 |
25 | # ide
26 | /.vscode
27 | /.idea
28 | /.history
29 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npx lint-staged
5 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx --no-install commitlint --edit "$1"
5 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | **/*.svg
2 | **/*.ejs
3 | **/*.html
4 | .**/**
5 | package.json
6 | .umi
7 | .umi-production
8 | .umi-test
9 | dist
10 | es
11 | lib
12 | docs-dist
13 | iconfont.js
14 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all",
4 | "printWidth": 80,
5 | "overrides": [
6 | {
7 | "files": ".prettierrc",
8 | "options": { "parser": "json" }
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = require('@umijs/fabric').prettier;
2 |
--------------------------------------------------------------------------------
/.umirc.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'dumi';
2 |
3 | const isProduction = process.env.NODE_ENV === 'production';
4 |
5 | export default defineConfig({
6 | title: 'L7Draw',
7 | favicon:
8 | 'https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7svFR6wkPMoAAAAAAAAAAAAADmJ7AQ/original',
9 | logo: 'https://user-images.githubusercontent.com/9554297/83762004-a0761b00-a6a9-11ea-83b4-9c8ff721d4b8.png',
10 | mode: 'site',
11 | extraBabelIncludes: ['@antv/dumi-theme-antv'],
12 | navs: [
13 | {
14 | title: '文档',
15 | path: '/docs',
16 | },
17 | {
18 | title: '示例',
19 | path: '/example',
20 | },
21 | {
22 | title: '工具',
23 | path: 'https://l7editor.antv.antgroup.com',
24 | },
25 | {
26 | title: '周边生态',
27 | children: [
28 | {
29 | title: 'L7',
30 | path: 'https://l7.antv.antgroup.com/',
31 | },
32 | {
33 | title: 'L7Plot',
34 | path: 'https://l7plot.antv.antgroup.com/',
35 | },
36 | {
37 | title: 'LarkMap',
38 | path: 'https://larkmap.antv.antgroup.com/',
39 | },
40 | {
41 | title: 'Location Insight',
42 | path: 'https://locationinsight.antv.antgroup.com/',
43 | },
44 | {
45 | title: 'L7Editor',
46 | path: 'https://li.antv.antgroup.com/#/home',
47 | },
48 | ],
49 | },
50 | {
51 | title: '历史版本',
52 | children: [
53 | {
54 | title: '2.x',
55 | path: 'https://antv.vision/l7draw-2.x-site/',
56 | },
57 | ],
58 | },
59 | {
60 | title: 'Github',
61 | path: 'https://github.com/antvis/L7Draw',
62 | },
63 | // {
64 | // title: '更新日志',
65 | // path: 'https://github.com/antvis/L7Draw/tree/feat/refactor',
66 | // },
67 | ],
68 | // styles: ['https://cdn.bootcdn.net/ajax/libs/antd/4.20.2/antd.css'],
69 | outputPath: 'docs-dist',
70 | devServer: {
71 | port: 8080,
72 | },
73 | copy: isProduction ? ['docs/CNAME'] : [],
74 | devtool: isProduction ? false : 'eval',
75 | scripts: [
76 | ` window._AMapSecurityConfig = {
77 | securityJsCode: "290ddc4b0d33be7bc9b354bc6a4ca614"
78 | }`,
79 | 'https://webapi.amap.com/maps?v=2.0&key=6f025e700cbacbb0bb866712d20bb35c',
80 | ],
81 | // more config: https://d.umijs.org/config
82 | });
83 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2021 AntV
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # L7Draw
2 |
3 | > 基于 [L7](https://l7.antv.vision/zh) 封装的地理绘制库,支持在地图上通过单击、拖拽等方式绘制点、线、面的 GeoJSON 的数据
4 |
5 | [](https://www.npmjs.com/package/@antv/l7-draw) [](https://www.npmjs.com/package/@antv/l7-draw)
6 |
7 | [文档](https://antv.vision/L7Draw/docs/draw/point) · [示例](https://antv.vision/L7Draw/example/point/start)
8 |
9 | ## 🔨 工具
10 |
11 | 基于 L7Draw 的面向 GeoJSON 编辑工具 [L7Editor](https://l7editor.antv.antgroup.com/) 已上线,欢迎尝鲜~。
12 |
13 | ## 📦 安装
14 |
15 | ```bash
16 | npm install -S @antv/l7-draw
17 | ```
18 |
19 | ## 🔨 使用
20 |
21 | ### 通过 NPM 引入
22 |
23 | ```tsx | pure
24 | // ----js-----
25 | import { GaodeMap, Scene } from '@antv/l7';
26 | import { DrawEvent, DrawPoint } from '@antv/l7-draw';
27 |
28 | const scene = new Scene({
29 | id: 'map',
30 | map: new GaodeMap({}),
31 | });
32 |
33 | scene.on('loaded', () => {
34 | // 实例化 Draw
35 | const draw = new DrawPoint(scene, {
36 | editable: false,
37 | // Draw 配置
38 | });
39 |
40 | // 调用 Draw 上的方法
41 | draw.enable();
42 |
43 | // 监听 Draw 的事件
44 | draw.on(DrawEvent.Add, (newPoint) => {
45 | console.log(newPoint);
46 | });
47 | });
48 |
49 | // ----html----
50 |
;
51 | ```
52 |
53 | ### 通过 CDN 引入
54 |
55 | ```html | pure
56 |
57 |
58 |
59 |
60 |
75 | ```
76 |
77 | ## ⌨️ 本地开发
78 |
79 | ```bash
80 | # 安装依赖
81 | npm install
82 |
83 | # 运行页面
84 | npm run start
85 |
86 | # 打包
87 | npm run build
88 | ```
89 |
90 | ## 💬 答疑
91 |
92 | 在使用 L7Draw 过程中,若有疑惑无法在文档中解决的可以扫码加入 L7 官方答疑群。
93 |
94 |
95 |
96 | ## 📋 待办
97 |
98 | - [ ] 新增 Marker 绘制类型
99 | - [ ] 新增 文本 绘制类型
100 | - [ ] 新增支持编辑挖孔 Polygon
101 | - [ ] 新增 两个 Polygon 交/并/异或/差集(合并/挖孔/切割)
102 | - [ ] 优化 DrawControl Icon
103 |
104 | ## 🤝 如何贡献
105 |
106 | 如果您在使用的过程中碰到问题,可以先通过 [issues](https://github.com/antvis/l7-draw/issues) 看看有没有类似的 bug 或者建议。
107 |
108 | ## 📖 许可证
109 |
110 | MIT@[AntV](https://github.com/antvis).
111 |
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | l7draw.antv.vision
2 |
--------------------------------------------------------------------------------
/docs/docs/event.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 事件
3 | hide: true
4 | ---
5 |
6 | | 事件名 | 说明 | 类型 |
7 | | ---------------------------------------- | ------------------------------------------------------ | ---------------------------------------------------------------------------- |
8 | | DrawEvent.Init | 'init' | Draw 初始化完成的事件 | `function(drawer: Draw)` |
9 | | DrawEvent.Destroy | 'destroy' | Draw 完成销毁的事件 | `function(drawer: Draw)` |
10 | | DrawEvent.Enable | 'enable' | 启用绘制的事件 | `function(drawer: Draw)` |
11 | | DrawEvent.Disable | 'disable' | 禁用绘制的事件 | `function(drawer: Draw)` |
12 | | DrawEvent.Clear | 'clear' | 清空数据的事件 | `function(drawer: Draw)` |
13 | | DrawEvent.AddNode | 'addNode' | 添加结点 | `(newNode: Feature,editFeature: Feature, featureList: Feature[]) => void` |
14 | | DrawEvent.RemoveNode | 'removeNode' | 删除结点 | `(removeNode: Feature,editFeature: Feature, featureList: Feature[]) => void` |
15 | | DrawEvent.Add | 'add' | 新增的事件 | `function(newFeature: Feature, featureList: Feature[])` |
16 | | DrawEvent.Edit | 'edit' | 编辑(位移或节点发生变更)的事件 | `function(editFeature: Feature, featureList: Feature[])` |
17 | | DrawEvent.Remove | 'remove' | 删除的事件 | `function(deleteFeature: Feature, featureList: Feature[])` |
18 | | DrawEvent.DragStart | 'dragStart' | 开始拖拽的事件 | `function(dragFeature: Feature, featureList: Feature[])` |
19 | | DrawEvent.Dragging | 'dragging' | 拖拽中的事件 | `function(dragFeature: Feature, featureList: Feature[])` |
20 | | DrawEvent.DragEnd | 'dragEnd' | 拖拽结束的事件 | `function(dragFeature: Feature, featureList: Feature[])` |
21 | | DrawEvent.Change | 'change' | 绘制数据发生变更后的事件(包含以上绘制数据变动的事件) | `function(featureList: Feature[])` |
22 | | DrawEvent.Select | 'select' | 当前选中元素发生改变的事件 | `function(selectFeature: Feature | null)` |
23 |
--------------------------------------------------------------------------------
/docs/docs/pointEvent.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 事件
3 | hide: true
4 | ---
5 |
6 | | 事件名 | 说明 | 类型 |
7 | | -------------------------------------- | ------------------------------------------------------ | ---------------------------------------------------------- |
8 | | DrawEvent.Init | 'init' | Draw 初始化完成的事件 | `function(drawer: Draw)` |
9 | | DrawEvent.Destroy | 'destroy' | Draw 完成销毁的事件 | `function(drawer: Draw)` |
10 | | DrawEvent.Enable | 'enable' | 启用绘制的事件 | `function(drawer: Draw)` |
11 | | DrawEvent.Disable | 'disable' | 禁用绘制的事件 | `function(drawer: Draw)` |
12 | | DrawEvent.Clear | 'clear' | 清空数据的事件 | `function(drawer: Draw)` |
13 | | DrawEvent.Add | 'add' | 新增的事件 | `function(newFeature: Feature, featureList: Feature[])` |
14 | | DrawEvent.Edit | 'edit' | 编辑(位移或节点发生变更)的事件 | `function(editFeature: Feature, featureList: Feature[])` |
15 | | DrawEvent.Remove | 'remove' | 删除的事件 | `function(deleteFeature: Feature, featureList: Feature[])` |
16 | | DrawEvent.DragStart | 'dragStart' | 开始拖拽的事件 | `function(dragFeature: Feature, featureList: Feature[])` |
17 | | DrawEvent.Dragging | 'dragging' | 拖拽中的事件 | `function(dragFeature: Feature, featureList: Feature[])` |
18 | | DrawEvent.DragEnd | 'dragEnd' | 拖拽结束的事件 | `function(dragFeature: Feature, featureList: Feature[])` |
19 | | DrawEvent.Change | 'change' | 绘制数据发生变更后的事件(包含以上绘制数据变动的事件) | `function(featureList: Feature[])` |
20 |
--------------------------------------------------------------------------------
/docs/docs/super/adsorb.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 吸附能力
3 | order: 6
4 | group:
5 | title: 高级
6 | order: 2
7 | path: /super
8 | ---
9 |
10 | ## 说明
11 |
12 | 在 `DrawLine` 和 `DrawPolygon` 中,在**绘制和拖拽结点**的过程中,当结点位置距离目标吸附物的点或线指定像素值内时,会将当前操作结点自动吸附到吸附物的点或线上,若开启吸附时会自动计算各个 `Feature` 的 `bbox` 用于吸附的计算性能提升。
13 |
14 |
15 |
16 | ## 示例
17 |
18 | ```tsx | pure
19 | import { DrawPolygon } from '@antv/l7-draw';
20 |
21 | const adsorbPolygon = {
22 | type: 'Feature',
23 | properties: {},
24 | geometry: {
25 | type: 'Polygon',
26 | coordinates: [
27 | [
28 | [120.1519775390625, 30.263663574301724],
29 | [120.13240814208984, 30.228963070192805],
30 | [120.15695571899413, 30.252691235553513],
31 | [120.1519775390625, 30.263663574301724],
32 | ],
33 | ],
34 | },
35 | };
36 |
37 | const drawer = new DrawPolygon(scene, {
38 | adsorbOptions: {
39 | // 指定吸附围栏
40 | data: [adsorbPolygon],
41 | // data: () => [adsorbPolygon] // 通过函数获取吸附物
42 | // data: 'drawData' // 开启时的默认吸附物, 吸附物为当前绘制的图形
43 | },
44 | // adsorbOptions: false // 默认,关闭吸附
45 | });
46 | ```
47 |
48 | ## 配置
49 |
50 | | 名称 | 说明 | 类型 | 默认值 |
51 | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------ |
52 | | data | 吸附对象,传入 `'drawData'` 表示吸附物为已有的绘制物,传入 `'allDrawData'` 表示吸附物为所有 Draw 实例的绘制物,也可以传入绘制物的 `GeoJSON` | `'drawData'` | `'allDrawData'`|`Feature[]`|`() => Feature[]` | `'drawData'` |
53 | | pointAdsorbPixel | 被吸附物上点吸附的像素值,当值 ≤ 0 时不吸附点 | `number` | `12` |
54 | | lineAdsorbPixel | 被吸附物上线吸附的像素值,当值 ≤ 0 时不吸附线 | `number` | `10` |
55 |
--------------------------------------------------------------------------------
/docs/docs/super/area.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 面积
3 | order: 3
4 | group:
5 | title: 高级
6 | order: 2
7 | path: /super
8 | ---
9 |
10 | ## 说明
11 |
12 | 用于展示面真实的面积
13 |
14 |
15 |
16 | ## 示例
17 |
18 | 距离文本配置是在各个 Draw 的 areaOptions 字段来进行配置的
19 |
20 | ```tsx | pure
21 | import { DrawPoint } from '@antv/l7-draw';
22 |
23 | const drawer = new DrawPoint(scene, {
24 | areaOptions: {
25 | format: (squareMeters: number, polygonFeature: Feature) => {
26 | return squareMeters > 1000000
27 | ? `${+(squareMeters / 1000000).toFixed(2)}km²`
28 | : `${+squareMeters.toFixed(2)}m²`;
29 | },
30 | },
31 | // 传false表示不展示文本,默认也为false
32 | // areaOptions: false,
33 | });
34 | ```
35 |
36 | ## 配置
37 |
38 | | 名称 | 说明 | 类型 | 默认值 |
39 | | ------ | ---------------------- | -------------------------------------------------------------------- | ------------------------------- |
40 | | format | 格式化面积平方米的函数 | `(squareMeters: number, polygonFeature: Feature) => string` | [见示例中的 format 方法](#示例) |
41 |
--------------------------------------------------------------------------------
/docs/docs/super/distance.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 距离
3 | order: 2
4 | group:
5 | title: 高级
6 | order: 2
7 | path: /super
8 | ---
9 |
10 | ## 说明
11 |
12 | 用于展示线段真实的距离长度
13 |
14 |
15 |
16 | ## 示例
17 |
18 | 距离文本配置是在各个 Draw 的 distanceOptions 字段来进行配置的
19 |
20 | ```tsx | pure
21 | import { DrawPoint } from '@antv/l7-draw';
22 |
23 | const drawer = new DrawPoint(scene, {
24 | distanceOptions: {
25 | showTotalDistance: false,
26 | showDashDistance: true,
27 | format: (meters, points: Feature[]) => {
28 | if (meters >= 1000) {
29 | return +(meters / 1000).toFixed(2) + 'km';
30 | } else {
31 | return +meters.toFixed(2) + 'm';
32 | }
33 | },
34 | },
35 | // 传false表示不展示文本,默认也为false
36 | // distanceOptions: false,
37 | });
38 | ```
39 |
40 | ## 配置
41 |
42 | | 名称 | 说明 | 类型 | 默认值 |
43 | | ----------------- | ---------------------------------------- | ------------------------------------------------------ | ------------------------------- |
44 | | showTotalDistance | 是否展示线段总长度,但是分段距离会不展示 | `boolean` | `false` |
45 | | showDashDistance | 是否展示虚线的长度 | `boolean` | `true` |
46 | | format | 格式化距离长度的函数 | `(meters: number, points: Feature[]) => string` | [见示例中的 format 方法](#示例) |
47 |
--------------------------------------------------------------------------------
/docs/docs/super/history.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 历史记录
3 | order: 5
4 | group:
5 | title: 高级
6 | order: 2
7 | path: /super
8 | ---
9 |
10 | ## 说明
11 |
12 | 默认情况下,Draw 会自动在主要操作(创建、编辑、拖拽、新增点等)后的绘制数据,自动保存在历史记录栈中,用户可以通过快捷键或者调用方法的方式进行 **↩️ 回退** 和 **↪️ 重做** 操作,对应的就是将历史记录栈中的数据进行还原至 Draw 中。
13 |
14 | 回退和重做操作默认分别通过[快捷键](/docs/super/keyboard) `ctrl/command + z` 和 `ctrl/command + shift + z` 来触发,也可以通过调用 Draw 实例中的方法 `revertHistory` 和 `redoHistory`来手动触发回退/重做操作。
15 |
16 | ## 示例
17 |
18 | ```tsx | pure
19 | import { DrawPoint } from '@antv/l7-draw';
20 |
21 | const drawer = new DrawPoint(scene, {
22 | // 历史记录栈相关的配置
23 | history: {
24 | maxSize: 100,
25 | },
26 | // 传false表示不开启历史记录的保存,同时也会导致回退/重做功能失效
27 | // history: false,
28 | });
29 |
30 | // 手动调用回退方法
31 | drawer.revertHistory();
32 | ```
33 |
34 | ## 配置
35 |
36 | | 名称 | 说明 | 类型 | 默认值 |
37 | | ------- | ---------------------------------------------------- | -------- | ------ |
38 | | maxSize | 保存历史记录的最大个数,超出时则把最早保存的记录剔除 | `number` | `100` |
39 |
--------------------------------------------------------------------------------
/docs/docs/super/keyboard.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 快捷操作
3 | order: 4
4 | group:
5 | title: 高级
6 | order: 2
7 | path: /super
8 | ---
9 |
10 | ## 说明
11 |
12 | 为了方便用户快速编辑绘制物,Draw 中内置了一系列快捷键。
13 |
14 | - ↩️ 回退:回退至上一次历史记录,默认使用 `command/ctrl + z`。
15 | - ↪️ 重做:撤销上一次回退,默认使用 `command/ctrl + shift + z`。
16 | - ❌ 删除:删除当前激活的绘制物,默认使用 `delete` 或 `backspace`。
17 |
18 | 用户可以选择关闭部分快捷键功能,或者自定义快捷键的按键。
19 |
20 | 除此之外,`L7Draw` 还提供了一些通过鼠标触发的快捷操作:
21 |
22 | - ⭕ 删除结点:删除当前节点,仅支持在 `DrawLine` 和 `DrawPolygon` 中使用,默认在 `鼠标右键单击节点` 时触发。
23 |
24 | ## 示例
25 |
26 | ```tsx | pure
27 | import { DrawPoint } from '@antv/l7-draw';
28 |
29 | const drawer = new DrawPoint(scene, {
30 | keyboard: {
31 | revert: ['command + z', 'ctrl + z'], // 覆盖默认回退快捷键按键
32 | remove: false, // false表示关闭当前删除快捷键功能
33 | },
34 | });
35 |
36 | // 当前快捷键对应的回调方法,开发中可以手动调用
37 |
38 | // 回退
39 | drawer.revertHistory();
40 |
41 | // 重做
42 | drawer.redoHistory();
43 |
44 | // 删除当前激活的绘制物
45 | drawer.removeActiveFeature();
46 | ```
47 |
48 | ## 配置
49 |
50 | | 名称 | 说明 | 类型 | 默认值 |
51 | | ------ | -------------------- | ------------------------- | --------------------------------------------- |
52 | | revert | 回退至上一次历史记录 | `string[]` | `false` | `['command + z', 'ctrl + z']` |
53 | | redo | 撤销上一次回退 | `string[]` | `false` | `['command + shift + z', 'ctrl + shift + z']` |
54 | | remove | 删除当前激活的绘制物 | `string[]` | `false` | `['del', 'backspace']` |
55 |
--------------------------------------------------------------------------------
/docs/docs/super/style.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon, getSingleColorStyle } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { Button } from 'antd';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | useEffect(() => {
11 | const newScene = new Scene({
12 | id,
13 | map: new GaodeMap({
14 | center: [120.151634, 30.244831],
15 | pitch: 0,
16 | style: 'dark',
17 | zoom: 10,
18 | }),
19 | });
20 | newScene.on('loaded', () => {
21 | const draw = new DrawPolygon(newScene, {
22 | style: getSingleColorStyle('#ff0000'),
23 | initialData: [
24 | {
25 | type: 'Feature',
26 | properties: {},
27 | geometry: {
28 | type: 'Polygon',
29 | coordinates: [
30 | [
31 | [120.107524, 30.257503],
32 | [120.153369, 30.255792],
33 | [120.162425, 30.237213],
34 | [120.112335, 30.228655],
35 | [120.107524, 30.257503],
36 | ],
37 | ],
38 | },
39 | },
40 | ],
41 | });
42 | draw.enable();
43 | });
44 | }, []);
45 |
46 | return ;
47 | };
48 |
49 | export default Demo;
50 |
--------------------------------------------------------------------------------
/docs/example/circle/area.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 展示距离和面积
3 | order: 3
4 | group:
5 | path: /circle
6 | title: 绘制圆
7 | order: 5
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/circle/area.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawCircle } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [circleDrawer, setCircleDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawCircle(scene, {
23 | distanceOptions: {},
24 | areaOptions: {},
25 | });
26 | setCircleDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/circle/autoActive.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关闭自动激活
3 | order: 3
4 | group:
5 | path: /circle
6 | title: 绘制圆
7 | order: 5
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/circle/autoActive.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawCircle } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [circleDrawer, setCircleDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawCircle(scene, {
24 | autoActive: false,
25 | });
26 | setCircleDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/circle/createByDrag.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 通过拖拽创建
3 | order: 2
4 | group:
5 | path: /circle
6 | title: 绘制圆
7 | order: 5
8 | ---
9 |
10 | 注意:配置 `trigger: 'drag'` 之后,只要 Drawer 在绘制状态下,就无法拖拽地图。如需开启拖拽,需要将调用 Drawer 的 disable 方法
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/example/circle/createByDrag.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawCircle } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [circleDrawer, setCircleDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawCircle(scene, {
24 | trigger: 'drag',
25 | });
26 | setCircleDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/circle/edges.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 绘制正多边形
3 | order: 3
4 | group:
5 | path: /circle
6 | title: 绘制圆
7 | order: 5
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/circle/edges.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawCircle } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [circleDrawer, setCircleDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawCircle(scene, {
23 | circleSteps: 6,
24 | });
25 | setCircleDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
34 | );
35 | };
36 |
37 | export default Demo;
38 |
--------------------------------------------------------------------------------
/docs/example/circle/editable.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 是否支持编辑
3 | order: 4
4 | group:
5 | path: /circle
6 | title: 绘制圆
7 | order: 5
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/circle/editable.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawCircle } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [circleDrawer, setCircleDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawCircle(scene, {
24 | editable: false,
25 | });
26 | setCircleDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/circle/event.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 监听绘制事件
3 | order: 7
4 | group:
5 | path: /circle
6 | title: 绘制圆
7 | order: 5
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/circle/event.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawCircle, DrawEvent } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [circleDrawer, setCircleDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawCircle(scene, {});
23 | setCircleDrawer(drawer);
24 | drawer.enable();
25 |
26 | // 监听添加Polygon的事件
27 | drawer.on(DrawEvent.Add, (newPolygon, polygonList) => {
28 | console.log('add', newPolygon, polygonList);
29 | });
30 |
31 | // 监听编辑Polygon(拖拽结束)的事件
32 | drawer.on(DrawEvent.Edit, (editPolygon, polygonList) => {
33 | console.log('edit', editPolygon, polygonList);
34 | });
35 |
36 | // 监听删除 Polygon 的事件
37 | drawer.on(DrawEvent.Remove, (removePolygon, polygonList) => {
38 | console.log('remove', removePolygon, polygonList);
39 | });
40 |
41 | // Polygon数据发生变更时触发,等价于同时监听add和edit事件
42 | drawer.on(DrawEvent.Change, (polygonList) => {
43 | console.log('change', polygonList);
44 | });
45 |
46 | // 拖拽开始
47 | drawer.on(DrawEvent.DragStart, (editPolygon, polygonList) => {
48 | console.log('dragStart', editPolygon, polygonList);
49 | });
50 |
51 | // 拖拽中
52 | drawer.on(DrawEvent.Dragging, (editPolygon, polygonList) => {
53 | console.log('dragging', editPolygon, polygonList);
54 | });
55 |
56 | // 拖拽结束
57 | drawer.on(DrawEvent.DragEnd, (editPolygon, polygonList) => {
58 | console.log('dragEnd', editPolygon, polygonList);
59 | });
60 | });
61 | }, []);
62 |
63 | return (
64 |
67 | );
68 | };
69 |
70 | export default Demo;
71 |
--------------------------------------------------------------------------------
/docs/example/circle/initialData.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 初始化数据
3 | order: 2
4 | group:
5 | path: /circle
6 | title: 绘制圆
7 | order: 5
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/circle/initialData.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawCircle, DrawEvent } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { circleList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [circleDrawer, setCircleDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawCircle(scene, {
24 | initialData: circleList,
25 | });
26 | setCircleDrawer(drawer);
27 | drawer.enable();
28 |
29 | // setTimeout(() => {
30 | // drawer.setData([
31 | // rectList[2]
32 | // ])
33 | // }, 1000)
34 |
35 | drawer.on(DrawEvent.Add, (e) => {});
36 | });
37 | }, []);
38 |
39 | return (
40 |
43 | );
44 | };
45 |
46 | export default Demo;
47 |
--------------------------------------------------------------------------------
/docs/example/circle/multiple.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁止绘制多个
3 | order: 5
4 | group:
5 | path: /circle
6 | title: 绘制圆
7 | order: 5
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/circle/multiple.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawCircle } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [circleDrawer, setCircleDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawCircle(scene, {
23 | multiple: false,
24 | });
25 | setCircleDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
34 | );
35 | };
36 |
37 | export default Demo;
38 |
--------------------------------------------------------------------------------
/docs/example/circle/start.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 快速开始
3 | order: 1
4 | group:
5 | path: /circle
6 | title: 绘制圆
7 | order: 5
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/circle/start.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawCircle } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { Button } from 'antd';
5 | import 'antd/dist/antd.css';
6 | import React, { useEffect, useState } from 'react';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [circleDrawer, setCircleDrawer] = useState(null);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 | scene.on('loaded', () => {
24 | const drawer = new DrawCircle(scene, {});
25 | setCircleDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | );
40 | };
41 |
42 | export default Demo;
43 |
--------------------------------------------------------------------------------
/docs/example/common/adsorb.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 吸附
3 | order: 2
4 | group:
5 | path: /common
6 | title: 通用配置
7 | order: 7
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/common/bbox.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: bbox
3 | order: 3
4 | group:
5 | path: /common
6 | title: 通用配置
7 | order: 7
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/common/bbox.tsx:
--------------------------------------------------------------------------------
1 | import { Scene, PolygonLayer } from '@antv/l7';
2 | import { DrawEvent, DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { Feature, bboxPolygon, featureCollection } from '@turf/turf';
5 | import 'antd/dist/antd.css';
6 | import React, { useEffect, useState } from 'react';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [polygonList, setPolygonList] = useState([]);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 | scene.on('loaded', () => {
24 | const drawer = new DrawPolygon(scene, {
25 | bbox: true,
26 | });
27 | drawer.enable();
28 |
29 | const polygonLayer = new PolygonLayer();
30 |
31 | polygonLayer
32 | .source(featureCollection([]))
33 | .shape('line')
34 | .size(2)
35 | .color('#fff')
36 | .style({
37 | opacity: 0.5,
38 | });
39 |
40 | scene.addLayer(polygonLayer);
41 |
42 | drawer.on(DrawEvent.Change, (newFeatures: Feature[]) => {
43 | setPolygonList(newFeatures);
44 |
45 | polygonLayer.setData(
46 | featureCollection(newFeatures.map((item) => bboxPolygon(item.bbox!))),
47 | );
48 | });
49 | });
50 | }, []);
51 |
52 | return (
53 |
54 |
55 |
56 | {JSON.stringify(
57 | polygonList.map((item) => item.bbox),
58 | null,
59 | 2,
60 | )}
61 |
62 |
63 | );
64 | };
65 |
66 | export default Demo;
67 |
--------------------------------------------------------------------------------
/docs/example/common/helper.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 绘制提示
3 | order: 1
4 | group:
5 | path: /common
6 | title: 通用配置
7 | order: 7
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/common/helper.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { Button } from 'antd';
5 | import 'antd/dist/antd.css';
6 | import React, { useEffect, useState } from 'react';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [polygonDrawer, setPolygonDrawer] = useState(null);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 | scene.on('loaded', () => {
24 | const container = document.createElement('div');
25 | container.innerHTML = '双击结束绘制
';
26 |
27 | // @ts-ignore
28 | const drawer = new DrawPolygon(scene, {
29 | // 绘制提示文案配置
30 | helper: {
31 | // 可以替换默认提示文案
32 | draw: '绘制第一个节点',
33 | drawContinue: '继续绘制节点',
34 |
35 | // 可以插入 DOM 元素
36 | drawFinish: container.firstElementChild ?? undefined,
37 | },
38 | // 弹框相关配置
39 | popup: {
40 | theme: 'dark',
41 | },
42 |
43 | // 关闭绘制提示
44 | // helper: false,
45 | });
46 | setPolygonDrawer(drawer);
47 | drawer.enable();
48 | });
49 | }, []);
50 |
51 | return (
52 |
53 |
54 |
62 |
63 |
64 |
65 | );
66 | };
67 |
68 | export default Demo;
69 |
--------------------------------------------------------------------------------
/docs/example/control/add.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 添加/移除 Control
3 | order: 2
4 | group:
5 | path: /control
6 | title: 绘制控制条
7 | order: 6
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/control/add.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { Button } from 'antd';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [scene, setScene] = useState(null);
11 | const [drawControl, setDrawControl] = useState(null);
12 |
13 | useEffect(() => {
14 | const newScene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 | newScene.on('loaded', () => {
24 | setScene(newScene);
25 | });
26 | }, []);
27 |
28 | /**
29 | * 添加 DrawControl
30 | */
31 | const onAdd = () => {
32 | if (!scene) {
33 | return;
34 | }
35 | // 实例化 DrawControl
36 | const newDrawControl = new DrawControl(scene, {});
37 | // 将 Control 添加至地图中
38 | scene.addControl(newDrawControl);
39 | setDrawControl(newDrawControl);
40 | };
41 |
42 | /**
43 | * 移除 DrawControl
44 | */
45 | const onRemove = () => {
46 | if (!scene || !drawControl) {
47 | return;
48 | }
49 | scene.removeControl(drawControl);
50 | };
51 |
52 | return (
53 |
54 |
55 |
58 |
59 |
60 |
61 |
62 | );
63 | };
64 |
65 | export default Demo;
66 |
--------------------------------------------------------------------------------
/docs/example/control/common.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 通用 Draw 配置
3 | order: 3
4 | group:
5 | path: /control
6 | title: 绘制控制条
7 | order: 6
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/control/common.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { ControlEvent } from '../../../src';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | // const [circleDrawer, setCircleDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const overwriteStyle = {
24 | color: '#a03dff',
25 | };
26 | // 实例化 DrawControl
27 | const drawControl = new DrawControl(scene, {
28 | // 支持传入所有 Draw 的通用配置,会在各个 Draw 实例化时传入
29 | commonDrawOptions: {
30 | editable: false,
31 | style: {
32 | point: {
33 | normal: overwriteStyle,
34 | hover: overwriteStyle,
35 | active: overwriteStyle,
36 | },
37 | line: {
38 | normal: overwriteStyle,
39 | hover: overwriteStyle,
40 | active: overwriteStyle,
41 | },
42 | polygon: {
43 | normal: overwriteStyle,
44 | hover: overwriteStyle,
45 | active: overwriteStyle,
46 | },
47 | midPoint: {
48 | normal: overwriteStyle,
49 | },
50 | dashLine: {
51 | normal: overwriteStyle,
52 | },
53 | text: {
54 | normal: overwriteStyle,
55 | active: overwriteStyle,
56 | },
57 | },
58 | },
59 | });
60 |
61 | // 将 Control 添加至地图中
62 | scene.addControl(drawControl);
63 | });
64 | }, []);
65 |
66 | return (
67 |
70 | );
71 | };
72 |
73 | export default Demo;
74 |
--------------------------------------------------------------------------------
/docs/example/control/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 自定义按钮
3 | order: 4
4 | group:
5 | path: /control
6 | title: 绘制控制条
7 | order: 6
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/control/custom.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | // const [circleDrawer, setCircleDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const customBtn = document.createElement('button');
23 | customBtn.classList.add('l7-draw-control__btn');
24 | customBtn.innerText = '✅';
25 | // 实例化 DrawControl
26 | const drawControl = new DrawControl(scene, {
27 | drawConfig: {
28 | point: {
29 | order: 1,
30 | },
31 | custom: {
32 | button: customBtn,
33 | order: 2,
34 | },
35 | },
36 | });
37 |
38 | // 将 Control 添加至地图中
39 | scene.addControl(drawControl);
40 | });
41 | }, []);
42 |
43 | return (
44 |
47 | );
48 | };
49 |
50 | export default Demo;
51 |
--------------------------------------------------------------------------------
/docs/example/control/draw.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 配置展示按钮
3 | order: 4
4 | group:
5 | path: /control
6 | title: 绘制控制条
7 | order: 6
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/control/draw.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | // const [circleDrawer, setCircleDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | // 实例化 DrawControl
23 | const drawControl = new DrawControl(scene, {
24 | defaultActiveType: 'point',
25 | drawConfig: {
26 | // 支持设置展示的绘制按钮,并传入绘制类实例化时的 options
27 | point: {
28 | autoActive: false,
29 | editable: false,
30 | style: {
31 | point: {
32 | normal: {
33 | color: '#6F17FF',
34 | },
35 | },
36 | },
37 | },
38 | clear: true,
39 | },
40 | });
41 |
42 | // 将 Control 添加至地图中
43 | scene.addControl(drawControl);
44 | });
45 | }, []);
46 |
47 | return (
48 |
51 | );
52 | };
53 |
54 | export default Demo;
55 |
--------------------------------------------------------------------------------
/docs/example/control/enable-by-click.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 通过点击元素激活
3 | order: 5
4 | group:
5 | path: /control
6 | title: 绘制控制条
7 | order: 6
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/control/enable-by-click.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect } from 'react';
5 | import { pointList } from '../point/mock';
6 | import { lineList } from '../line/mock';
7 | import { polygonList } from '../polygon/mock';
8 |
9 | const id = String(Math.random());
10 |
11 | const Demo: React.FC = () => {
12 | // const [circleDrawer, setCircleDrawer] = useState(null);
13 |
14 | useEffect(() => {
15 | const scene = new Scene({
16 | id,
17 | map: new GaodeMap({
18 | center: [120.151634, 30.244831],
19 | pitch: 0,
20 | style: 'dark',
21 | zoom: 10,
22 | }),
23 | });
24 | scene.on('loaded', () => {
25 | const customBtn = document.createElement('button');
26 | customBtn.classList.add('l7-draw-control__btn');
27 | customBtn.innerText = '✅';
28 | // 实例化 DrawControl
29 | const drawControl = new DrawControl(scene, {
30 | drawConfig: {
31 | point: {
32 | initialData: pointList,
33 | },
34 | line: {
35 | initialData: lineList,
36 | },
37 | polygon: {
38 | initialData: polygonList,
39 | },
40 | },
41 | });
42 |
43 | // 将 Control 添加至地图中
44 | scene.addControl(drawControl);
45 | });
46 | }, []);
47 |
48 | return (
49 |
52 | );
53 | };
54 |
55 | export default Demo;
56 |
--------------------------------------------------------------------------------
/docs/example/control/event.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 监听事件
3 | order: 10
4 | group:
5 | path: /control
6 | title: 绘制控制条
7 | order: 6
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/control/event.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl, ControlEvent } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | // const [circleDrawer, setCircleDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | // 实例化 DrawControl
23 | const drawControl = new DrawControl(scene, {
24 | defaultActiveType: 'point',
25 | });
26 |
27 | // 将 Control 添加至地图中
28 | scene.addControl(drawControl);
29 |
30 | drawControl.on(ControlEvent.DrawChange, (newType) => {
31 | console.log('当前激活的绘制发生更改', newType);
32 | });
33 |
34 | drawControl.on(ControlEvent.DataChange, (newData) => {
35 | console.log('当前绘制数据发生更改', newData);
36 | });
37 |
38 | drawControl.on(ControlEvent.DrawSelect, (drawType, feature) => {
39 | console.log('当前选中数据发生更改', drawType, feature);
40 | });
41 | });
42 | }, []);
43 |
44 | return (
45 |
48 | );
49 | };
50 |
51 | export default Demo;
52 |
--------------------------------------------------------------------------------
/docs/example/control/start.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 快速使用
3 | order: 1
4 | group:
5 | path: /control
6 | title: 绘制控制条
7 | order: 6
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/control/start.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl, getSingleColorStyle } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | // const [circleDrawer, setCircleDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | // 实例化 DrawControl
23 | const drawControl = new DrawControl(scene, {
24 | defaultActiveType: 'point',
25 | commonDrawOptions: {
26 | style: getSingleColorStyle('#ff0000'),
27 | },
28 | });
29 |
30 | // 将 Control 添加至地图中
31 | scene.addControl(drawControl);
32 | });
33 | }, []);
34 |
35 | return (
36 |
39 | );
40 | };
41 |
42 | export default Demo;
43 |
--------------------------------------------------------------------------------
/docs/example/line/adsorb.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 吸附能力
3 | order: 6
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/line/adsorb.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [lineDrawer, setLineDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawLine(scene, {
23 | adsorbOptions: {},
24 | });
25 | setLineDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
34 | );
35 | };
36 |
37 | export default Demo;
38 |
--------------------------------------------------------------------------------
/docs/example/line/autoActive.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关闭自动激活
3 | order: 5
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/line/autoActive.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [lineDrawer, setLineDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawLine(scene, {
24 | autoActive: false,
25 | });
26 | setLineDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/line/createByDrag.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 通过拖拽创建
3 | order: 2
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 | 注意:配置 `trigger: 'drag'` 之后,只要 Drawer 在绘制状态下,就无法拖拽地图。如需开启拖拽,需要将调用 Drawer 的 disable 方法
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/example/line/createByDrag.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [rectDrawer, setRectDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawLine(scene, {
24 | trigger: 'drag',
25 | dragOptions: {
26 | dotDuration: 100,
27 | dotDistance: 30,
28 | },
29 | });
30 | setRectDrawer(drawer);
31 | drawer.enable();
32 | });
33 | }, []);
34 |
35 | return (
36 |
39 | );
40 | };
41 |
42 | export default Demo;
43 |
--------------------------------------------------------------------------------
/docs/example/line/distance.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 展示距离
3 | order: 3
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/line/distance.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [lineDrawer, setLineDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawLine(scene, {
23 | distanceOptions: {},
24 | });
25 | setLineDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
34 | );
35 | };
36 |
37 | export default Demo;
38 |
--------------------------------------------------------------------------------
/docs/example/line/editable.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁用编辑
3 | order: 6
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/line/editable.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { lineList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [lineDrawer, setLineDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawLine(scene, {
24 | editable: false, // 禁用编辑
25 | initialData: lineList,
26 | });
27 | setLineDrawer(drawer);
28 | drawer.enable();
29 | });
30 | }, []);
31 |
32 | return (
33 |
36 | );
37 | };
38 |
39 | export default Demo;
40 |
--------------------------------------------------------------------------------
/docs/example/line/event.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 监听绘制事件
3 | order: 7
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/line/event.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [lineDrawer, setLineDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawLine(scene, {});
23 | setLineDrawer(drawer);
24 | drawer.enable();
25 |
26 | // 监听添加LineString的事件
27 | drawer.on(DrawEvent.Add, (newLine, lineList) => {
28 | console.log('add', newLine, lineList);
29 | });
30 |
31 | // 监听编辑LineString(拖拽结束)的事件
32 | drawer.on(DrawEvent.Edit, (editLine, lineList) => {
33 | console.log('edit', editLine, lineList);
34 | });
35 |
36 | // 监听删除 LineString 的事件
37 | drawer.on(DrawEvent.Remove, (removePolygon, polygonList) => {
38 | console.log('remove', removePolygon, polygonList);
39 | });
40 |
41 | // 监听添加结点的事件
42 | drawer.on(DrawEvent.AddNode, (node, editLine, lineList) => {
43 | console.log('addNode', node, editLine, lineList);
44 | });
45 |
46 | // 监听添加结点的事件
47 | drawer.on(DrawEvent.RemoveNode, (node, editLine, lineList) => {
48 | console.log('removeNode', node, editLine, lineList);
49 | });
50 |
51 | // LineString数据发生变更时触发,等价于同时监听add和edit事件
52 | drawer.on(DrawEvent.Change, (lineList) => {
53 | console.log('change', lineList);
54 | });
55 |
56 | // 拖拽开始
57 | drawer.on(DrawEvent.DragStart, (editLine, lineList) => {
58 | console.log('dragStart', editLine, lineList);
59 | });
60 |
61 | // 拖拽中
62 | drawer.on(DrawEvent.Dragging, (editLine, lineList) => {
63 | console.log('dragging', editLine, lineList);
64 | });
65 |
66 | // 拖拽结束
67 | drawer.on(DrawEvent.DragEnd, (editLine, lineList) => {
68 | console.log('dragEnd', editLine, lineList);
69 | });
70 | });
71 | }, []);
72 |
73 | return (
74 |
77 | );
78 | };
79 |
80 | export default Demo;
81 |
--------------------------------------------------------------------------------
/docs/example/line/initialData.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 初始化数据
3 | order: 2
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/example/line/initialData.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { lineList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [lineDrawer, setLineDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawLine(scene, {
24 | initialData: lineList,
25 | });
26 | setLineDrawer(drawer);
27 | drawer.enable();
28 |
29 | drawer.on(DrawEvent.Add, (e) => {});
30 | });
31 | }, []);
32 |
33 | return (
34 |
37 | );
38 | };
39 |
40 | export default Demo;
41 |
--------------------------------------------------------------------------------
/docs/example/line/initialData1.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { multiLineList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [lineDrawer, setLineDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawLine(scene, {
24 | initialData: multiLineList,
25 | });
26 | setLineDrawer(drawer);
27 | drawer.enable();
28 |
29 | drawer.on(DrawEvent.Change, console.log);
30 | });
31 | }, []);
32 |
33 | return (
34 |
37 | );
38 | };
39 |
40 | export default Demo;
41 |
--------------------------------------------------------------------------------
/docs/example/line/midPoint.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁用中点
3 | order: 4
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/line/midPoint.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { cloneDeep } from 'lodash';
5 | import React, { useEffect, useState } from 'react';
6 | import { lineList } from './mock';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [lineDrawer, setLineDrawer] = useState(null);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 |
24 | const line = cloneDeep(lineList);
25 |
26 | if (line[0].properties) {
27 | line[0].properties.isActive = true;
28 | }
29 |
30 | scene.on('loaded', () => {
31 | const drawer = new DrawLine(scene, {
32 | showMidPoint: false,
33 | initialData: line,
34 | });
35 | setLineDrawer(drawer);
36 | drawer.enable();
37 | });
38 | }, []);
39 |
40 | return (
41 |
44 | );
45 | };
46 |
47 | export default Demo;
48 |
--------------------------------------------------------------------------------
/docs/example/line/mock.ts:
--------------------------------------------------------------------------------
1 | import { Feature, LineString, MultiLineString } from '@turf/turf';
2 |
3 | export const lineList: Feature[] = [
4 | {
5 | type: 'Feature',
6 | properties: {},
7 | geometry: {
8 | type: 'LineString',
9 | coordinates: [
10 | [119.988511, 30.269614],
11 | [119.9851, 30.269323],
12 | [119.985438, 30.267852],
13 | [119.990291, 30.267257],
14 | [119.991454, 30.261762],
15 | [119.994974, 30.256115],
16 | [119.983641, 30.246146],
17 | [119.985286, 30.241228],
18 | [119.983351, 30.224089],
19 | [119.985473, 30.221814],
20 | [119.99271, 30.22088],
21 | ],
22 | },
23 | },
24 | {
25 | type: 'Feature',
26 | properties: {},
27 | geometry: {
28 | type: 'LineString',
29 | coordinates: [
30 | [120.075427, 30.147148],
31 | [120.073659, 30.147609],
32 | [120.074996, 30.154115],
33 | [120.070946, 30.160916],
34 | [120.074171, 30.161745],
35 | [120.075425, 30.158086],
36 | [120.081662, 30.159401],
37 | [120.084335, 30.163868],
38 | [120.112648, 30.17977],
39 | [120.119262, 30.186753],
40 | [120.137108, 30.198481],
41 | [120.137962, 30.202496],
42 | [120.135039, 30.208876],
43 | [120.135625, 30.216541],
44 | [120.138548, 30.225005],
45 | [120.145412, 30.229088],
46 | [120.155609, 30.230104],
47 | [120.158572, 30.241788],
48 | [120.160816, 30.245725],
49 | [120.16441, 30.245929],
50 | [120.164401, 30.247589],
51 | [120.165608, 30.247515],
52 | [120.166546, 30.254134],
53 | ],
54 | },
55 | },
56 | {
57 | type: 'Feature',
58 | properties: {},
59 | geometry: {
60 | type: 'LineString',
61 | coordinates: [
62 | [120.216401, 30.291456],
63 | [120.217689, 30.289456],
64 | [120.218912, 30.28995],
65 | [120.216862, 30.292565],
66 | [120.221055, 30.293611],
67 | [120.221909, 30.291061],
68 | [120.211464, 30.28603],
69 | [120.207209, 30.278355],
70 | [120.207448, 30.270482],
71 | [120.199987, 30.270352],
72 | [120.200252, 30.247617],
73 | [120.210037, 30.243515],
74 | [120.204483, 30.237082],
75 | [120.224585, 30.222153],
76 | [120.213219, 30.213984],
77 | [120.216402, 30.20977],
78 | [120.194058, 30.196853],
79 | [120.17329, 30.188212],
80 | [120.174223, 30.181411],
81 | [120.16777, 30.181168],
82 | [120.167244, 30.173706],
83 | [120.147426, 30.172062],
84 | [120.146042, 30.176801],
85 | [120.135382, 30.17619],
86 | ],
87 | },
88 | },
89 | ];
90 |
91 | export const multiLineList: Feature[] = [
92 | {
93 | type: 'Feature',
94 | properties: {},
95 | geometry: {
96 | type: 'MultiLineString',
97 | coordinates: [
98 | [
99 | [120.023854, 30.309834],
100 | [120.027542, 30.162633],
101 | [120.090236, 30.170923],
102 | [120.111625, 30.053525],
103 | ],
104 | [
105 | [120.20671, 30.277609],
106 | [120.174986, 30.151506],
107 | [120.25218, 30.106691],
108 | ],
109 | ],
110 | },
111 | },
112 | ];
113 |
--------------------------------------------------------------------------------
/docs/example/line/multiple.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁止绘制多个
3 | order: 5
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/line/multiple.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [lineDrawer, setLineDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawLine(scene, {
23 | multiple: false,
24 | });
25 | setLineDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
34 | );
35 | };
36 |
37 | export default Demo;
38 |
--------------------------------------------------------------------------------
/docs/example/line/start.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 快速开始
3 | order: 1
4 | group:
5 | path: /line
6 | title: 绘制线
7 | order: 2
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/line/start.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawLine } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { Button } from 'antd';
5 | import 'antd/dist/antd.css';
6 | import React, { useEffect, useState } from 'react';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [lineDrawer, setLineDrawer] = useState(null);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 | scene.on('loaded', () => {
24 | const drawer = new DrawLine(scene, {});
25 | setLineDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | );
40 | };
41 |
42 | export default Demo;
43 |
--------------------------------------------------------------------------------
/docs/example/map/baidu.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 百度地图
3 | order: 3
4 | group:
5 | path: /map
6 | title: 底图
7 | order: 8
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/map/baidu.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import { BaiduMap } from '@antv/l7-maps';
4 | import React, { useEffect } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | useEffect(() => {
10 | const scene = new Scene({
11 | id,
12 | map: new BaiduMap({
13 | center: [107.054293, 35.246265],
14 | zoom: 4.056,
15 | style: 'c17b1c2b528429a7b04bbc8d3eb8bae9',
16 | // 百度地图的logo是否可见,默认true
17 | logoVisible: false,
18 | }),
19 | });
20 | scene.on('loaded', () => {
21 | const drawControl = new DrawControl(scene, {});
22 |
23 | // 将 Control 添加至地图中
24 | scene.addControl(drawControl);
25 | });
26 | }, []);
27 |
28 | return (
29 |
32 | );
33 | };
34 |
35 | export default Demo;
36 |
--------------------------------------------------------------------------------
/docs/example/map/gaode.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 高德地图
3 | order: 1
4 | group:
5 | path: /map
6 | title: 底图
7 | order: 8
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/map/gaode.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | useEffect(() => {
10 | const scene = new Scene({
11 | id,
12 | map: new GaodeMap({
13 | center: [107.054293, 35.246265],
14 | zoom: 4.056,
15 | }),
16 | });
17 | scene.on('loaded', () => {
18 | const drawControl = new DrawControl(scene, {});
19 |
20 | // 将 Control 添加至地图中
21 | scene.addControl(drawControl);
22 | });
23 | }, []);
24 |
25 | return (
26 |
29 | );
30 | };
31 |
32 | export default Demo;
33 |
--------------------------------------------------------------------------------
/docs/example/map/mapbox.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Mapbox
3 | order: 2
4 | group:
5 | path: /map
6 | title: 底图
7 | order: 8
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/map/mapbox.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import { Mapbox } from '@antv/l7-maps';
4 | import React, { useEffect } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | useEffect(() => {
10 | const scene = new Scene({
11 | id,
12 | map: new Mapbox({
13 | center: [107.054293, 35.246265],
14 | zoom: 4.056,
15 | token:
16 | 'pk.eyJ1IjoibGl1dmlnb25nenVvc2hpIiwiYSI6ImNsaGs2czBrcTBvczUzbnFzOHU0dzk2ZWQifQ.hVvTgcbg_Ym-VQz36psLRg',
17 | }),
18 | });
19 | scene.on('loaded', () => {
20 | const drawControl = new DrawControl(scene, {});
21 |
22 | // 将 Control 添加至地图中
23 | scene.addControl(drawControl);
24 | });
25 | }, []);
26 |
27 | return (
28 |
31 | );
32 | };
33 |
34 | export default Demo;
35 |
--------------------------------------------------------------------------------
/docs/example/map/tencent.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 腾讯地图
3 | order: 4
4 | group:
5 | path: /map
6 | title: 底图
7 | order: 8
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/map/tencent.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import { TencentMap } from '@antv/l7-maps';
4 | import React, { useEffect } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | useEffect(() => {
10 | const scene = new Scene({
11 | id,
12 | map: new TencentMap({
13 | center: [107.054293, 35.246265],
14 | zoom: 4.056,
15 | style: 'style1',
16 | }),
17 | });
18 | scene.on('loaded', () => {
19 | const drawControl = new DrawControl(scene, {});
20 | // 将 Control 添加至地图中
21 | scene.addControl(drawControl);
22 | });
23 | }, []);
24 |
25 | return (
26 |
29 | );
30 | };
31 |
32 | export default Demo;
33 |
--------------------------------------------------------------------------------
/docs/example/map/tianditu.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 天地图
3 | order: 5
4 | group:
5 | path: /map
6 | title: 底图
7 | order: 8
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/map/tianditu.tsx:
--------------------------------------------------------------------------------
1 | import { Scene, TMap } from '@antv/l7';
2 | import { DrawControl } from '@antv/l7-draw';
3 | import React, { useEffect } from 'react';
4 |
5 | const id = String(Math.random());
6 |
7 | const Demo: React.FC = () => {
8 | useEffect(() => {
9 | const scene = new Scene({
10 | id,
11 | map: new TMap({
12 | center: [107.054293, 35.246265],
13 | zoom: 4.056,
14 | style: 'style1',
15 | }),
16 | });
17 | scene.on('loaded', () => {
18 | const drawControl = new DrawControl(scene, {});
19 | // 将 Control 添加至地图中
20 | scene.addControl(drawControl);
21 | });
22 | }, []);
23 |
24 | return (
25 |
28 | );
29 | };
30 |
31 | export default Demo;
32 |
--------------------------------------------------------------------------------
/docs/example/point/autoActive.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关闭自动激活
3 | order: 5
4 | group:
5 | path: /point
6 | title: 绘制点
7 | order: 1
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/point/autoActive.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPoint } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [pointDrawer, setPointDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPoint(scene, {
24 | autoActive: false,
25 | });
26 | setPointDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/point/editable.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁用编辑
3 | order: 6
4 | group:
5 | path: /point
6 | title: 绘制点
7 | order: 1
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/point/editable.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPoint } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { pointList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [pointDrawer, setPointDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPoint(scene, {
24 | editable: false, // 禁用编辑
25 | initialData: pointList,
26 | });
27 | setPointDrawer(drawer);
28 | drawer.enable();
29 | });
30 | }, []);
31 |
32 | return (
33 |
36 | );
37 | };
38 |
39 | export default Demo;
40 |
--------------------------------------------------------------------------------
/docs/example/point/event.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 监听绘制事件
3 | order: 7
4 | group:
5 | path: /point
6 | title: 绘制点
7 | order: 1
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/point/event.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawPoint } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [pointDrawer, setPointDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawPoint(scene, {});
23 | setPointDrawer(drawer);
24 | drawer.enable();
25 |
26 | // 监听添加Point的事件
27 | drawer.on(DrawEvent.Add, (newPoint, pointList) => {
28 | console.log('add', newPoint, pointList);
29 | });
30 |
31 | // 监听编辑Point(拖拽结束)的事件
32 | drawer.on(DrawEvent.Edit, (editPoint, pointList) => {
33 | console.log('edit', editPoint, pointList);
34 | });
35 |
36 | // 删除 Point 的事件
37 | drawer.on(DrawEvent.Remove, (removePoint, pointList) => {
38 | console.log('remove', removePoint, pointList);
39 | });
40 |
41 | // Point数据发生变更时触发,等价于同时监听add和edit事件
42 | drawer.on(DrawEvent.Change, (pointList) => {
43 | console.log('change', pointList);
44 | });
45 |
46 | // 拖拽开始
47 | drawer.on(DrawEvent.DragStart, (editPoint, pointList) => {
48 | console.log('dragStart', editPoint, pointList);
49 | });
50 |
51 | // 拖拽中
52 | drawer.on(DrawEvent.Dragging, (editPoint, pointList) => {
53 | console.log('dragging', editPoint, pointList);
54 | });
55 |
56 | // 拖拽结束
57 | drawer.on(DrawEvent.DragEnd, (editPoint, pointList) => {
58 | console.log('dragEnd', editPoint, pointList);
59 | });
60 | });
61 | }, []);
62 |
63 | return (
64 |
67 | );
68 | };
69 |
70 | export default Demo;
71 |
--------------------------------------------------------------------------------
/docs/example/point/image.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 使用图片
3 | order: 3
4 | group:
5 | path: /point
6 | title: 绘制点
7 | order: 1
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/point/image.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPoint } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [pointDrawer, setPointDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | scene.addImage(
23 | 'dingwei',
24 | 'https://gw.alipayobjects.com/mdn/rms_3bf4aa/afts/img/A*JL46TZ_iYB0AAAAAAAAAAAAAARQnAQ',
25 | );
26 |
27 | const drawer = new DrawPoint(scene, {
28 | style: {
29 | point: {
30 | normal: { shape: 'dingwei', size: 10 },
31 | hover: { shape: 'dingwei', size: 20, color: '#1990FF' },
32 | active: { shape: 'dingwei', size: 20 },
33 | },
34 | },
35 | });
36 | setPointDrawer(drawer);
37 | drawer.enable();
38 | });
39 | }, []);
40 |
41 | return (
42 |
45 | );
46 | };
47 |
48 | export default Demo;
49 |
--------------------------------------------------------------------------------
/docs/example/point/initialData.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 初始化数据
3 | order: 2
4 | group:
5 | path: /point
6 | title: 绘制点
7 | order: 1
8 | ---
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/example/point/initialData.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPoint } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { pointList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [pointDrawer, setPointDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPoint(scene, {
24 | initialData: pointList,
25 | });
26 | setPointDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/point/initialData1.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawPoint } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { multiPointList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [pointDrawer, setPointDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPoint(scene, {
24 | initialData: multiPointList,
25 | });
26 | setPointDrawer(drawer);
27 | drawer.enable();
28 |
29 | drawer.on(DrawEvent.Change, console.log);
30 | });
31 | }, []);
32 |
33 | return ;
34 | };
35 |
36 | export default Demo;
37 |
--------------------------------------------------------------------------------
/docs/example/point/mock.ts:
--------------------------------------------------------------------------------
1 | import { Feature, MultiPoint, Point } from '@turf/turf';
2 |
3 | export const pointList: Feature[] = [
4 | {
5 | type: 'Feature',
6 | properties: {},
7 | geometry: {
8 | type: 'Point',
9 | coordinates: [120.103666, 30.262449],
10 | },
11 | },
12 | {
13 | type: 'Feature',
14 | properties: {},
15 | geometry: {
16 | type: 'Point',
17 | coordinates: [120.12, 30.262449],
18 | },
19 | },
20 | ];
21 |
22 | export const multiPointList: Feature[] = [
23 | {
24 | type: 'Feature',
25 | properties: {},
26 | geometry: {
27 | type: 'MultiPoint',
28 | coordinates: [
29 | [119.99837899999996, 30.155454000000002],
30 | [119.99837899999996, 30.328756999999992],
31 | [120.282943, 30.328756999999992],
32 | [120.282943, 30.155454000000002],
33 | ],
34 | },
35 | },
36 | ];
37 |
--------------------------------------------------------------------------------
/docs/example/point/multiple.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁止绘制多个
3 | order: 5
4 | group:
5 | path: /point
6 | title: 绘制点
7 | order: 1
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/point/multiple.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPoint } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [pointDrawer, setPointDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawPoint(scene, {
23 | multiple: false,
24 | });
25 | setPointDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
34 | );
35 | };
36 |
37 | export default Demo;
38 |
--------------------------------------------------------------------------------
/docs/example/point/start.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 快速开始
3 | order: 1
4 | group:
5 | path: /point
6 | title: 绘制点
7 | order: 1
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/point/start.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPoint } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { Button } from 'antd';
5 | import 'antd/dist/antd.css';
6 | import React, { useEffect, useState } from 'react';
7 |
8 | const Demo: React.FC = () => {
9 | const [pointDrawer, setPointDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id: 'map',
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | token: '5ae4492ef912cbbc93034fea0e66ff2a',
18 | style: 'amap://styles/6a4114a0dc821c17bb74e4f730413e01',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPoint(scene, {});
24 | setPointDrawer(drawer);
25 | drawer.enable();
26 | });
27 | }, []);
28 |
29 | return (
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | );
39 | };
40 |
41 | export default Demo;
42 |
--------------------------------------------------------------------------------
/docs/example/point/style.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 自定义样式
3 | order: 4
4 | group:
5 | path: /point
6 | title: 绘制点
7 | order: 1
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/point/style.tsx:
--------------------------------------------------------------------------------
1 | import { ILayer, Scene } from '@antv/l7';
2 | import { DrawPoint, IPointStyleItem } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [pointDrawer, setPointDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const overwriteStyle: Partial = {
24 | color: '#0000ff',
25 | size: 8,
26 | shape: 'square',
27 | };
28 |
29 | const drawer = new DrawPoint(scene, {
30 | style: {
31 | point: {
32 | normal: overwriteStyle,
33 | hover: {
34 | ...overwriteStyle,
35 | size: 12,
36 | },
37 | active: {
38 | ...overwriteStyle,
39 | size: 12,
40 | color: '#ff0000',
41 | },
42 | callback: (layers: ILayer[]) => {
43 | // 对layers进行函数式设置样式
44 | },
45 | },
46 | },
47 | });
48 | setPointDrawer(drawer);
49 | drawer.enable();
50 | });
51 | }, []);
52 |
53 | return (
54 |
57 | );
58 | };
59 |
60 | export default Demo;
61 |
--------------------------------------------------------------------------------
/docs/example/polygon/adsorb.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 吸附能力
3 | order: 5
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/polygon/adsorb.tsx:
--------------------------------------------------------------------------------
1 | import { PointLayer, Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 | import { polygonList } from './mock';
7 | import { Feature, featureCollection } from '@turf/turf';
8 |
9 | const id = String(Math.random());
10 |
11 | const Demo: React.FC = () => {
12 | const [polygonDrawer, setPolygonDrawer] = useState(null);
13 |
14 | useEffect(() => {
15 | const scene = new Scene({
16 | id,
17 | map: new GaodeMap({
18 | center: [120.151634, 30.244831],
19 | pitch: 0,
20 | style: 'dark',
21 | zoom: 10,
22 | }),
23 | });
24 | scene.on('loaded', () => {
25 | const drawer = new DrawPolygon(scene, {
26 | adsorbOptions: {},
27 | });
28 | setPolygonDrawer(drawer);
29 | drawer.enable();
30 | });
31 | }, []);
32 |
33 | return (
34 |
37 | );
38 | };
39 |
40 | export default Demo;
41 |
--------------------------------------------------------------------------------
/docs/example/polygon/area.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 展示距离和面积
3 | order: 3
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/polygon/area.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [polygonDrawer, setPolygonDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawPolygon(scene, {
23 | distanceOptions: {},
24 | areaOptions: {},
25 | liveUpdate: true,
26 | });
27 | setPolygonDrawer(drawer);
28 | drawer.enable();
29 | });
30 | }, []);
31 |
32 | return (
33 |
36 | );
37 | };
38 |
39 | export default Demo;
40 |
--------------------------------------------------------------------------------
/docs/example/polygon/autoActive.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关闭自动激活
3 | order: 4
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/polygon/autoActive.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [polygonDrawer, setPolygonDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPolygon(scene, {
24 | autoActive: false,
25 | });
26 | setPolygonDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/polygon/createByDrag.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 通过拖拽创建
3 | order: 2
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 | 注意:配置 `trigger: 'drag'` 之后,只要 Drawer 在绘制状态下,就无法拖拽地图。如需开启拖拽,需要将调用 Drawer 的 disable 方法
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/example/polygon/createByDrag.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [rectDrawer, setRectDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPolygon(scene, {
24 | trigger: 'drag',
25 | dragOptions: {
26 | dotDuration: 100,
27 | dotDistance: 30,
28 | },
29 | });
30 | setRectDrawer(drawer);
31 | drawer.enable();
32 | });
33 | }, []);
34 |
35 | return (
36 |
39 | );
40 | };
41 |
42 | export default Demo;
43 |
--------------------------------------------------------------------------------
/docs/example/polygon/editable.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁用编辑
3 | order: 5
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/polygon/editable.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 | import { polygonList } from './mock';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [polygonDrawer, setPolygonDrawer] = useState(null);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 | scene.on('loaded', () => {
24 | const drawer = new DrawPolygon(scene, {
25 | initialData: polygonList,
26 | editable: false,
27 | });
28 | setPolygonDrawer(drawer);
29 | drawer.enable();
30 | });
31 | }, []);
32 |
33 | return (
34 |
37 | );
38 | };
39 |
40 | export default Demo;
41 |
--------------------------------------------------------------------------------
/docs/example/polygon/event.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 监听绘制事件
3 | order: 6
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/polygon/event.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [polygonDrawer, setPolygonDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawPolygon(scene, {});
23 | setPolygonDrawer(drawer);
24 | drawer.enable();
25 |
26 | // 监听添加Polygon的事件
27 | drawer.on(DrawEvent.Add, (newPolygon, polygonList) => {
28 | console.log('add', newPolygon, polygonList);
29 | });
30 |
31 | // 监听编辑Polygon(拖拽结束)的事件
32 | drawer.on(DrawEvent.Edit, (editPolygon, polygonList) => {
33 | console.log('edit', editPolygon, polygonList);
34 | });
35 |
36 | // 监听删除 Polygon 的事件
37 | drawer.on(DrawEvent.Remove, (removePolygon, polygonList) => {
38 | console.log('remove', removePolygon, polygonList);
39 | });
40 |
41 | // 监听添加结点的事件
42 | drawer.on(DrawEvent.AddNode, (node, editPoint, polygonList) => {
43 | console.log('addNode', node, editPoint, polygonList);
44 | });
45 |
46 | // 监听添加结点的事件
47 | drawer.on(DrawEvent.RemoveNode, (node, editLine, lineList) => {
48 | console.log('removeNode', node, editLine, lineList);
49 | });
50 |
51 | // Polygon数据发生变更时触发,等价于同时监听add和edit事件
52 | drawer.on(DrawEvent.Change, (polygonList) => {
53 | console.log('change', polygonList);
54 | });
55 |
56 | // 拖拽开始
57 | drawer.on(DrawEvent.DragStart, (editPolygon, polygonList) => {
58 | console.log('dragStart', editPolygon, polygonList);
59 | });
60 |
61 | // 拖拽中
62 | drawer.on(DrawEvent.Dragging, (editPolygon, polygonList) => {
63 | console.log('dragging', editPolygon, polygonList);
64 | });
65 |
66 | // 拖拽结束
67 | drawer.on(DrawEvent.DragEnd, (editPolygon, polygonList) => {
68 | console.log('dragEnd', editPolygon, polygonList);
69 | });
70 | });
71 | }, []);
72 |
73 | return (
74 |
77 | );
78 | };
79 |
80 | export default Demo;
81 |
--------------------------------------------------------------------------------
/docs/example/polygon/initialData.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 初始化数据
3 | order: 2
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/example/polygon/initialData.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { polygonList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [polygonDrawer, setPolygonDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPolygon(scene, {
24 | initialData: polygonList,
25 | });
26 | setPolygonDrawer(drawer);
27 | drawer.enable();
28 |
29 | drawer.on(DrawEvent.Add, (e) => {});
30 | });
31 | }, []);
32 |
33 | return (
34 |
37 | );
38 | };
39 |
40 | export default Demo;
41 |
--------------------------------------------------------------------------------
/docs/example/polygon/initialData1.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { multiPolygonList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [polygonDrawer, setPolygonDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPolygon(scene, {
24 | initialData: multiPolygonList,
25 | });
26 | setPolygonDrawer(drawer);
27 | drawer.enable();
28 |
29 | drawer.on(DrawEvent.Change, console.log);
30 | });
31 | }, []);
32 |
33 | return (
34 |
37 | );
38 | };
39 |
40 | export default Demo;
41 |
--------------------------------------------------------------------------------
/docs/example/polygon/midPoint.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁用中点
3 | order: 4
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/polygon/midPoint.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { cloneDeep } from 'lodash';
5 | import React, { useEffect, useState } from 'react';
6 | import { polygonList } from './mock';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [polygonDrawer, setPolygonDrawer] = useState(null);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 |
24 | const polygon = cloneDeep(polygonList);
25 |
26 | if (polygon[0].properties) {
27 | polygon[0].properties.isActive = true;
28 | }
29 |
30 | scene.on('loaded', () => {
31 | const drawer = new DrawPolygon(scene, {
32 | showMidPoint: false,
33 | initialData: polygon,
34 | });
35 | setPolygonDrawer(drawer);
36 | drawer.enable();
37 | });
38 | }, []);
39 |
40 | return (
41 |
44 | );
45 | };
46 |
47 | export default Demo;
48 |
--------------------------------------------------------------------------------
/docs/example/polygon/mock.ts:
--------------------------------------------------------------------------------
1 | import { Feature, MultiPolygon, Polygon } from '@turf/turf';
2 |
3 | export const polygonList: Feature[] = [
4 | {
5 | type: 'Feature',
6 | properties: {},
7 | geometry: {
8 | type: 'Polygon',
9 | coordinates: [
10 | [
11 | [120.10116577148436, 30.292867742612255],
12 | [120.08949279785156, 30.216058476325074],
13 | [120.15781402587892, 30.207751175495517],
14 | [120.17051696777344, 30.277154904692335],
15 | [120.10597229003906, 30.325174912575307],
16 | [120.10116577148436, 30.292867742612255],
17 | ],
18 | ],
19 | },
20 | },
21 | {
22 | type: 'Feature',
23 | properties: {},
24 | geometry: {
25 | type: 'Polygon',
26 | coordinates: [
27 | [
28 | [120.02357482910155, 30.24839093066276],
29 | [120.06889343261717, 30.24839093066276],
30 | [120.06889343261717, 30.29790717639933],
31 | [120.02357482910155, 30.29790717639933],
32 | [120.02357482910155, 30.24839093066276],
33 | ],
34 | ],
35 | },
36 | },
37 | {
38 | type: 'Feature',
39 | properties: {},
40 | geometry: {
41 | type: 'Polygon',
42 | coordinates: [
43 | [
44 | [120.18287658691406, 30.316284093102404],
45 | [120.18424987792969, 30.285159872426014],
46 | [120.20450592041017, 30.275968928008236],
47 | [120.20862579345703, 30.2907926063742],
48 | [120.18287658691406, 30.316284093102404],
49 | ],
50 | ],
51 | },
52 | },
53 | ];
54 |
55 | export const multiPolygonList: Feature[] = [
56 | {
57 | type: 'Feature',
58 | properties: {},
59 | geometry: {
60 | type: 'MultiPolygon',
61 | coordinates: [
62 | [
63 | [
64 | [120.18287658691406, 30.316284093102404],
65 | [120.18424987792969, 30.285159872426014],
66 | [120.20450592041017, 30.275968928008236],
67 | [120.20862579345703, 30.2907926063742],
68 | [120.18287658691406, 30.316284093102404],
69 | ],
70 | ],
71 | [
72 | [
73 | [120.02357482910155, 30.24839093066276],
74 | [120.06889343261717, 30.24839093066276],
75 | [120.06889343261717, 30.29790717639933],
76 | [120.02357482910155, 30.29790717639933],
77 | [120.02357482910155, 30.24839093066276],
78 | ],
79 | ],
80 | [
81 | [
82 | [120.10116577148436, 30.292867742612255],
83 | [120.08949279785156, 30.216058476325074],
84 | [120.15781402587892, 30.207751175495517],
85 | [120.17051696777344, 30.277154904692335],
86 | [120.10597229003906, 30.325174912575307],
87 | [120.10116577148436, 30.292867742612255],
88 | ],
89 | ],
90 | ],
91 | },
92 | },
93 | ];
94 |
--------------------------------------------------------------------------------
/docs/example/polygon/multiple.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁止绘制多个
3 | order: 5
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/polygon/multiple.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [polygonDrawer, setPolygonDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawPolygon(scene, {
24 | multiple: false,
25 | });
26 | setPolygonDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/polygon/start.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 快速开始
3 | order: 1
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/polygon/start.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { Button } from 'antd';
5 | import 'antd/dist/antd.css';
6 | import React, { useEffect, useState } from 'react';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [polygonDrawer, setPolygonDrawer] = useState(null);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 | scene.on('loaded', () => {
24 | const drawer = new DrawPolygon(scene, {
25 | // distanceOptions: {},
26 | });
27 | setPolygonDrawer(drawer);
28 | drawer.enable();
29 | });
30 | }, []);
31 |
32 | return (
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | );
42 | };
43 |
44 | export default Demo;
45 |
--------------------------------------------------------------------------------
/docs/example/polygon/style.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 自定义样式
3 | order: 4
4 | group:
5 | path: /polygon
6 | title: 绘制面
7 | order: 3
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/polygon/style.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { cloneDeep } from 'lodash';
5 | import React, { useEffect, useState } from 'react';
6 | import { polygonList } from './mock';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [polygonDrawer, setPolygonDrawer] = useState(null);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 |
24 | const polygon = cloneDeep(polygonList);
25 |
26 | if (polygon[0].properties) {
27 | polygon[0].properties.isActive = true;
28 | }
29 |
30 | scene.on('loaded', () => {
31 | const overwriteStyle = {
32 | color: '#a03dff',
33 | };
34 | const drawer = new DrawPolygon(scene, {
35 | initialData: polygon,
36 | style: {
37 | point: {
38 | normal: overwriteStyle,
39 | hover: overwriteStyle,
40 | active: overwriteStyle,
41 | },
42 | line: {
43 | normal: overwriteStyle,
44 | hover: overwriteStyle,
45 | active: overwriteStyle,
46 | },
47 | polygon: {
48 | normal: overwriteStyle,
49 | hover: overwriteStyle,
50 | active: overwriteStyle,
51 | },
52 | midPoint: {
53 | normal: overwriteStyle,
54 | },
55 | dashLine: {
56 | normal: overwriteStyle,
57 | },
58 | text: {
59 | normal: overwriteStyle,
60 | active: overwriteStyle,
61 | },
62 | },
63 | });
64 | setPolygonDrawer(drawer);
65 | drawer.enable();
66 | });
67 | }, []);
68 |
69 | return (
70 |
73 | );
74 | };
75 |
76 | export default Demo;
77 |
--------------------------------------------------------------------------------
/docs/example/rect/area.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 展示距离和面积
3 | order: 3
4 | group:
5 | path: /rect
6 | title: 绘制矩形
7 | order: 4
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/rect/area.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawRect } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [rectDrawer, setRectDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawRect(scene, {
23 | distanceOptions: {},
24 | areaOptions: {},
25 | });
26 | setRectDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/rect/autoActive.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关闭自动激活
3 | order: 3
4 | group:
5 | path: /rect
6 | title: 绘制矩形
7 | order: 4
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/rect/autoActive.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawRect } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [rectDrawer, setRectDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawRect(scene, {
24 | autoActive: false,
25 | });
26 | setRectDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/rect/createByDrag.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 通过拖拽创建
3 | order: 2
4 | group:
5 | path: /rect
6 | title: 绘制矩形
7 | order: 4
8 | ---
9 |
10 | 注意:配置 `trigger: 'drag'` 之后,只要 Drawer 在绘制状态下,就无法拖拽地图。如需开启拖拽,需要将调用 Drawer 的 disable 方法
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/example/rect/createByDrag.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawRect } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [rectDrawer, setRectDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawRect(scene, {
24 | trigger: 'drag',
25 | });
26 | setRectDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/rect/editable.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 是否支持编辑
3 | order: 4
4 | group:
5 | path: /rect
6 | title: 绘制矩形
7 | order: 4
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/rect/editable.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawRect } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import 'antd/dist/antd.css';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [rectDrawer, setRectDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawRect(scene, {
24 | editable: false,
25 | });
26 | setRectDrawer(drawer);
27 | drawer.enable();
28 | });
29 | }, []);
30 |
31 | return (
32 |
35 | );
36 | };
37 |
38 | export default Demo;
39 |
--------------------------------------------------------------------------------
/docs/example/rect/event.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 监听绘制事件
3 | order: 7
4 | group:
5 | path: /rect
6 | title: 绘制矩形
7 | order: 4
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/rect/event.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawRect } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [rectDrawer, setRectDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawRect(scene, {});
23 | setRectDrawer(drawer);
24 | drawer.enable();
25 |
26 | // 监听添加Polygon的事件
27 | drawer.on(DrawEvent.Add, (newPolygon, polygonList) => {
28 | console.log('add', newPolygon, polygonList);
29 | });
30 |
31 | // 监听编辑Polygon(拖拽结束)的事件
32 | drawer.on(DrawEvent.Edit, (editPolygon, polygonList) => {
33 | console.log('edit', editPolygon, polygonList);
34 | });
35 |
36 | // 监听删除 Polygon 的事件
37 | drawer.on(DrawEvent.Remove, (removePolygon, polygonList) => {
38 | console.log('remove', removePolygon, polygonList);
39 | });
40 |
41 | // Polygon数据发生变更时触发,等价于同时监听add和edit事件
42 | drawer.on(DrawEvent.Change, (polygonList) => {
43 | console.log('change', polygonList);
44 | });
45 |
46 | // 拖拽开始
47 | drawer.on(DrawEvent.DragStart, (editPolygon, polygonList) => {
48 | console.log('dragStart', editPolygon, polygonList);
49 | });
50 |
51 | // 拖拽中
52 | drawer.on(DrawEvent.Dragging, (editPolygon, polygonList) => {
53 | console.log('dragging', editPolygon, polygonList);
54 | });
55 |
56 | // 拖拽结束
57 | drawer.on(DrawEvent.DragEnd, (editPolygon, polygonList) => {
58 | console.log('dragEnd', editPolygon, polygonList);
59 | });
60 | });
61 | }, []);
62 |
63 | return (
64 |
67 | );
68 | };
69 |
70 | export default Demo;
71 |
--------------------------------------------------------------------------------
/docs/example/rect/initialData.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 初始化数据
3 | order: 2
4 | group:
5 | path: /rect
6 | title: 绘制矩形
7 | order: 4
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/rect/initialData.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawEvent, DrawRect } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 | import { rectList } from './mock';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [rectDrawer, setRectDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | const drawer = new DrawRect(scene, {
24 | initialData: rectList,
25 | });
26 | setRectDrawer(drawer);
27 | drawer.enable();
28 |
29 | // setTimeout(() => {
30 | // drawer.setData([
31 | // rectList[2]
32 | // ])
33 | // }, 1000)
34 |
35 | drawer.on(DrawEvent.Add, (e) => {});
36 | });
37 | }, []);
38 |
39 | return (
40 |
43 | );
44 | };
45 |
46 | export default Demo;
47 |
--------------------------------------------------------------------------------
/docs/example/rect/mock.ts:
--------------------------------------------------------------------------------
1 | import { Feature, Polygon } from '@turf/turf';
2 |
3 | export const rectList: Feature[] = [
4 | {
5 | type: 'Feature',
6 | properties: {},
7 | geometry: {
8 | type: 'Polygon',
9 | coordinates: [
10 | [
11 | [120.11146545410156, 30.23000129725004],
12 | [120.15438079833983, 30.23000129725004],
13 | [120.15438079833983, 30.251060107580553],
14 | [120.11146545410156, 30.251060107580553],
15 | [120.11146545410156, 30.23000129725004],
16 | ],
17 | ],
18 | },
19 | },
20 | {
21 | type: 'Feature',
22 | properties: {},
23 | geometry: {
24 | type: 'Polygon',
25 | coordinates: [
26 | [
27 | [120.14511108398436, 30.257287905035877],
28 | [120.19592285156249, 30.257287905035877],
29 | [120.19592285156249, 30.27270741823115],
30 | [120.14511108398436, 30.27270741823115],
31 | [120.14511108398436, 30.257287905035877],
32 | ],
33 | ],
34 | },
35 | },
36 | {
37 | type: 'Feature',
38 | properties: {},
39 | geometry: {
40 | type: 'Polygon',
41 | coordinates: [
42 | [
43 | [120.10047912597655, 30.26559102073103],
44 | [120.1303482055664, 30.26559102073103],
45 | [120.1303482055664, 30.29523927312319],
46 | [120.10047912597655, 30.29523927312319],
47 | [120.10047912597655, 30.26559102073103],
48 | ],
49 | ],
50 | },
51 | },
52 | ];
53 |
--------------------------------------------------------------------------------
/docs/example/rect/multiple.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 禁止绘制多个
3 | order: 5
4 | group:
5 | path: /rect
6 | title: 绘制矩形
7 | order: 4
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/rect/multiple.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawRect } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import React, { useEffect, useState } from 'react';
5 |
6 | const id = String(Math.random());
7 |
8 | const Demo: React.FC = () => {
9 | const [rectDrawer, setRectDrawer] = useState(null);
10 |
11 | useEffect(() => {
12 | const scene = new Scene({
13 | id,
14 | map: new GaodeMap({
15 | center: [120.151634, 30.244831],
16 | pitch: 0,
17 | style: 'dark',
18 | zoom: 10,
19 | }),
20 | });
21 | scene.on('loaded', () => {
22 | const drawer = new DrawRect(scene, {
23 | multiple: false,
24 | });
25 | setRectDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
34 | );
35 | };
36 |
37 | export default Demo;
38 |
--------------------------------------------------------------------------------
/docs/example/rect/start.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 快速开始
3 | order: 1
4 | group:
5 | path: /rect
6 | title: 绘制矩形
7 | order: 4
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/rect/start.tsx:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { DrawRect } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { Button } from 'antd';
5 | import 'antd/dist/antd.css';
6 | import React, { useEffect, useState } from 'react';
7 |
8 | const id = String(Math.random());
9 |
10 | const Demo: React.FC = () => {
11 | const [rectDrawer, setRectDrawer] = useState(null);
12 |
13 | useEffect(() => {
14 | const scene = new Scene({
15 | id,
16 | map: new GaodeMap({
17 | center: [120.151634, 30.244831],
18 | pitch: 0,
19 | style: 'dark',
20 | zoom: 10,
21 | }),
22 | });
23 | scene.on('loaded', () => {
24 | const drawer = new DrawRect(scene, {});
25 | setRectDrawer(drawer);
26 | drawer.enable();
27 | });
28 | }, []);
29 |
30 | return (
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | );
40 | };
41 |
42 | export default Demo;
43 |
--------------------------------------------------------------------------------
/docs/example/usage/bus.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 定制公交场景
3 | order: 2
4 | group:
5 | path: /usage
6 | title: 使用场景
7 | order: 7
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/usage/tilMap.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 遥感绘制场景
3 | order: 1
4 | group:
5 | path: /usage
6 | title: 使用场景
7 | order: 7
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/example/usage/tileMap.tsx:
--------------------------------------------------------------------------------
1 | import { PointLayer, Scene } from '@antv/l7';
2 | import { DrawEvent, DrawPolygon } from '@antv/l7-draw';
3 | import { GaodeMap } from '@antv/l7-maps';
4 | import { bbox, pointsWithinPolygon, randomPoint } from '@turf/turf';
5 | import React, { useEffect, useState } from 'react';
6 |
7 | const id = String(Math.random());
8 |
9 | const Demo: React.FC = () => {
10 | const [polygonDrawer, setPolygonDrawer] = useState(null);
11 |
12 | useEffect(() => {
13 | const scene = new Scene({
14 | id,
15 | map: new GaodeMap({
16 | center: [120.151634, 30.244831],
17 | pitch: 0,
18 | style: 'dark',
19 | zoom: 10,
20 | }),
21 | });
22 | scene.on('loaded', () => {
23 | scene.addImage(
24 | 'site',
25 | 'https://gw.alipayobjects.com/mdn/rms_2591f5/afts/img/A*i7uyS6lLupYAAAAAAAAAAAAAARQnAQ',
26 | );
27 | const drawer = new DrawPolygon(scene, {
28 | editable: false,
29 | style: {
30 | polygon: {
31 | normal: {
32 | color: 'rgba(0,0,0,0)',
33 | },
34 | hover: {
35 | color: 'rgba(0,0,0,0)',
36 | },
37 | active: {
38 | color: 'rgba(0,0,0,0)',
39 | },
40 | },
41 | },
42 | });
43 | const layer = new PointLayer({
44 | blend: 'normal',
45 | })
46 | .source([])
47 | .shape('site')
48 | .size(12)
49 | .style({
50 | offsets: [0, 16],
51 | });
52 | scene.addLayer(layer);
53 | setPolygonDrawer(drawer);
54 | drawer.enable();
55 | (scene.map as any).addLayer(new window.AMap.TileLayer.Satellite());
56 |
57 | drawer.on(DrawEvent.Add, (newPolygon) => {
58 | const box = bbox(newPolygon);
59 | const data = pointsWithinPolygon(
60 | randomPoint(80, {
61 | bbox: box,
62 | }),
63 | newPolygon,
64 | );
65 | layer.setData(data);
66 | });
67 | });
68 | }, []);
69 |
70 | return (
71 |
74 | );
75 | };
76 |
77 | export default Demo;
78 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@antv/l7-draw",
3 | "version": "3.1.5",
4 | "description": "A drawing package for L7",
5 | "license": "MIT",
6 | "scripts": {
7 | "prepare": "husky install",
8 | "start": "dumi dev",
9 | "docs:build": "dumi build",
10 | "docs:deploy": "gh-pages -d docs-dist",
11 | "less": "lessc ./src/control/index.less ./src/control/index.css",
12 | "analyze": "ANALYZE=1 dumi build",
13 | "build": "father-build",
14 | "deploy": "npm run docs:build && npm run docs:deploy",
15 | "release": "npm run build && npm publish",
16 | "prettier": "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"",
17 | "test": "umi-test",
18 | "test:coverage": "umi-test --coverage",
19 | "ci": "npm run prettier && npm run build",
20 | "prepublishOnly": "npm run ci"
21 | },
22 | "files": [
23 | "lib",
24 | "es",
25 | "README.md",
26 | "dist/l7-draw.*"
27 | ],
28 | "main": "lib/index.js",
29 | "module": "es/index.js",
30 | "typings": "es/index.d.ts",
31 | "browser": "dist/l7-draw.min.js",
32 | "dependencies": {
33 | "@turf/turf": "^6.5.0",
34 | "eventemitter3": "^4.0.7",
35 | "lodash": "^4.17.21",
36 | "mousetrap": "^1.6.5",
37 | "tippy.js": "^6.3.7"
38 | },
39 | "devDependencies": {
40 | "@antv/dumi-theme-antv": "^0.2.1",
41 | "@antv/l7": "^2.21.8",
42 | "@commitlint/cli": "^12.1.4",
43 | "@commitlint/config-conventional": "^12.1.4",
44 | "@optimize-lodash/rollup-plugin": "^3.0.0",
45 | "@testing-library/jest-dom": "^5.15.1",
46 | "@testing-library/react": "^12.1.2",
47 | "@types/jest": "^27.0.3",
48 | "@types/lodash": "^4.14.177",
49 | "@types/mousetrap": "^1.6.9",
50 | "@types/next-tick": "^1.0.0",
51 | "@typescript-eslint/eslint-plugin": "^4.33.0",
52 | "@typescript-eslint/parser": "^4.33.0",
53 | "@umijs/fabric": "^2.8.1",
54 | "@umijs/test": "^3.0.5",
55 | "dumi": "^1.1.0",
56 | "eslint": "^7.32.0",
57 | "eslint-config-prettier": "^8.3.0",
58 | "eslint-plugin-jest": "^24.7.0",
59 | "eslint-plugin-prettier": "^3.4.1",
60 | "father-build": "^1.17.2",
61 | "gh-pages": "^3.0.0",
62 | "husky": "^8.0.1",
63 | "lint-staged": "^10.0.7",
64 | "prettier": "^2.2.1",
65 | "rollup-plugin-analyzer": "^4.0.0",
66 | "rollup-plugin-node-polyfills": "^0.2.1",
67 | "yorkie": "^2.0.0"
68 | },
69 | "peerDependencies": {
70 | "@antv/l7": "^2.21.8"
71 | },
72 | "husky": {
73 | "hooks": {
74 | "pre-commit": "lint-staged",
75 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
76 | }
77 | },
78 | "lint-staged": {
79 | "*.{ts,tsx}": "eslint --fix",
80 | "*.{ts,tsx,md,json}": [
81 | "prettier --write"
82 | ],
83 | "*.ts?(x)": [
84 | "prettier --parser=typescript --write"
85 | ]
86 | },
87 | "keywords": [
88 | "antv",
89 | "l7",
90 | "draw",
91 | "l7 draw"
92 | ],
93 | "author": {
94 | "name": "AntV",
95 | "url": "https://antv.vision/"
96 | },
97 | "repository": {
98 | "type": "git",
99 | "url": "https://github.com/antvis/l7-draw"
100 | },
101 | "bugs": {
102 | "url": "https://github.com/antvis/l7-draw/issues"
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/constant/default.ts:
--------------------------------------------------------------------------------
1 | import { ICursor, SourceData } from '../typings';
2 |
3 | /**
4 | * 鼠标指针默认值
5 | */
6 | export const DEFAULT_CURSOR_MAP: ICursor = {
7 | draw: 'crosshair',
8 | pointHover: 'pointer',
9 | pointDrag: 'move',
10 | lineHover: 'pointer',
11 | lineDrag: 'move',
12 | polygonHover: 'pointer',
13 | polygonDrag: 'move',
14 | };
15 |
16 | export const DEFAULT_SOURCE_DATA: SourceData = {
17 | point: [],
18 | line: [],
19 | polygon: [],
20 | midPoint: [],
21 | dashLine: [],
22 | text: [],
23 | };
24 |
--------------------------------------------------------------------------------
/src/constant/drawer.ts:
--------------------------------------------------------------------------------
1 | import { ILineDrawerOptions } from '../drawer/line-drawer';
2 | import {
3 | HistoryConfig,
4 | IAdsorbOptions,
5 | IAreaOptions,
6 | IDistanceOptions,
7 | KeyBoardConfig,
8 | PopupOptions,
9 | } from '../typings';
10 | import { followCursor } from 'tippy.js';
11 |
12 | export const DEFAULT_DISTANCE_OPTIONS: IDistanceOptions = {
13 | showTotalDistance: false,
14 | showDashDistance: true,
15 | showWhen: ['normal', 'active'],
16 | format: (meters) => {
17 | if (meters >= 1000) {
18 | return +(meters / 1000).toFixed(2) + 'km';
19 | } else {
20 | return +meters.toFixed(2) + 'm';
21 | }
22 | },
23 | };
24 |
25 | export const DEFAULT_AREA_OPTIONS: IAreaOptions = {
26 | showWhen: ['normal', 'active'],
27 | format: (squareMeters: number) => {
28 | return squareMeters > 1000000
29 | ? `${+(squareMeters / 1000000).toFixed(2)}km²`
30 | : `${+squareMeters.toFixed(2)}m²`;
31 | },
32 | };
33 |
34 | export const DEFAULT_HISTORY_CONFIG: HistoryConfig = {
35 | maxSize: 100,
36 | };
37 |
38 | export const DEFAULT_KEYBOARD_CONFIG: KeyBoardConfig = {
39 | remove: ['del', 'backspace'],
40 | revert: ['command+z', 'ctrl+z'],
41 | redo: ['command+shift+z', 'ctrl+shift+z'],
42 | };
43 |
44 | export const DEFAULT_POPUP_CONFIG: PopupOptions = {
45 | allowHTML: true,
46 | followCursor: true,
47 | placement: 'bottom-start',
48 | offset: [-10, 20],
49 | plugins: [followCursor],
50 | trigger: 'manual',
51 | hideOnClick: false,
52 | theme: 'light',
53 | };
54 |
55 | export const DEFAULT_ADSORB_CONFIG: IAdsorbOptions = {
56 | data: 'drawData',
57 | pointAdsorbPixel: 12,
58 | lineAdsorbPixel: 10,
59 | };
60 |
61 | export const DEFAULT_DRAG_OPTIONS: ILineDrawerOptions['dragOptions'] = {
62 | dotDuration: 100,
63 | dotDistance: 30,
64 | };
65 |
--------------------------------------------------------------------------------
/src/constant/event.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Drawer事件枚举
3 | */
4 | export enum DrawEvent {
5 | Init = 'init',
6 | Destroy = 'destroy',
7 | Enable = 'enable',
8 | Disable = 'disable',
9 | Add = 'add',
10 | Edit = 'edit',
11 | Remove = 'remove',
12 | Clear = 'clear',
13 | Change = 'change',
14 | DragStart = 'dragStart',
15 | Dragging = 'dragging',
16 | DragEnd = 'dragEnd',
17 | Select = 'select',
18 | AddNode = 'addNode',
19 | RemoveNode = 'removeNode',
20 | }
21 |
22 | /**
23 | * Source事件枚举
24 | */
25 | export enum SourceEvent {
26 | Change = 'change',
27 | Update = 'update',
28 | }
29 |
30 | /**
31 | * Render事件枚举
32 | */
33 | export enum RenderEvent {
34 | Click = 'click',
35 | UnClick = 'unclick',
36 | Dragstart = 'dragstart',
37 | Mousemove = 'mousemove',
38 | Mouseout = 'mouseout',
39 | Dragging = 'dragging',
40 | Dragend = 'dragend',
41 | DblClick = 'dblClick',
42 | Contextmenu = 'contextmenu',
43 | }
44 |
45 | /**
46 | * L7 Layer 事件名枚举
47 | */
48 | export enum LayerEvent {
49 | Mousedown = 'mousedown',
50 | Mouseup = 'mouseup',
51 | Click = 'click',
52 | UnClick = 'unclick',
53 | Dblclick = 'dblclick',
54 | Mousemove = 'mousemove',
55 | Mouseover = 'mouseover',
56 | Mouseenter = 'mouseenter',
57 | Mouseleave = 'mouseleave',
58 | Mouseout = 'mouseout',
59 | Contextmenu = 'contextmenu',
60 | }
61 |
62 | /**
63 | * L7 Scene 事件名枚举
64 | */
65 | export enum SceneEvent {
66 | Loaded = 'loaded',
67 | MapMove = 'mapmove',
68 | MoveStart = 'movestart',
69 | MoveEnd = 'moveend',
70 | ZoomChange = 'zoomchange',
71 | ZoomStart = 'zoomstart',
72 | ZoomEnd = 'zoomend',
73 | Click = 'click',
74 | Dblclick = 'dblclick',
75 | Mousemove = 'mousemove',
76 | Mousewheel = 'mousewheel',
77 | Mouseover = 'mouseover',
78 | Mouseout = 'mouseout',
79 | Mouseup = 'mouseup',
80 | Mousedown = 'mousedown',
81 | Contextmenu = 'contextmenu',
82 | Dragstart = 'dragstart',
83 | Dragging = 'dragging',
84 | Dragend = 'dragend',
85 | }
86 |
87 | export enum ControlEvent {
88 | DrawChange = 'drawchange',
89 | DataChange = 'datachange',
90 | DrawSelect = 'drawselect',
91 | DrawClear = 'drawclear',
92 | }
93 |
--------------------------------------------------------------------------------
/src/constant/helper.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ILineHelperOptions,
3 | IPointHelperOptions,
4 | IPolygonHelperOptions,
5 | IDragPolygonHelperOptions,
6 | } from '../typings';
7 |
8 | export const DEFAULT_POINT_HELPER_CONFIG: IPointHelperOptions = {
9 | draw: '单击绘制点',
10 | pointHover: '可拖拽调整点位置',
11 | pointDrag: null,
12 | };
13 |
14 | export const DEFAULT_LINE_HELPER_CONFIG: ILineHelperOptions = {
15 | draw: '单击绘制首个节点',
16 | pointHover: '可拖拽调整节点位置',
17 | pointDrag: null,
18 | lineHover: '可拖拽调整线位置',
19 | lineDrag: null,
20 | midPointHover: '单击在该位置新增节点',
21 | drawFinish: '单击继续绘制,双击结束绘制',
22 | };
23 |
24 | export const DEFAULT_POLYGON_HELPER_CONFIG: IPolygonHelperOptions = {
25 | draw: '单击绘制首个节点',
26 | drawContinue: '单击继续绘制',
27 | drawFinish: '单击继续绘制,双击结束绘制',
28 | midPointHover: '单击在该位置新增节点',
29 | pointHover: '可拖拽调整节点位置',
30 | pointDrag: null,
31 | lineHover: '可拖拽调整面位置',
32 | lineDrag: null,
33 | polygonHover: '可拖拽调整面位置',
34 | polygonDrag: null,
35 | };
36 |
37 | export const DEFAULT_DRAG_POLYGON_HELPER_CONFIg: IDragPolygonHelperOptions = {
38 | ...DEFAULT_POLYGON_HELPER_CONFIG,
39 | draw: '单击绘制首个节点',
40 | drawFinish: '单击结束绘制',
41 | };
42 |
43 | export const DEFAULT_TRIGGER_DRAG_HELPER_CONFIG: Partial =
44 | {
45 | draw: '拖拽开始绘制',
46 | drawFinish: '松开鼠标结束绘制',
47 | };
48 |
49 | export const DEFAULT_RECT_HELPER_CONFIG: Partial = {
50 | lineHover: '可拖拽调整矩形位置',
51 | polygonHover: '可拖拽调整矩形位置',
52 | };
53 |
54 | export const DEFAULT_CIRCLE_HELPER_CONFIG: Partial =
55 | {
56 | lineHover: '可拖拽调整圆位置',
57 | polygonHover: '可拖拽调整圆位置',
58 | };
59 |
--------------------------------------------------------------------------------
/src/constant/index.ts:
--------------------------------------------------------------------------------
1 | export * from './default';
2 | export * from './drawer';
3 | export * from './event';
4 | export * from './render';
5 | export * from './style';
6 | export * from './helper';
7 |
--------------------------------------------------------------------------------
/src/constant/render.ts:
--------------------------------------------------------------------------------
1 | import {
2 | DashLineRender,
3 | LineRender,
4 | MidPointRender,
5 | PointRender,
6 | PolygonRender,
7 | TextRender,
8 | } from '../render';
9 | import { IRenderType } from '../typings';
10 |
11 | /**
12 | * renderType与render的映射
13 | */
14 | export const RENDER_MAP: Record<
15 | IRenderType,
16 | | typeof PointRender
17 | | typeof LineRender
18 | | typeof MidPointRender
19 | | typeof TextRender
20 | | typeof PolygonRender
21 | | typeof DashLineRender
22 | > = {
23 | point: PointRender,
24 | line: LineRender,
25 | dashLine: DashLineRender,
26 | midPoint: MidPointRender,
27 | text: TextRender,
28 | polygon: PolygonRender,
29 | };
30 |
--------------------------------------------------------------------------------
/src/constant/style.ts:
--------------------------------------------------------------------------------
1 | import { ILayerConfig } from '@antv/l7';
2 | import {
3 | IPointStyle,
4 | IPointStyleItem,
5 | IStyle,
6 | ITextStyleItem,
7 | } from '../typings';
8 |
9 | export const NORMAL_COLOR = '#1990FF';
10 |
11 | export const ACTIVE_COLOR = '#ED9D48';
12 |
13 | export const DEFAULT_COMMON_OPTIONS: Partial = {
14 | blend: 'normal',
15 | pickingBuffer: 5,
16 | };
17 |
18 | export const DEFAULT_POINT_NORMAL_STYLE: IPointStyleItem = {
19 | color: NORMAL_COLOR,
20 | shape: 'circle',
21 | size: 6,
22 | };
23 |
24 | export const DEFAULT_NODE_NORMAL_STYLE: IPointStyleItem = {
25 | color: ACTIVE_COLOR,
26 | shape: 'circle',
27 | size: 6,
28 | };
29 |
30 | export const DEFAULT_MID_POINT_STYLE: IPointStyleItem = {
31 | shape: 'circle',
32 | size: 6,
33 | color: ACTIVE_COLOR,
34 | };
35 |
36 | export const DEFAULT_POINT_STYLE: IPointStyle = {
37 | options: DEFAULT_COMMON_OPTIONS,
38 | normal: DEFAULT_POINT_NORMAL_STYLE,
39 | hover: {
40 | ...DEFAULT_POINT_NORMAL_STYLE,
41 | size: 8,
42 | },
43 | active: {
44 | ...DEFAULT_POINT_NORMAL_STYLE,
45 | size: 8,
46 | color: ACTIVE_COLOR,
47 | },
48 | style: {
49 | stroke: '#ffffff',
50 | strokeWidth: 2,
51 | },
52 | };
53 |
54 | export const DEFAULT_NODE_STYLE: IPointStyle = {
55 | options: DEFAULT_COMMON_OPTIONS,
56 | normal: DEFAULT_NODE_NORMAL_STYLE,
57 | hover: {
58 | ...DEFAULT_NODE_NORMAL_STYLE,
59 | size: 8,
60 | },
61 | active: {
62 | ...DEFAULT_NODE_NORMAL_STYLE,
63 | size: 8,
64 | },
65 | style: {
66 | stroke: '#ffffff',
67 | strokeWidth: 2,
68 | },
69 | };
70 |
71 | export const DEFAULT_TEXT_NORMAL_STYLE: ITextStyleItem = {
72 | color: NORMAL_COLOR,
73 | size: 12,
74 | };
75 |
76 | export const DEFAULT_STYLE: IStyle = {
77 | point: DEFAULT_NODE_STYLE,
78 | line: {
79 | options: DEFAULT_COMMON_OPTIONS,
80 | normal: {
81 | color: NORMAL_COLOR,
82 | size: 2,
83 | },
84 | hover: {
85 | color: NORMAL_COLOR,
86 | size: 2,
87 | },
88 | active: {
89 | color: ACTIVE_COLOR,
90 | size: 2,
91 | },
92 | style: {},
93 | },
94 | polygon: {
95 | options: DEFAULT_COMMON_OPTIONS,
96 | normal: {
97 | color: NORMAL_COLOR,
98 | },
99 | hover: {
100 | color: NORMAL_COLOR,
101 | },
102 | active: {
103 | color: ACTIVE_COLOR,
104 | },
105 | style: {
106 | opacity: 0.15,
107 | },
108 | },
109 | midPoint: {
110 | options: DEFAULT_COMMON_OPTIONS,
111 | normal: DEFAULT_MID_POINT_STYLE,
112 | },
113 | dashLine: {
114 | options: DEFAULT_COMMON_OPTIONS,
115 | normal: {
116 | color: ACTIVE_COLOR,
117 | size: 2,
118 | },
119 | style: {
120 | lineType: 'dash',
121 | dashArray: [6, 6],
122 | },
123 | },
124 | text: {
125 | options: DEFAULT_COMMON_OPTIONS,
126 | normal: DEFAULT_TEXT_NORMAL_STYLE,
127 | active: {
128 | ...DEFAULT_TEXT_NORMAL_STYLE,
129 | color: ACTIVE_COLOR,
130 | },
131 | style: {
132 | fontWeight: '800',
133 | textOffset: [0, DEFAULT_TEXT_NORMAL_STYLE.size + 6],
134 | textAllowOverlap: true,
135 | stroke: '#ffffff',
136 | strokeWidth: 2,
137 | },
138 | },
139 | };
140 |
--------------------------------------------------------------------------------
/src/control/constant.ts:
--------------------------------------------------------------------------------
1 | import {
2 | DrawPoint,
3 | DrawLine,
4 | DrawPolygon,
5 | DrawCircle,
6 | DrawRect,
7 | } from '../drawer';
8 | import { BtnType, DrawType } from './types';
9 |
10 | export const DrawTypeList: BtnType[] = [
11 | 'point',
12 | 'line',
13 | 'polygon',
14 | 'rect',
15 | 'circle',
16 | 'clear',
17 | ];
18 |
19 | export const DrawIconMap: Record = {
20 | point: '#l7draw-point',
21 | line: '#l7draw-line',
22 | polygon: '#l7draw-polygon',
23 | rect: '#l7draw-rect',
24 | circle: '#l7draw-circle',
25 | clear: '#l7draw-qingkong',
26 | };
27 |
28 | export const DrawInstanceMap: Record = {
29 | point: DrawPoint,
30 | line: DrawLine,
31 | polygon: DrawPolygon,
32 | rect: DrawRect,
33 | circle: DrawCircle,
34 | };
35 |
36 | export const DrawTypeAttrName = 'data-draw-type';
37 |
38 | export const DrawControlClassName = 'l7-draw-control';
39 |
40 | export const DrawBtnClassName = `${DrawControlClassName}__btn`;
41 |
42 | export const DrawBtnActiveClassName = `${DrawBtnClassName}--active`;
43 |
--------------------------------------------------------------------------------
/src/control/index.css:
--------------------------------------------------------------------------------
1 | .l7-draw-control {
2 | display: flex;
3 | overflow: hidden;
4 | background: #ffffff;
5 | border-radius: 2px;
6 | box-shadow: 0 0 20px #00000026;
7 | }
8 | .l7-draw-control__btn {
9 | display: inline-flex;
10 | align-items: center;
11 | justify-content: center;
12 | width: 30px;
13 | height: 30px;
14 | padding: 0;
15 | text-align: center;
16 | background: transparent;
17 | border-width: 0 0 0 0;
18 | border-right: 1px solid #e0e0e0;
19 | outline: 0;
20 | cursor: pointer;
21 | transition: background-color 0.3s;
22 | }
23 | .l7-draw-control__btn svg {
24 | transition: color 0.3s;
25 | }
26 | .l7-draw-control__btn:hover {
27 | background-color: #e5e5e5;
28 | }
29 | .l7-draw-control__btn:hover svg {
30 | color: #000;
31 | }
32 | .l7-draw-control__btn:last-child {
33 | border-right: 0;
34 | border-bottom: 0;
35 | }
36 | .l7-draw-control__btn .l7-draw-icon {
37 | width: 26px;
38 | height: 26px;
39 | overflow: hidden;
40 | fill: currentColor;
41 | }
42 | .l7-draw-control__btn--active,
43 | .l7-draw-control__btn--active:hover {
44 | background-color: #0370fe;
45 | }
46 | .l7-draw-control__btn--active svg,
47 | .l7-draw-control__btn--active:hover svg {
48 | color: #fff;
49 | }
50 |
--------------------------------------------------------------------------------
/src/control/index.less:
--------------------------------------------------------------------------------
1 | @cls-prefix: l7-draw-control;
2 | @btn-size: 30px;
3 | @icon-size: 26px;
4 |
5 | .@{cls-prefix} {
6 | display: flex;
7 | overflow: hidden;
8 | background: #ffffff;
9 | border-radius: 2px;
10 | box-shadow: 0 0 20px #00000026;
11 | &__btn {
12 | display: inline-flex;
13 | align-items: center;
14 | justify-content: center;
15 | width: @btn-size;
16 | height: @btn-size;
17 | padding: 0;
18 | text-align: center;
19 | background: transparent;
20 | border-width: 0 0 0 0;
21 | border-right: 1px solid #e0e0e0;
22 | outline: 0;
23 | cursor: pointer;
24 | transition: background-color 0.3s;
25 | svg {
26 | transition: color 0.3s;
27 | }
28 | &:hover {
29 | background-color: #e5e5e5;
30 | svg {
31 | color: #000;
32 | }
33 | }
34 | &:last-child {
35 | border-right: 0;
36 | border-bottom: 0;
37 | }
38 | .l7-draw-icon {
39 | width: @icon-size;
40 | height: @icon-size;
41 | overflow: hidden;
42 | fill: currentColor;
43 | }
44 | &--active,
45 | &--active:hover {
46 | background-color: #0370fe;
47 | svg {
48 | color: #fff;
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/control/types.ts:
--------------------------------------------------------------------------------
1 | import { IControlOption } from '@antv/l7';
2 | import { DeepPartial, IBaseModeOptions } from '../typings';
3 | import {
4 | ICircleDrawerOptions,
5 | ILineDrawerOptions,
6 | IPointDrawerOptions,
7 | IPolygonDrawerOptions,
8 | IRectDrawerOptions,
9 | } from '../drawer';
10 |
11 | export type DrawType = 'point' | 'line' | 'polygon' | 'rect' | 'circle';
12 |
13 | export type BtnType = DrawType | 'clear';
14 |
15 | export type DrawBtnConfig = Record<
16 | // 当 key 为 BtnType 时,展示的是内置按钮,当 key 为 string 时,展示的是自定义按钮
17 | BtnType | string,
18 | | boolean
19 | | (DeepPartial<
20 | | IPointDrawerOptions
21 | | ILineDrawerOptions
22 | | IPolygonDrawerOptions
23 | | IRectDrawerOptions
24 | | ICircleDrawerOptions
25 | > & {
26 | order?: number;
27 | })
28 | | { button?: HTMLElement; order?: number }
29 | >;
30 |
31 | export interface IDrawControlProps extends IControlOption {
32 | drawConfig: DrawBtnConfig;
33 | commonDrawOptions?: DeepPartial;
34 | defaultActiveType?: DrawType;
35 | className?: string;
36 | buttonClassName?: string;
37 | activeButtonClassName?: string;
38 | style?: string;
39 | }
40 |
--------------------------------------------------------------------------------
/src/drawer/index.ts:
--------------------------------------------------------------------------------
1 | import { CircleDrawer } from './circle-drawer';
2 | import { LineDrawer } from './line-drawer';
3 | import { PointDrawer } from './point-drawer';
4 | import { PolygonDrawer } from './polygon-drawer';
5 | import { RectDrawer } from './rect-drawer';
6 |
7 | export * from './circle-drawer';
8 | export * from './line-drawer';
9 | export * from './point-drawer';
10 | export * from './polygon-drawer';
11 | export * from './rect-drawer';
12 | export {
13 | PointDrawer as DrawPoint,
14 | LineDrawer as DrawLine,
15 | PolygonDrawer as DrawPolygon,
16 | RectDrawer as DrawRect,
17 | CircleDrawer as DrawCircle,
18 | };
19 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './constant';
2 | export * from './drawer';
3 | export * from './mode';
4 | export * from './render';
5 | export * from './source';
6 | export * from './typings';
7 | export * from './utils';
8 | export * from './control';
9 |
--------------------------------------------------------------------------------
/src/interactive/cursor.ts:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { ICursor, ICursorType } from '../typings';
3 | import { getMapDom } from '../utils';
4 |
5 | export class Cursor {
6 | container: HTMLDivElement | null;
7 | cursor: ICursorType | null = null;
8 | options: ICursor;
9 |
10 | constructor(scene: Scene, options: ICursor) {
11 | this.container = getMapDom(scene) as HTMLDivElement | null;
12 | this.options = options;
13 | }
14 |
15 | setCursor(cursor: ICursorType | null) {
16 | if (cursor !== this.cursor && this.container) {
17 | this.container.style.cursor = cursor ? this.options[cursor] : '';
18 | this.cursor = cursor;
19 | }
20 | }
21 |
22 | destroy() {
23 | this.setCursor(null);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/interactive/index.ts:
--------------------------------------------------------------------------------
1 | export * from './cursor';
2 | export * from './popup';
3 |
--------------------------------------------------------------------------------
/src/interactive/popup.ts:
--------------------------------------------------------------------------------
1 | import Tippy, { Instance as TippyInstance } from 'tippy.js';
2 | import { Scene } from '@antv/l7';
3 | import { getMapDom } from '../utils';
4 | import { PopupContent, PopupOptions } from '../typings';
5 | import 'tippy.js/dist/tippy.css';
6 | import 'tippy.js/themes/light.css';
7 | import { DEFAULT_POPUP_CONFIG, SceneEvent } from '../constant';
8 | import { debounce } from 'lodash';
9 |
10 | export class Popup {
11 | protected content: PopupContent = '';
12 |
13 | protected tippy?: TippyInstance;
14 |
15 | protected scene: Scene;
16 |
17 | protected isMouseInner = false;
18 |
19 | constructor(scene: Scene, tippyProps: PopupOptions) {
20 | const container = getMapDom(scene);
21 | this.scene = scene;
22 | if (container) {
23 | this.tippy = Tippy(getMapDom(scene)!, {
24 | ...DEFAULT_POPUP_CONFIG,
25 | ...tippyProps,
26 | });
27 | this.tippy.hide();
28 | scene.on(SceneEvent.Mousemove, this.onMouseMove);
29 | scene.on(SceneEvent.Mouseout, this.onMouseOut);
30 | }
31 | }
32 |
33 | onMouseMove = () => {
34 | this.isMouseInner = true;
35 | this.checkTippyShow();
36 | };
37 |
38 | onMouseOut = () => {
39 | this.isMouseInner = false;
40 | this.checkTippyShow();
41 | };
42 |
43 | getContent() {
44 | return this.content;
45 | }
46 |
47 | setContent = debounce(
48 | (content: PopupContent | null) => {
49 | this.content = content ?? '';
50 | this.tippy?.setContent(content ?? '');
51 | this.checkTippyShow();
52 | },
53 | 16,
54 | {
55 | maxWait: 16,
56 | },
57 | );
58 |
59 | checkTippyShow() {
60 | if (this.content && this.isMouseInner) {
61 | this.tippy?.show();
62 | } else {
63 | this.tippy?.hide();
64 | }
65 | }
66 |
67 | destroy() {
68 | this.scene.off(SceneEvent.Mousemove, this.onMouseMove);
69 | this.scene.off(SceneEvent.Mouseout, this.onMouseOut);
70 | this.tippy?.destroy();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/mode/index.ts:
--------------------------------------------------------------------------------
1 | export * from './base-mode';
2 | export * from './drag-polygon-mode';
3 | export * from './line-mode';
4 | export * from './mid-point-mode';
5 | export * from './point-mode';
6 | export * from './polygon-mode';
7 |
--------------------------------------------------------------------------------
/src/mode/mid-point-mode.ts:
--------------------------------------------------------------------------------
1 | import { center, Feature, featureCollection } from '@turf/turf';
2 | import { RenderEvent } from '../constant';
3 | import { MidPointRender } from '../render';
4 | import {
5 | DeepPartial,
6 | FeatureUpdater,
7 | IBaseModeOptions,
8 | ILayerMouseEvent,
9 | ILineFeature,
10 | IMidPointFeature,
11 | IPointFeature,
12 | } from '../typings';
13 | import { getUuid } from '../utils';
14 | import { PointMode } from './point-mode';
15 |
16 | export interface IMidPointModeOptions
17 | extends IBaseModeOptions {
18 | showMidPoint: boolean;
19 | }
20 |
21 | export abstract class MidPointMode<
22 | T extends IMidPointModeOptions,
23 | > extends PointMode {
24 | /**
25 | * 获取midPoint类型对应的render
26 | * @protected
27 | */
28 | protected get midPointRender(): MidPointRender | undefined {
29 | return this.render.midPoint;
30 | }
31 |
32 | getCommonOptions(options: DeepPartial): T {
33 | // @ts-ignore
34 | return {
35 | ...super.getCommonOptions(options),
36 | showMidPoint: true,
37 | };
38 | }
39 |
40 | bindMidPointRenderEvent() {
41 | this.midPointRender?.on(RenderEvent.Click, this.onMidPointClick.bind(this));
42 | this.midPointRender?.on(
43 | RenderEvent.Mousemove,
44 | this.onMidPointHover.bind(this),
45 | );
46 | this.midPointRender?.on(
47 | RenderEvent.Mouseout,
48 | this.onMidPointUnHover.bind(this),
49 | );
50 | }
51 |
52 | /**
53 | * 获取中点数据
54 | */
55 | getMidPointData() {
56 | return this.source.getRenderData('midPoint');
57 | }
58 |
59 | /**
60 | * 设置中点数据
61 | * @param data
62 | */
63 | setMidPointData(data: FeatureUpdater) {
64 | return this.source.setRenderData('midPoint', data);
65 | }
66 |
67 | /**
68 | * 计算并返回传入线段的中点数组
69 | * @param line
70 | */
71 | getMidPointsByLine(line: ILineFeature): IMidPointFeature[] {
72 | const nodes = line.properties.nodes;
73 | if (!this.options.showMidPoint || nodes.length < 2) {
74 | return [];
75 | }
76 | const midPoints: IMidPointFeature[] = [];
77 | for (let index = 0; index < nodes.length - 1; index++) {
78 | const newMidPoint = center(
79 | featureCollection([nodes[index], nodes[index + 1]]),
80 | {
81 | properties: {
82 | id: getUuid('midPoint'),
83 | startId: nodes[index].properties?.id ?? '',
84 | endId: nodes[index + 1].properties?.id ?? '',
85 | },
86 | },
87 | ) as IMidPointFeature;
88 | midPoints.push(newMidPoint);
89 | }
90 | return midPoints;
91 | }
92 |
93 | abstract onMidPointClick(
94 | e: ILayerMouseEvent,
95 | ): IPointFeature | undefined;
96 |
97 | onMidPointHover(e: ILayerMouseEvent) {
98 | this.setCursor('pointHover');
99 | }
100 |
101 | onMidPointUnHover(e: ILayerMouseEvent) {
102 | this.resetCursor();
103 | }
104 |
105 | enableMidPointRenderAction() {
106 | this.midPointRender?.enableClick();
107 | this.midPointRender?.enableHover();
108 | }
109 |
110 | disableMidPointRenderAction() {
111 | this.midPointRender?.disableClick();
112 | this.midPointRender?.disableHover();
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/render/dash-line-render.ts:
--------------------------------------------------------------------------------
1 | import { ILayer, LineLayer } from '@antv/l7';
2 | import { featureCollection } from '@turf/turf';
3 | import { IDashLineFeature, IDashLineStyle } from '../typings';
4 | import { LayerRender } from './layer-render';
5 |
6 | export class DashLineRender extends LayerRender<
7 | IDashLineFeature,
8 | IDashLineStyle
9 | > {
10 | initLayers(): ILayer[] {
11 | const { normal, style, options } = this.style;
12 |
13 | const layer = new LineLayer(options ?? {})
14 | .source(featureCollection([]))
15 | .size(normal.size)
16 | .color(normal.color)
17 | .shape('line')
18 | .style(style);
19 |
20 | return [layer];
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/render/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dash-line-render';
2 | export * from './layer-render';
3 | export * from './line-render';
4 | export * from './mid-point-render';
5 | export * from './point-render';
6 | export * from './polygon-render';
7 | export * from './scene-render';
8 | export * from './text-render';
9 |
--------------------------------------------------------------------------------
/src/render/layer-render.ts:
--------------------------------------------------------------------------------
1 | import { ILayer, Scene } from '@antv/l7';
2 | import { featureCollection } from '@turf/turf';
3 | import { EventEmitter } from 'eventemitter3';
4 | import { RenderEvent } from '../constant';
5 | import { IBaseFeature, IBaseStyle, IRenderOptions } from '../typings';
6 |
7 | export abstract class LayerRender<
8 | F extends IBaseFeature = IBaseFeature,
9 | S extends IBaseStyle = IBaseStyle,
10 | > extends EventEmitter {
11 | /**
12 | * 地图场景Scene的实例
13 | */
14 | protected scene: Scene;
15 |
16 | /**
17 | * 样式配置
18 | */
19 | protected style: S;
20 |
21 | /**
22 | * 图层列表
23 | */
24 | protected layers: ILayer[];
25 |
26 | /**
27 | * 当前展示的数据
28 | */
29 | protected data: F[] = [];
30 |
31 | constructor(scene: Scene, { style }: IRenderOptions) {
32 | super();
33 |
34 | this.scene = scene;
35 | this.style = style;
36 | this.layers = this.initLayers();
37 |
38 | this.layers.forEach((layer) => {
39 | scene.addLayer(layer);
40 | // layer.active(true);
41 | });
42 |
43 | if (style.callback instanceof Function) {
44 | style.callback(this.layers);
45 | }
46 | }
47 |
48 | /**
49 | * 子类继承时需要实现该方法并返回对应的layer数组
50 | */
51 | abstract initLayers(): ILayer[];
52 |
53 | getLayers() {
54 | return this.layers;
55 | }
56 |
57 | /**
58 | * 显示所有图层
59 | */
60 | show() {
61 | this.layers.forEach((layer) => {
62 | layer.show();
63 | });
64 | }
65 |
66 | /**
67 | * 隐藏所有图层
68 | */
69 | hide() {
70 | this.layers.forEach((layer) => {
71 | layer.hide();
72 | });
73 | }
74 |
75 | /**
76 | * 设置数据
77 | * @param features 设置对应的Feature数组
78 | */
79 | setData(features: F[]) {
80 | const newFeatures = [...features].sort(
81 | (a, b) => +a.properties.isActive! - +b.properties.isActive!,
82 | );
83 | this.data = newFeatures;
84 | this.layers.forEach((layer) => {
85 | layer.setData(featureCollection(newFeatures));
86 | });
87 | }
88 |
89 | /**
90 | * render销毁时,需要把图层从Scene中移除
91 | */
92 | destroy() {
93 | this.layers.forEach((layer) => {
94 | this.scene.removeLayer(layer);
95 | });
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/render/line-render.ts:
--------------------------------------------------------------------------------
1 | import { ILayer, LineLayer } from '@antv/l7';
2 | import { featureCollection } from '@turf/turf';
3 | import { debounce } from 'lodash';
4 | import { LayerEvent, RenderEvent, SceneEvent } from '../constant';
5 | import {
6 | ILayerMouseEvent,
7 | ILineFeature,
8 | ILineStyle,
9 | ISceneMouseEvent,
10 | } from '../typings';
11 | import { LayerRender } from './layer-render';
12 |
13 | export class LineRender extends LayerRender {
14 | initLayers(): ILayer[] {
15 | const { normal, hover, active, style, options } = this.style;
16 |
17 | const layer = new LineLayer(options ?? {})
18 | .source(featureCollection([]))
19 | .size('isHover*isActive', (isHover: boolean, isActive: boolean) => {
20 | return isActive ? active.size : isHover ? hover.size : normal.size;
21 | })
22 | .color('isHover*isActive', (isHover: boolean, isActive: boolean) => {
23 | return isActive ? active.color : isHover ? hover.color : normal.color;
24 | })
25 | .shape('line')
26 | .style(style);
27 |
28 | return [layer];
29 | }
30 |
31 | onMouseMove = (e: ILayerMouseEvent) => {
32 | this.emit(RenderEvent.Mousemove, e);
33 | };
34 |
35 | onMouseOut = (e: ILayerMouseEvent) => {
36 | this.emit(RenderEvent.Mouseout, e);
37 | };
38 |
39 | onMouseDown = (e: ILayerMouseEvent) => {
40 | this.emit(RenderEvent.Dragstart, e);
41 | };
42 |
43 | onDragging = (e: ILayerMouseEvent) => {
44 | this.emit(RenderEvent.Dragging, e);
45 | };
46 |
47 | onDragEnd = debounce((e: ISceneMouseEvent) => {
48 | this.emit(RenderEvent.Dragend, e);
49 | }, 0);
50 |
51 | onUnClick = (e: ILayerMouseEvent) => {
52 | this.emit(RenderEvent.UnClick, e);
53 | };
54 |
55 | enableHover = () => {
56 | this.disableHover();
57 | this.layers[0]?.on(LayerEvent.Mousemove, this.onMouseMove);
58 | this.layers[0]?.on(LayerEvent.Mouseout, this.onMouseOut);
59 | };
60 |
61 | disableHover = () => {
62 | this.layers[0]?.off(LayerEvent.Mousemove, this.onMouseMove);
63 | this.layers[0]?.off(LayerEvent.Mouseout, this.onMouseOut);
64 | };
65 |
66 | enableDrag() {
67 | this.disableDrag();
68 | this.layers[0].on(LayerEvent.Mousedown, this.onMouseDown);
69 | this.scene.on(SceneEvent.Dragging, this.onDragging);
70 | this.scene.on(SceneEvent.Mouseup, this.onDragEnd);
71 | this.scene.on(SceneEvent.Dragend, this.onDragEnd);
72 | }
73 |
74 | disableDrag() {
75 | this.layers[0].off(LayerEvent.Mousedown, this.onMouseDown);
76 | this.scene.off(SceneEvent.Dragging, this.onDragging);
77 | this.scene.off(SceneEvent.Mouseup, this.onDragEnd);
78 | this.scene.off(SceneEvent.Dragend, this.onDragEnd);
79 | }
80 |
81 | enableUnClick() {
82 | this.disableUnClick();
83 | this.layers[0].on(LayerEvent.UnClick, this.onUnClick);
84 | }
85 |
86 | disableUnClick() {
87 | this.layers[0].off(LayerEvent.UnClick, this.onUnClick);
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/render/mid-point-render.ts:
--------------------------------------------------------------------------------
1 | import { ILayer, PointLayer } from '@antv/l7';
2 | import { featureCollection } from '@turf/turf';
3 | import { LayerEvent, RenderEvent } from '../constant';
4 | import { ILayerMouseEvent, IMidPointFeature, IMidPointStyle } from '../typings';
5 | import { LayerRender } from './layer-render';
6 |
7 | export class MidPointRender extends LayerRender<
8 | IMidPointFeature,
9 | IMidPointStyle
10 | > {
11 | initLayers(): ILayer[] {
12 | const { normal, style = {}, options } = this.style;
13 | const { shape, size, color } = normal;
14 | const layer = new PointLayer(options ?? {})
15 | .source(featureCollection([]))
16 | .size(size)
17 | .color(color)
18 | .shape(shape)
19 | .style(style);
20 |
21 | return [layer];
22 | }
23 |
24 | onMouseMove = (e: ILayerMouseEvent) => {
25 | this.emit(RenderEvent.Mousemove, e);
26 | };
27 |
28 | onMouseOut = (e: ILayerMouseEvent) => {
29 | this.emit(RenderEvent.Mouseout, e);
30 | };
31 |
32 | onMouseDown = (e: ILayerMouseEvent) => {
33 | this.emit(RenderEvent.Click, e);
34 | };
35 |
36 | enableClick() {
37 | this.disableClick();
38 | this.layers[0].on(LayerEvent.Mousedown, this.onMouseDown);
39 | }
40 |
41 | disableClick() {
42 | this.layers[0].off(LayerEvent.Mousedown, this.onMouseDown);
43 | }
44 |
45 | enableHover() {
46 | this.disableHover();
47 | this.layers[0]?.on(LayerEvent.Mousemove, this.onMouseMove);
48 | this.layers[0]?.on(LayerEvent.Mouseout, this.onMouseOut);
49 | }
50 |
51 | disableHover() {
52 | this.layers[0]?.off(LayerEvent.Mousemove, this.onMouseMove);
53 | this.layers[0]?.off(LayerEvent.Mouseout, this.onMouseOut);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/render/point-render.ts:
--------------------------------------------------------------------------------
1 | import { ILayer, PointLayer } from '@antv/l7';
2 | import { featureCollection } from '@turf/turf';
3 | import { debounce } from 'lodash';
4 | import { LayerEvent, RenderEvent, SceneEvent } from '../constant';
5 | import {
6 | ILayerMouseEvent,
7 | IPointFeature,
8 | IPointStyle,
9 | ISceneMouseEvent,
10 | } from '../typings';
11 | import { LayerRender } from './layer-render';
12 |
13 | export class PointRender extends LayerRender {
14 | initLayers(): ILayer[] {
15 | const { normal, hover, active, style = {}, options } = this.style;
16 | const layer = new PointLayer(options ?? {})
17 | .source(featureCollection([]))
18 | .size('isHover*isActive', (isHover: boolean, isActive: boolean) => {
19 | return isActive ? active.size : isHover ? hover.size : normal.size;
20 | })
21 | .color('isHover*isActive', (isHover: boolean, isActive: boolean) => {
22 | return isActive ? active.color : isHover ? hover.color : normal.color;
23 | })
24 | .shape('isHover*isActive', (isHover: boolean, isActive: boolean) => {
25 | return isActive ? active.shape : isHover ? hover.shape : normal.shape;
26 | })
27 | .style(style);
28 |
29 | return [layer];
30 | }
31 |
32 | onCreate = (e: ILayerMouseEvent) => {
33 | this.emit(RenderEvent.UnClick, e);
34 | };
35 |
36 | onMouseMove = (e: ILayerMouseEvent) => {
37 | this.emit(RenderEvent.Mousemove, e);
38 | };
39 |
40 | onMouseOut = (e: ILayerMouseEvent) => {
41 | this.emit(RenderEvent.Mouseout, e);
42 | };
43 |
44 | onMouseDown = (e: ILayerMouseEvent) => {
45 | this.emit(RenderEvent.Dragstart, e);
46 | };
47 |
48 | onDragging = (e: ISceneMouseEvent) => {
49 | this.emit(RenderEvent.Dragging, e);
50 | };
51 |
52 | onDragEnd = debounce((e: ISceneMouseEvent) => {
53 | this.emit(RenderEvent.Dragend, e);
54 | }, 0);
55 |
56 | onClick = (e: ILayerMouseEvent) => {
57 | this.emit(RenderEvent.Click, e);
58 | };
59 |
60 | onContextmenu = (e: ILayerMouseEvent) => {
61 | this.emit(RenderEvent.Contextmenu, e);
62 | };
63 |
64 | enableCreate() {
65 | this.disableCreate();
66 | this.layers[0].on(LayerEvent.UnClick, this.onCreate);
67 | }
68 |
69 | disableCreate() {
70 | this.layers[0].off(LayerEvent.UnClick, this.onCreate);
71 | }
72 |
73 | enableHover() {
74 | this.disableHover();
75 | this.layers[0]?.on(LayerEvent.Mousemove, this.onMouseMove);
76 | this.layers[0]?.on(LayerEvent.Mouseout, this.onMouseOut);
77 | }
78 |
79 | disableHover() {
80 | this.layers[0]?.off(LayerEvent.Mousemove, this.onMouseMove);
81 | this.layers[0]?.off(LayerEvent.Mouseout, this.onMouseOut);
82 | }
83 |
84 | enableDrag() {
85 | this.disableDrag();
86 | this.layers[0].on(LayerEvent.Mousedown, this.onMouseDown);
87 | this.scene.on(SceneEvent.Dragging, this.onDragging);
88 | this.scene.on(SceneEvent.Mouseup, this.onDragEnd);
89 | this.scene.on(SceneEvent.Dragend, this.onDragEnd);
90 | }
91 |
92 | disableDrag() {
93 | this.layers[0].off(LayerEvent.Mousedown, this.onMouseDown);
94 | this.scene.off(SceneEvent.Dragging, this.onDragging);
95 | this.scene.off(SceneEvent.Mouseup, this.onDragEnd);
96 | this.scene.off(SceneEvent.Dragend, this.onDragEnd);
97 | }
98 |
99 | enableClick() {
100 | this.disableClick();
101 | this.layers[0].on(LayerEvent.Click, this.onClick);
102 | }
103 |
104 | disableClick() {
105 | this.layers[0].off(LayerEvent.Click, this.onClick);
106 | }
107 |
108 | enableContextMenu() {
109 | this.disableContextMenu();
110 | this.layers[0].on(LayerEvent.Contextmenu, this.onContextmenu);
111 | }
112 |
113 | disableContextMenu() {
114 | this.layers[0].off(LayerEvent.Contextmenu, this.onContextmenu);
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/render/polygon-render.ts:
--------------------------------------------------------------------------------
1 | import { ILayer, PolygonLayer } from '@antv/l7';
2 | import { featureCollection } from '@turf/turf';
3 | import { debounce } from 'lodash';
4 | import { LayerEvent, RenderEvent, SceneEvent } from '../constant';
5 | import {
6 | ILayerMouseEvent,
7 | ILineFeature,
8 | IPolygonFeature,
9 | IPolygonStyle,
10 | ISceneMouseEvent,
11 | } from '../typings';
12 | import { LayerRender } from './layer-render';
13 |
14 | export class PolygonRender extends LayerRender {
15 | initLayers(): ILayer[] {
16 | const { normal, hover, active, style, options } = this.style;
17 | const polygonLayer = new PolygonLayer(options ?? {});
18 |
19 | polygonLayer
20 | .source(featureCollection([]))
21 | .color('isHover*isActive', (isHover: boolean, isActive: boolean) => {
22 | return isActive ? active.color : isHover ? hover.color : normal.color;
23 | })
24 | .style(style);
25 |
26 | return [polygonLayer];
27 | }
28 |
29 | onMouseMove = (e: ILayerMouseEvent) => {
30 | this.emit(RenderEvent.Mousemove, e);
31 | };
32 |
33 | onMouseOut = (e: ILayerMouseEvent) => {
34 | this.emit(RenderEvent.Mouseout, e);
35 | };
36 |
37 | onMouseDown = (e: ILayerMouseEvent) => {
38 | this.emit(RenderEvent.Dragstart, e);
39 | };
40 |
41 | onDragging = (e: ILayerMouseEvent) => {
42 | this.emit(RenderEvent.Dragging, e);
43 | };
44 |
45 | onDragEnd = debounce((e: ISceneMouseEvent) => {
46 | this.emit(RenderEvent.Dragend, e);
47 | }, 0);
48 |
49 | onUnClick = (e: ILayerMouseEvent) => {
50 | this.emit(RenderEvent.UnClick, e);
51 | };
52 |
53 | enableHover = () => {
54 | this.disableHover();
55 | this.layers[0]?.on(LayerEvent.Mousemove, this.onMouseMove);
56 | this.layers[0]?.on(LayerEvent.Mouseout, this.onMouseOut);
57 | };
58 |
59 | disableHover = () => {
60 | this.layers[0]?.off(LayerEvent.Mousemove, this.onMouseMove);
61 | this.layers[0]?.off(LayerEvent.Mouseout, this.onMouseOut);
62 | };
63 |
64 | enableDrag() {
65 | this.disableDrag();
66 | this.layers[0].on(LayerEvent.Mousedown, this.onMouseDown);
67 | this.scene.on(SceneEvent.Dragging, this.onDragging);
68 | this.scene.on(SceneEvent.Mouseup, this.onDragEnd);
69 | this.scene.on(SceneEvent.Dragend, this.onDragEnd);
70 | }
71 |
72 | disableDrag() {
73 | this.layers[0].off(LayerEvent.Mousedown, this.onMouseDown);
74 | this.scene.off(SceneEvent.Dragging, this.onDragging);
75 | this.scene.off(SceneEvent.Mouseup, this.onDragEnd);
76 | this.scene.off(SceneEvent.Dragend, this.onDragEnd);
77 | }
78 |
79 | enableUnClick() {
80 | this.disableUnClick();
81 | this.layers[0].on(LayerEvent.UnClick, this.onUnClick);
82 | }
83 |
84 | disableUnClick() {
85 | this.layers[0].off(LayerEvent.UnClick, this.onUnClick);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/render/scene-render.ts:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import EventEmitter from 'eventemitter3';
3 | import { debounce } from 'lodash';
4 | import { RenderEvent, SceneEvent } from '../constant';
5 | import { ISceneMouseEvent } from '../typings';
6 |
7 | type PreviousClick = {
8 | time: number;
9 | x: number;
10 | y: number;
11 | };
12 |
13 | export class SceneRender extends EventEmitter<
14 | RenderEvent | keyof typeof RenderEvent
15 | > {
16 | protected scene: Scene;
17 |
18 | protected previousClick?: PreviousClick;
19 |
20 | constructor(scene: Scene) {
21 | super();
22 | this.scene = scene;
23 | }
24 |
25 | /**
26 | * L7原生dblclick经常误触发,故改用这种方式
27 | * @param e
28 | */
29 | onDblClick = (e: ISceneMouseEvent) => {
30 | const { x = 0, y = 0 } = e.pixel ?? e.point ?? {};
31 | const time = Date.now();
32 |
33 | if (this.previousClick) {
34 | const { x: oldX, y: oldY, time: oldTime } = this.previousClick;
35 | if (
36 | time - oldTime < 300 &&
37 | Math.abs(x - oldX) < 5 &&
38 | Math.abs(y - oldY) < 5
39 | ) {
40 | this.emit(RenderEvent.DblClick, e);
41 | }
42 | }
43 | this.previousClick = { x, y, time };
44 | };
45 |
46 | onMouseMove = (e: ISceneMouseEvent) => {
47 | this.emit(RenderEvent.Mousemove, e);
48 | };
49 |
50 | onMouseDown = (e: ISceneMouseEvent) => {
51 | this.emit(RenderEvent.Dragstart, e);
52 | };
53 |
54 | onDragging = (e: ISceneMouseEvent) => {
55 | this.emit(RenderEvent.Dragging, e);
56 | };
57 |
58 | onDragEnd = debounce((e: ISceneMouseEvent) => {
59 | this.emit(RenderEvent.Dragend, e);
60 | }, 0);
61 |
62 | enableDrag() {
63 | this.disableDrag();
64 | this.scene.on(SceneEvent.Mousedown, this.onMouseDown);
65 | this.scene.on(SceneEvent.Dragging, this.onDragging);
66 | this.scene.on(SceneEvent.Mouseup, this.onDragEnd);
67 | this.scene.on(SceneEvent.Dragend, this.onDragEnd);
68 | }
69 |
70 | disableDrag() {
71 | this.scene.off(SceneEvent.Mousedown, this.onMouseDown);
72 | this.scene.off(SceneEvent.Dragging, this.onDragging);
73 | this.scene.off(SceneEvent.Mouseup, this.onDragEnd);
74 | this.scene.off(SceneEvent.Dragend, this.onDragEnd);
75 | }
76 |
77 | enableMouseMove() {
78 | this.disableMouseMove();
79 | this.scene.on(SceneEvent.Mousemove, this.onMouseMove);
80 | }
81 |
82 | disableMouseMove() {
83 | this.scene.off(SceneEvent.Mousemove, this.onMouseMove);
84 | }
85 |
86 | enableDblClick() {
87 | this.disableDblClick();
88 | this.scene.on(SceneEvent.Mousedown, this.onDblClick);
89 | }
90 |
91 | disableDblClick() {
92 | this.scene.off(SceneEvent.Mousedown, this.onDblClick);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/render/text-render.ts:
--------------------------------------------------------------------------------
1 | import { ILayer, PointLayer } from '@antv/l7';
2 | import { featureCollection } from '@turf/turf';
3 | import { ITextFeature, ITextStyle } from '../typings';
4 | import { LayerRender } from './layer-render';
5 |
6 | export class TextRender extends LayerRender {
7 | initLayers(): ILayer[] {
8 | const { normal, active, style = {}, options } = this.style;
9 | const layer = new PointLayer(options ?? {})
10 | .source(featureCollection([]))
11 | .size('isActive', (isActive: boolean) => {
12 | return isActive ? active.size : normal.size;
13 | })
14 | .color('isActive', (isActive: boolean) => {
15 | return isActive ? active.color : normal.color;
16 | })
17 | .shape('text', 'text')
18 | .style(style);
19 |
20 | return [layer];
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/source/history.ts:
--------------------------------------------------------------------------------
1 | import { cloneDeep } from 'lodash';
2 | import { HistoryConfig, SourceData } from '../typings';
3 |
4 | export class History {
5 | /**
6 | * 保存历史数组的队列,越新的数据越靠前
7 | * @protected
8 | */
9 | protected historyList: SourceData[] = [];
10 |
11 | /**
12 | * 当前回退/重做操作后对应的index下标,回退对应index++,重做对应index--
13 | * @protected
14 | */
15 | protected historyIndex = 0;
16 |
17 | /**
18 | * 配置
19 | * @protected
20 | */
21 | protected config: HistoryConfig;
22 |
23 | constructor({ config }: { config: HistoryConfig }) {
24 | this.config = config;
25 | }
26 |
27 | save(data: SourceData) {
28 | if (!this.config) {
29 | return;
30 | }
31 | const { maxSize } = this.config;
32 |
33 | if (this.historyIndex) {
34 | this.historyList = this.historyList.slice(this.historyIndex);
35 | this.historyIndex = 0;
36 | }
37 |
38 | if (this.historyList.length >= maxSize) {
39 | this.historyList.pop();
40 | }
41 | const cloneData = cloneDeep(data);
42 | this.historyList.unshift(cloneData);
43 | return cloneData;
44 | }
45 |
46 | revert() {
47 | if (
48 | !this.historyList.length ||
49 | this.historyIndex >= this.historyList.length - 1
50 | ) {
51 | return;
52 | }
53 | const previousData = this.historyList[++this.historyIndex];
54 | if (previousData) {
55 | return cloneDeep(previousData);
56 | }
57 | }
58 |
59 | redo() {
60 | if (!this.historyList.length || this.historyIndex <= 0) {
61 | return;
62 | }
63 | const nextData = this.historyList[--this.historyIndex];
64 | if (nextData) {
65 | return cloneDeep(nextData);
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/source/index.ts:
--------------------------------------------------------------------------------
1 | export * from './source';
2 |
--------------------------------------------------------------------------------
/src/typings/dom.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 遍历当前结点 dom 的本身及其所有父节点,直到找到对应
3 | * @param dom
4 | * @param className
5 | * @returns
6 | */
7 | export const getParentByClassName = (dom: Element, className: string) => {
8 | let currentDom: Element | null = dom;
9 | while (currentDom && !Array.from(currentDom.classList).includes(className)) {
10 | currentDom = currentDom.parentElement;
11 | }
12 | return currentDom;
13 | };
14 |
--------------------------------------------------------------------------------
/src/typings/drawer.ts:
--------------------------------------------------------------------------------
1 | import { Feature, LineString, Point, Polygon, Position } from '@turf/turf';
2 | import { Content, Props as TippyProps } from 'tippy.js';
3 | import { HistoryConfig } from './source';
4 | import { IStyle } from './style';
5 | import { ILineFeature, IPointFeature, IPolygonFeature } from './feature';
6 |
7 | /**
8 | * 鼠标指针类型
9 | */
10 | export type ICursorType =
11 | | 'draw'
12 | | 'pointHover'
13 | | 'pointDrag'
14 | | 'lineHover'
15 | | 'lineDrag'
16 | | 'polygonHover'
17 | | 'polygonDrag';
18 |
19 | /**
20 | * 鼠标指针类型键值对
21 | */
22 | export type ICursor = Record;
23 |
24 | export type KeyBoardConfig = Partial<{
25 | remove: string[] | false;
26 | revert: string[] | false;
27 | redo: string[] | false;
28 | }>;
29 |
30 | /**
31 | * 基础Drawer配置
32 | */
33 | export interface IBaseModeOptions {
34 | style: IStyle;
35 | cursor: ICursor;
36 | initialData?: F[];
37 | editable: boolean;
38 | autoActive: boolean;
39 | multiple: boolean;
40 | helper: any | boolean;
41 | maxCount: number;
42 | bbox?: boolean;
43 | popup: PopupOptions | boolean;
44 | history: HistoryConfig | false;
45 | keyboard: KeyBoardConfig | false;
46 | }
47 |
48 | /**
49 | * 距离文案配置
50 | */
51 | export interface IDistanceOptions {
52 | showTotalDistance: boolean;
53 | showDashDistance: boolean;
54 | showWhen: ('normal' | 'active')[];
55 | format: (meters: number, points: Feature[]) => string;
56 | }
57 |
58 | /**
59 | * 面积文案配置
60 | */
61 | export interface IAreaOptions {
62 | format: (squareMeters: number, polygonFeature: Feature) => string;
63 | showWhen: ('normal' | 'active')[];
64 | }
65 |
66 | export type PopupOptions = Partial;
67 |
68 | export type PopupContent = Content | null | undefined;
69 |
70 | export type AdsorbTargetFeature =
71 | | Feature
72 | | IPointFeature
73 | | ILineFeature
74 | | IPolygonFeature;
75 |
76 | export interface IAdsorbOptions {
77 | data:
78 | | 'drawData'
79 | | 'allDrawData'
80 | | AdsorbTargetFeature[]
81 | | ((position: Position) => AdsorbTargetFeature[]);
82 | pointAdsorbPixel: number;
83 | lineAdsorbPixel: number;
84 | }
85 |
86 | export type AdsorbResult = {
87 | points: Feature[];
88 | lines: Feature[];
89 | };
90 |
--------------------------------------------------------------------------------
/src/typings/feature.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Geometry,
3 | GeometryCollection,
4 | } from '@turf/helpers/dist/js/lib/geojson';
5 | import { Feature, LineString, Point, Polygon } from '@turf/turf';
6 |
7 | export interface IBaseProperties {
8 | id: string;
9 | isDraw?: boolean;
10 | isActive?: boolean;
11 | multiIndex?: number;
12 | [key: string]: any;
13 | }
14 |
15 | export interface IBaseFeature<
16 | G extends Geometry | GeometryCollection = Geometry,
17 | P extends IBaseProperties = IBaseProperties,
18 | > extends Feature {
19 | type: 'Feature';
20 | geometry: G;
21 | properties: P;
22 | }
23 |
24 | // 点类型
25 | export interface IPointProperties extends IBaseProperties {
26 | isHover?: boolean;
27 | isDrag?: boolean;
28 | createTime: number;
29 | }
30 |
31 | export type IPointFeature = IBaseFeature;
32 |
33 | // 线类型
34 | export interface ILineProperties extends IBaseProperties {
35 | nodes: IPointFeature[];
36 | isHover?: boolean;
37 | isDrag?: boolean;
38 | createTime: number;
39 | }
40 |
41 | export type ILineFeature = IBaseFeature;
42 |
43 | // 面类型
44 | export interface IPolygonProperties extends IBaseProperties {
45 | nodes: IPointFeature[];
46 | line: ILineFeature;
47 | isHover?: boolean;
48 | isDrag?: boolean;
49 | createTime: number;
50 | }
51 |
52 | export type IPolygonFeature = IBaseFeature;
53 |
54 | // 中点Feature Properties类型
55 | export interface IMidPointProperties extends IBaseProperties {
56 | startId: string;
57 | endId: string;
58 | }
59 |
60 | // 中点Feature类型
61 | export type IMidPointFeature = IBaseFeature;
62 |
63 | // 虚线Feature类型
64 | export type IDashLineFeature = IBaseFeature;
65 |
66 | // 文本Feature Properties类型
67 | export interface ITextProperties extends IBaseProperties {
68 | type: 'distance' | 'totalDistance' | 'dash' | 'area';
69 | text: string;
70 | meters: number;
71 | }
72 |
73 | // 文本Feature类型
74 | export type ITextFeature = IBaseFeature;
75 |
76 | export type FeatureUpdater =
77 | | F[]
78 | | ((newFeatures: F[]) => F[]);
79 |
--------------------------------------------------------------------------------
/src/typings/helper.ts:
--------------------------------------------------------------------------------
1 | import { PopupContent } from './drawer';
2 |
3 | export type IPointHelperOptions = {
4 | draw: PopupContent;
5 | pointHover: PopupContent;
6 | pointDrag: PopupContent;
7 | };
8 |
9 | export type ILineHelperOptions = IPointHelperOptions & {
10 | lineHover: PopupContent;
11 | lineDrag: PopupContent;
12 | midPointHover: PopupContent;
13 | drawFinish: PopupContent;
14 | };
15 |
16 | export type IPolygonHelperOptions = ILineHelperOptions & {
17 | drawContinue: PopupContent;
18 | polygonHover: PopupContent;
19 | polygonDrag: PopupContent;
20 | };
21 |
22 | export type IDragPolygonHelperOptions = IPolygonHelperOptions;
23 |
--------------------------------------------------------------------------------
/src/typings/index.ts:
--------------------------------------------------------------------------------
1 | export * from './drawer';
2 | export * from './feature';
3 | export * from './render';
4 | export * from './scene';
5 | export * from './source';
6 | export * from './style';
7 | export * from './utils';
8 | export * from './helper';
9 | export * from './dom';
10 |
--------------------------------------------------------------------------------
/src/typings/render.ts:
--------------------------------------------------------------------------------
1 | import { IBaseStyle } from './style';
2 |
3 | export type IRenderType =
4 | | 'point'
5 | | 'line'
6 | | 'polygon'
7 | | 'midPoint'
8 | | 'dashLine'
9 | | 'text';
10 |
11 | export interface IRenderOptions {
12 | style: S;
13 | }
14 |
--------------------------------------------------------------------------------
/src/typings/scene.ts:
--------------------------------------------------------------------------------
1 | import { IBaseFeature } from './feature';
2 |
3 | /**
4 | * 经纬度信息
5 | */
6 | export interface ILngLat {
7 | lng: number;
8 | lat: number;
9 | }
10 |
11 | /**
12 | * Scene回调事件类型
13 | */
14 | export interface ISceneMouseEvent {
15 | type: string;
16 | lnglat: ILngLat;
17 | lngLat: ILngLat;
18 | pixel?: { x: number; y: number };
19 | point?: { x: number; y: number };
20 | }
21 |
22 | /**
23 | * 图层回调事件类型
24 | */
25 | export interface ILayerMouseEvent {
26 | type: string;
27 | feature?: T;
28 | featureId?: number;
29 | lngLat: ILngLat;
30 | x: number;
31 | y: number;
32 | }
33 |
--------------------------------------------------------------------------------
/src/typings/source.ts:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import {
3 | DashLineRender,
4 | LineRender,
5 | MidPointRender,
6 | PointRender,
7 | PolygonRender,
8 | TextRender,
9 | } from '../render';
10 | import {
11 | IDashLineFeature,
12 | ILineFeature,
13 | IMidPointFeature,
14 | IPointFeature,
15 | IPolygonFeature,
16 | ITextFeature,
17 | } from './feature';
18 | // import { PointRender, LineRender, PolygonRender, TextRender } from '../render';
19 |
20 | /**
21 | * Source数据类型
22 | */
23 | export interface SourceData {
24 | point: IPointFeature[];
25 | line: ILineFeature[];
26 | polygon: IPolygonFeature[];
27 | midPoint: IMidPointFeature[];
28 | dashLine: IDashLineFeature[];
29 | text: ITextFeature[];
30 | }
31 |
32 | export type HistoryConfig = {
33 | maxSize: number;
34 | };
35 |
36 | /**
37 | * Render key => value 映射关系
38 | */
39 | export type RenderMap = Partial<{
40 | point: PointRender;
41 | line: LineRender;
42 | polygon: PolygonRender;
43 | midPoint: MidPointRender;
44 | dashLine: DashLineRender;
45 | text: TextRender;
46 | }>;
47 |
48 | /**
49 | * Source构造器中传输的配置
50 | */
51 | export interface SourceOptions {
52 | data?: Partial;
53 | render: RenderMap;
54 | history?: HistoryConfig;
55 | scene: Scene;
56 | bbox: boolean;
57 | }
58 |
--------------------------------------------------------------------------------
/src/typings/style.ts:
--------------------------------------------------------------------------------
1 | import { ILayer, ILayerConfig } from '@antv/l7';
2 |
3 | /**
4 | * Style的基类
5 | */
6 | export interface IBaseStyle {
7 | options?: Partial;
8 | normal: ItemType;
9 | style?: any;
10 | callback?: (layers: ILayer[]) => void; // 初始化图层之后的回调
11 | }
12 |
13 | export interface IComplexStyle extends IBaseStyle {
14 | hover: ItemType;
15 | active: ItemType;
16 | }
17 |
18 | /**
19 | * Point的单个Style项
20 | */
21 | export interface IPointStyleItem {
22 | color: string;
23 | shape: string;
24 | size: number;
25 | }
26 |
27 | /**
28 | * 整个Style类型
29 | */
30 | export type IPointStyle = IComplexStyle;
31 |
32 | /**
33 | *
34 | */
35 | export interface ILineStyleItem {
36 | color: string;
37 | size: number;
38 | }
39 |
40 | export type ILineStyle = IComplexStyle;
41 |
42 | export interface IPolygonStyleItem {
43 | color: string;
44 | }
45 |
46 | export type IPolygonStyle = IComplexStyle;
47 |
48 | export type IMidPointStyleItem = IPointStyleItem;
49 |
50 | export type IMidPointStyle = IBaseStyle;
51 |
52 | export type IDashLineStyle = IBaseStyle;
53 |
54 | export type ITextStyleItem = Omit;
55 |
56 | export type ITextStyle = IBaseStyle & {
57 | active: ITextStyleItem;
58 | };
59 |
60 | export interface IStyle {
61 | point: IPointStyle;
62 | line: ILineStyle;
63 | polygon: IPolygonStyle;
64 | midPoint: IMidPointStyle;
65 | dashLine: IDashLineStyle;
66 | text: ITextStyle;
67 | }
68 |
--------------------------------------------------------------------------------
/src/typings/utils.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 赋予参数对象T深度可选
3 | */
4 | export type DeepPartial = {
5 | [P in keyof T]?: DeepPartial;
6 | };
7 |
--------------------------------------------------------------------------------
/src/utils/calc.ts:
--------------------------------------------------------------------------------
1 | import {
2 | along,
3 | area,
4 | center,
5 | centerOfMass,
6 | coordAll,
7 | distance,
8 | Feature,
9 | featureCollection,
10 | length,
11 | LineString,
12 | point,
13 | Polygon,
14 | } from '@turf/turf';
15 | import {
16 | IAreaOptions,
17 | IDashLineFeature,
18 | IDistanceOptions,
19 | ILineFeature,
20 | ITextFeature,
21 | ITextProperties,
22 | } from '../typings';
23 | import { getUuid } from './feature';
24 |
25 | /**
26 | * 将数字转四舍五入为目标精度位数的数字
27 | * @param num
28 | * @param precision
29 | * @returns
30 | */
31 | export const getPrecisionNumber = (num: number, precision = 6) => {
32 | return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision);
33 | };
34 |
35 | /**
36 | * 获取线段的中心点Feature
37 | * @param feature
38 | */
39 | export const getLineCenterPoint = (feature: Feature) => {
40 | const dis = length(feature, {
41 | units: 'meters',
42 | });
43 | return along(feature, dis / 2, {
44 | units: 'meters',
45 | });
46 | };
47 |
48 | /**
49 | * 返回线段对应的距离文本
50 | * @param feature
51 | * @param showTotalDistance
52 | * @param format
53 | * @param properties
54 | */
55 | export const calcDistanceTextsByLine = (
56 | feature: ILineFeature | IDashLineFeature,
57 | {
58 | showTotalDistance,
59 | format,
60 | }: Pick,
61 | properties: Partial = {},
62 | ) => {
63 | const textList: ITextFeature[] = [];
64 | if (showTotalDistance) {
65 | const text = getLineCenterPoint(feature) as ITextFeature;
66 | const meters = length(feature, {
67 | units: 'meters',
68 | });
69 | const pointFeatures = coordAll(feature).map((item) => point(item));
70 | text.properties = {
71 | id: getUuid('text'),
72 | isActive: false,
73 | meters,
74 | text: format(meters, pointFeatures),
75 | type: 'totalDistance',
76 | ...properties,
77 | };
78 | textList.push(text);
79 | } else {
80 | const { coordinates } = feature.geometry;
81 | for (let index = 0; index < coordinates.length - 1; index++) {
82 | const currentPoint = point(coordinates[index]);
83 | const nextPoint = point(coordinates[index + 1]);
84 | const meters = distance(currentPoint, nextPoint, {
85 | units: 'meters',
86 | });
87 |
88 | const text = center(
89 | featureCollection([currentPoint, nextPoint]),
90 | ) as ITextFeature;
91 | text.properties = {
92 | id: getUuid('text'),
93 | isActive: false,
94 | meters,
95 | text: format(meters, [currentPoint, nextPoint]),
96 | type: 'distance',
97 | ...properties,
98 | };
99 | textList.push(text);
100 | }
101 | }
102 | return textList;
103 | };
104 |
105 | /**
106 | * 根据传入的polygon和options配置获取面积文本Feature
107 | * @param feature
108 | * @param options
109 | * @param properties
110 | */
111 | export const calcAreaText = (
112 | feature: Feature,
113 | options: Pick,
114 | properties: Partial = {},
115 | ) => {
116 | const { format } = options;
117 | const meters = area(feature);
118 | return centerOfMass(feature, {
119 | properties: {
120 | meters,
121 | text: format(meters, feature),
122 | type: 'area',
123 | isActive: false,
124 | ...properties,
125 | },
126 | }) as ITextFeature;
127 | };
128 |
--------------------------------------------------------------------------------
/src/utils/common.ts:
--------------------------------------------------------------------------------
1 | import { Scene } from '@antv/l7';
2 | import { Position } from '@turf/turf';
3 | import { ILayerMouseEvent, ILngLat, ISceneMouseEvent } from '../typings';
4 | import { isEqual } from 'lodash';
5 |
6 | // @ts-ignore
7 | export const isDev = process.env.NODE_ENV === 'development';
8 |
9 | /**
10 | * 获取完全覆盖地图区域的DOM,会根据地图类型返回不同的结果
11 | * @param scene
12 | */
13 | export const getMapDom = (scene: Scene): HTMLElement | null => {
14 | const container = scene.getContainer();
15 | return (
16 | container?.querySelector('.l7-marker-container') ??
17 | container?.querySelector('.BMap_mask') ??
18 | container?.querySelector('#tdt-L7') ??
19 | scene.getMapCanvasContainer() ??
20 | container?.querySelector('.l7-scene') ??
21 | container?.querySelector('.l7-control-container') ??
22 | container?.querySelector('.l7-marker-container2') ??
23 | null
24 | );
25 | };
26 |
27 | /**
28 | * 磨平L7 Scene 鼠标事件返回的经纬度差异
29 | * @param e
30 | */
31 | export const getLngLat = (e: ISceneMouseEvent | ILayerMouseEvent) => {
32 | // @ts-ignore
33 | return e.lngLat || e.lnglat || e.latlng;
34 | };
35 |
36 | export const getPosition: (
37 | e: ISceneMouseEvent | ILayerMouseEvent,
38 | ) => Position = (e) => {
39 | const { lng, lat } = getLngLat(e);
40 | return [lng, lat];
41 | };
42 |
43 | /**
44 | * 将lnglat转换为position格式
45 | * @param lng
46 | * @param lat
47 | */
48 | export const transLngLat2Position: (lngLat: ILngLat) => Position = ({
49 | lng,
50 | lat,
51 | }) => [lng, lat];
52 |
53 | /**
54 | * 找到最小值的下标
55 | * @param array
56 | */
57 | export const findMinIndex = (array: number[]) => {
58 | let maxValue = Number.MAX_SAFE_INTEGER;
59 | let maxIndex = 0;
60 | const length = array.length;
61 | for (let index = 0; index < length; index++) {
62 | if (array[index] < maxValue) {
63 | maxValue = array[index];
64 | maxIndex = index;
65 | }
66 | }
67 | return maxIndex;
68 | };
69 |
70 | export const splitByPosition = (
71 | positions: Position[],
72 | splitPosition: Position,
73 | ) => {
74 | const linePositionsList: Position[][] = [];
75 | let linePositions: Position[] = [];
76 | positions.forEach((position) => {
77 | if (!isEqual(position, splitPosition)) {
78 | linePositions.push(position);
79 | } else if (linePositions.length) {
80 | linePositionsList.push(linePositions);
81 | linePositions = [];
82 | }
83 | });
84 | if (linePositions.length) {
85 | linePositionsList.push(linePositions);
86 | }
87 | return linePositionsList;
88 | };
89 |
--------------------------------------------------------------------------------
/src/utils/event.ts:
--------------------------------------------------------------------------------
1 | import { ILayerMouseEvent, ISceneMouseEvent } from '../typings';
2 | import { Position } from '@turf/turf';
3 |
4 | export const resetEventLngLat = (
5 | e: ILayerMouseEvent | ISceneMouseEvent,
6 | position: Position,
7 | ) => {
8 | const [lng, lat] = position;
9 | if (e.lngLat) {
10 | e.lngLat = {
11 | lng,
12 | lat,
13 | };
14 | }
15 | // @ts-ignore
16 | if (e.lnglat) {
17 | // @ts-ignore
18 | e.lnglat = {
19 | lng,
20 | lat,
21 | };
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './calc';
2 | export * from './common';
3 | export * from './feature';
4 | export * from './adsorb';
5 | export * from './event';
6 | export * from './style';
7 |
--------------------------------------------------------------------------------
/src/utils/style.ts:
--------------------------------------------------------------------------------
1 | import { DeepPartial, IStyle } from '../typings';
2 |
3 | /**
4 | * 获取单个颜色的 style 供 draw 实例使用
5 | * @param color
6 | * @returns
7 | */
8 | export function getSingleColorStyle(color: string): DeepPartial {
9 | return {
10 | point: {
11 | normal: { color },
12 | hover: { color },
13 | active: { color },
14 | },
15 | line: {
16 | normal: { color },
17 | hover: { color },
18 | active: { color },
19 | },
20 | polygon: {
21 | normal: { color },
22 | hover: { color },
23 | active: { color },
24 |
25 | style: {
26 | // @ts-ignore
27 | opacity: 0.2,
28 | },
29 | },
30 | text: {
31 | normal: { color },
32 | active: { color },
33 | },
34 | midPoint: {
35 | normal: { color },
36 | },
37 | dashLine: {
38 | normal: { color },
39 | },
40 | };
41 | }
42 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "target": "esnext",
5 | "module": "esnext",
6 | "moduleResolution": "node",
7 | "importHelpers": true,
8 | "jsx": "react",
9 | "esModuleInterop": true,
10 | "types": ["jest"],
11 | "strict": true,
12 | "sourceMap": true,
13 | "baseUrl": "./",
14 | "skipLibCheck": true,
15 | "paths": {
16 | "@antv/l7-draw": ["./src/index.ts"]
17 | }
18 | },
19 | "include": ["docs", "src"],
20 | "exclude": [
21 | "node_modules",
22 | "lib",
23 | "es",
24 | "dist",
25 | "typings",
26 | "**/__test__",
27 | "test"
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.css';
2 | declare module '*.less';
3 |
--------------------------------------------------------------------------------