├── .nvmrc ├── pnpm-workspace.yaml ├── vitest └── setupTests.ts ├── packages ├── ol-plot-vue │ ├── README.md │ ├── vue2 │ │ ├── index.js │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── vite.config.ts │ ├── src │ │ ├── assets │ │ │ └── img │ │ │ │ ├── Arc.png │ │ │ │ ├── Circle.png │ │ │ │ ├── Curve.png │ │ │ │ ├── Point.png │ │ │ │ ├── Sector.png │ │ │ │ ├── scheme.png │ │ │ │ ├── theme.png │ │ │ │ ├── Arc-hover.png │ │ │ │ ├── CurveFlag.png │ │ │ │ ├── Ellipse.png │ │ │ │ ├── FineArrow.png │ │ │ │ ├── Polygon.png │ │ │ │ ├── Polyline.png │ │ │ │ ├── RectAngle.png │ │ │ │ ├── RectFlag.png │ │ │ │ ├── TextArea.png │ │ │ │ ├── AttackArrow.png │ │ │ │ ├── Curve-hover.png │ │ │ │ ├── DoubleArrow.png │ │ │ │ ├── FreePolygon.png │ │ │ │ ├── Point-hover.png │ │ │ │ ├── SquadCombat.png │ │ │ │ ├── Circle-hover.png │ │ │ │ ├── Ellipse-hover.png │ │ │ │ ├── FreeHandLine.png │ │ │ │ ├── GatheringPlace.png │ │ │ │ ├── Polygon-hover.png │ │ │ │ ├── Polyline-hover.png │ │ │ │ ├── RectFlag-hover.png │ │ │ │ ├── RectInclined1.png │ │ │ │ ├── RectInclined2.png │ │ │ │ ├── Sector-hover.png │ │ │ │ ├── StraightArrow.png │ │ │ │ ├── TextArea-hover.png │ │ │ │ ├── TriangleFlag.png │ │ │ │ ├── AssaultDirection.png │ │ │ │ ├── CurveFlag-hover.png │ │ │ │ ├── FineArrow-hover.png │ │ │ │ ├── RectAngle-hover.png │ │ │ │ ├── AttackArrow-hover.png │ │ │ │ ├── DoubleArrow-hover.png │ │ │ │ ├── FreeHandLine-hover.png │ │ │ │ ├── FreePolygon-hover.png │ │ │ │ ├── RectInclined1-hover.png │ │ │ │ ├── RectInclined2-hover.png │ │ │ │ ├── SquadCombat-hover.png │ │ │ │ ├── StraightArrow-hover.png │ │ │ │ ├── TailedAttackArrow.png │ │ │ │ ├── TriangleFlag-hover.png │ │ │ │ ├── GatheringPlace-hover.png │ │ │ │ ├── AssaultDirection-hover.png │ │ │ │ └── TailedAttackArrow-hover.png │ │ ├── ColorPicker │ │ │ └── README.md │ │ ├── __tests__ │ │ │ └── util.test.ts │ │ ├── index.ts │ │ ├── Input │ │ │ └── index.vue │ │ └── InputNumber │ │ │ └── index.vue │ ├── env.d.ts │ ├── scripts │ │ ├── postbuild.js │ │ └── postinstall.js │ ├── tsconfig.json │ ├── vite.config.ts │ ├── CHANGELOG.md │ └── package.json └── ol-plot │ ├── typings.d.ts │ ├── src │ ├── core │ │ └── PlotEvent.ts │ ├── __tests__ │ │ └── util.test.ts │ ├── geometry │ │ ├── Arrow │ │ │ ├── AssaultDirection.ts │ │ │ ├── SquadCombat.ts │ │ │ ├── TailedAttackArrow.ts │ │ │ ├── TailedSquadCombat.ts │ │ │ ├── StraightArrow.ts │ │ │ └── FineArrow.ts │ │ ├── index.ts │ │ ├── Polyline │ │ │ ├── Polyline.ts │ │ │ ├── FreeHandLine.ts │ │ │ └── Curve.ts │ │ ├── Polygon │ │ │ ├── FreePolygon.ts │ │ │ ├── Polygon.ts │ │ │ ├── RectAngle.ts │ │ │ ├── Sector.ts │ │ │ ├── Lune.ts │ │ │ ├── ClosedCurve.ts │ │ │ ├── Rectinclined2.ts │ │ │ ├── GatheringPlace.ts │ │ │ └── Rectinclined1.ts │ │ ├── Point │ │ │ ├── Pennant.ts │ │ │ └── Point.ts │ │ ├── Circle │ │ │ ├── Circle.ts │ │ │ └── Ellipse.ts │ │ ├── Flag │ │ │ ├── TriangleFlag.ts │ │ │ ├── RectFlag.ts │ │ │ └── CurveFlag.ts │ │ └── Arc │ │ │ └── Arc.ts │ ├── index.ts │ ├── constants.ts │ ├── utils │ │ ├── layerUtils.ts │ │ ├── PlotTypes.ts │ │ ├── domUtils.ts │ │ └── factory.ts │ └── less │ │ └── index.less │ ├── tsconfig.json │ ├── CHANGELOG.md │ ├── package.json │ ├── vite.config.ts │ └── README.md ├── .eslintrc.js ├── tsconfig.eslint.json ├── playground ├── vue3 │ ├── public │ │ └── image │ │ │ └── plot.png │ ├── tsconfig.json │ ├── src │ │ ├── index.ts │ │ └── App.vue │ ├── index.html │ ├── vite.config.ts │ └── package.json ├── single │ ├── tsconfig.json │ ├── vite.config.ts │ ├── package.json │ ├── src │ │ └── index.ts │ └── index.html └── vue2 │ ├── tsconfig.json │ ├── index.html │ ├── src │ ├── index.ts │ └── App.vue │ ├── vite.config.ts │ └── package.json ├── .gitignore ├── .prettierrc.js ├── .npmignore ├── .eslintignore ├── .changeset ├── config.json └── README.md ├── .prettierignore ├── .editorconfig ├── CHANGELOG.md ├── tsconfig.json ├── CONTRIBUTING.md ├── LICENSE ├── package.json ├── .github └── workflows │ └── ci.yml └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 18.17.0 -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - docs 3 | - packages/* 4 | - playground/* 5 | -------------------------------------------------------------------------------- /vitest/setupTests.ts: -------------------------------------------------------------------------------- 1 | import { afterEach } from 'vitest'; 2 | 3 | afterEach(() => void 0); 4 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/README.md: -------------------------------------------------------------------------------- 1 | # ol-plot-vue 2 | 3 | 是 ol-plot 的一个简单的绘制 Vue 组件,支持 Vue2 和 Vue3。 4 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/vue2/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | 3 | fs.copySync('./dist', '../dist/v2'); 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: [ 4 | '@aurorafe/eslint-config-vue', 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /playground/vue3/public/image/plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/playground/vue3/public/image/plot.png -------------------------------------------------------------------------------- /packages/ol-plot/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.json'; 2 | 3 | type WithNull = T | null; 4 | type WithUndef = T | undefined; 5 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Arc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Arc.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | node_modules/ 4 | 5 | node_modules 6 | dist 7 | coverage 8 | 9 | *.log 10 | .cache 11 | .DS_Store 12 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Circle.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Curve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Curve.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Point.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Sector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Sector.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/scheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/scheme.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/theme.png -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | const { prettierRules } = require('@aurorafe/eslint-config-base/rules') 2 | 3 | module.exports = { 4 | ...prettierRules, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/ColorPicker/README.md: -------------------------------------------------------------------------------- 1 | ## ColorPicker 2 | 3 | 来源:https://github.com/zuley/vue-color-picker 4 | 5 | 做了一定的改造直接支持 Vue2 和 Vue3 6 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Arc-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Arc-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/CurveFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/CurveFlag.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Ellipse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Ellipse.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/FineArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/FineArrow.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Polygon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Polygon.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Polyline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Polyline.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/RectAngle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/RectAngle.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/RectFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/RectFlag.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/TextArea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/TextArea.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/AttackArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/AttackArrow.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Curve-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Curve-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/DoubleArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/DoubleArrow.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/FreePolygon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/FreePolygon.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Point-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Point-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/SquadCombat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/SquadCombat.png -------------------------------------------------------------------------------- /playground/single/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": [ 4 | "src", 5 | "single/vite.config.ts" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /playground/vue3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": [ 4 | "src", 5 | "single/vite.config.ts" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Circle-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Circle-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Ellipse-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Ellipse-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/FreeHandLine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/FreeHandLine.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/GatheringPlace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/GatheringPlace.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Polygon-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Polygon-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Polyline-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Polyline-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/RectFlag-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/RectFlag-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/RectInclined1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/RectInclined1.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/RectInclined2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/RectInclined2.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/Sector-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/Sector-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/StraightArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/StraightArrow.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/TextArea-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/TextArea-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/TriangleFlag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/TriangleFlag.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/AssaultDirection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/AssaultDirection.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/CurveFlag-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/CurveFlag-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/FineArrow-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/FineArrow-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/RectAngle-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/RectAngle-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/AttackArrow-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/AttackArrow-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/DoubleArrow-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/DoubleArrow-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/FreeHandLine-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/FreeHandLine-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/FreePolygon-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/FreePolygon-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/RectInclined1-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/RectInclined1-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/RectInclined2-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/RectInclined2-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/SquadCombat-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/SquadCombat-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/StraightArrow-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/StraightArrow-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/TailedAttackArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/TailedAttackArrow.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/TriangleFlag-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/TriangleFlag-hover.png -------------------------------------------------------------------------------- /playground/vue2/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": [ 4 | "src", 5 | "vite.config.ts", 6 | "vite.lib.ts" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/GatheringPlace-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/GatheringPlace-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/AssaultDirection-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/AssaultDirection-hover.png -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/assets/img/TailedAttackArrow-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakitam-fdd/ol-plot/HEAD/packages/ol-plot-vue/src/assets/img/TailedAttackArrow-hover.png -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | build/ 2 | example/ 3 | config/ 4 | docs/ 5 | node_modules/ 6 | test/ 7 | .editorconfig 8 | .babelrc 9 | coverage/ 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | const component: DefineComponent<{}, {}, any> 6 | export default component 7 | } 8 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | *.html 2 | 3 | node_modules 4 | 5 | # build 6 | coverage 7 | dist 8 | 9 | # other 10 | .eslintrc.js 11 | .prettierrc.js 12 | vitest.config.ts 13 | 14 | # lib 15 | 16 | playground/lib 17 | 18 | # css 19 | **/*.less 20 | -------------------------------------------------------------------------------- /playground/vue3/src/index.ts: -------------------------------------------------------------------------------- 1 | import 'ol-plot-vue/dist/style.css'; 2 | import { createApp } from 'vue'; 3 | import Plot from 'ol-plot-vue'; 4 | import App from './App.vue'; 5 | 6 | const app = createApp(App); 7 | 8 | app.use(Plot); 9 | 10 | app.mount('#app'); 11 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/scripts/postbuild.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | 3 | const filterFunc = (src, dest) => { 4 | return src.indexOf('dist/v') <= -1; 5 | }; 6 | 7 | fs.copySync('./dist', './.lib', { filter: filterFunc }); 8 | fs.copySync('./.lib', './dist/v3'); 9 | 10 | fs.removeSync('./.lib'); 11 | -------------------------------------------------------------------------------- /packages/ol-plot/src/core/PlotEvent.ts: -------------------------------------------------------------------------------- 1 | import BaseEvent from 'ol/events/Event'; 2 | 3 | export default class PlotEvent extends BaseEvent { 4 | constructor(type: string, params = {}) { 5 | super(type); 6 | 7 | Object.keys(params).forEach((key) => { 8 | this[key] = params[key]; 9 | }); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /playground/single/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | 3 | export default defineConfig(({ mode }) => ({ 4 | base: './', 5 | publicDir: 'public', 6 | define: { 7 | 'process.env': { 8 | NODE_ENV: mode, 9 | }, 10 | }, 11 | optimizeDeps: { 12 | include: [], 13 | exclude: ['ol-plot'], 14 | }, 15 | })); 16 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": ["@changesets/changelog-github", { "repo": "sakitam-fdd/ol-plot" }], 4 | "commit": true, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /playground/vue2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ol-plot-vue 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /playground/vue3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ol-plot-vue 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | ## OS 2 | .DS_Store 3 | .idea 4 | .npmrc 5 | .husky 6 | 7 | ## Ignored 8 | .dockerignore 9 | .eslintignore 10 | .editorconfig 11 | .gitignore 12 | .prettierignore 13 | .eslintcache 14 | 15 | ## Other 16 | *.toml 17 | *.lock 18 | *.log 19 | *.md 20 | *.svg 21 | *.png 22 | 23 | LICENSE 24 | Dockerfile* 25 | 26 | package.json 27 | package-lock.json 28 | yarn-error.log 29 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | charset = utf-8 9 | 10 | [*.{js.ts,html,css}] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.{json,yml}] 15 | indent_style = space 16 | indent_size = 2 17 | 18 | [*.md] 19 | trim_trailing_whitespace = false 20 | 21 | [Makefile] 22 | indent_style = tab 23 | -------------------------------------------------------------------------------- /playground/single/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "single", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "vite --host", 6 | "build": "vite build" 7 | }, 8 | "dependenciesMeta": { 9 | "ol-plot": { 10 | "injected": true 11 | } 12 | }, 13 | "dependencies": { 14 | "ol": "^6.15.1", 15 | "ol-plot": "workspace:*" 16 | }, 17 | "devDependencies": { 18 | "vite": "^4.3.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/__tests__/util.test.ts: -------------------------------------------------------------------------------- 1 | import { test, expect, describe, beforeAll, afterAll } from 'vitest'; 2 | 3 | beforeAll(async () => { 4 | console.log(`[ol-plot-vue]: start testing...`); 5 | }); 6 | 7 | afterAll(async () => { 8 | console.log(`[ol-plot-vue]: test end`); 9 | }); 10 | 11 | describe('utils', async () => { 12 | test('isNumber', async () => { 13 | const a = false; 14 | expect(a).toBe(false); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/ol-plot/src/__tests__/util.test.ts: -------------------------------------------------------------------------------- 1 | import { test, expect, describe, beforeAll, afterAll } from 'vitest'; 2 | 3 | import { isObject } from '../utils/utils'; 4 | 5 | beforeAll(async () => { 6 | console.log(`[ol-plot]: start testing...`); 7 | }); 8 | 9 | afterAll(async () => { 10 | console.log(`[ol-plot]: test end`); 11 | }); 12 | 13 | describe('utils', async () => { 14 | test('isObject', async () => { 15 | expect(isObject({})).toBe(true); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /playground/vue2/src/index.ts: -------------------------------------------------------------------------------- 1 | import 'ol-plot-vue/dist/style.css'; 2 | import Vue from 'vue'; 3 | import VueCompositionAPI from '@vue/composition-api'; 4 | 5 | import Plot from 'ol-plot-vue'; 6 | import App from './App.vue'; 7 | 8 | Vue.config.productionTip = false; 9 | Vue.use(VueCompositionAPI); 10 | Vue.use(Plot); 11 | 12 | console.log(Vue.version) 13 | 14 | /* eslint-disable no-new */ 15 | new Vue({ 16 | el: '#app', 17 | components: { App }, 18 | template: '', 19 | }); 20 | -------------------------------------------------------------------------------- /playground/vue3/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | 4 | export default defineConfig(({ command, mode }) => ({ 5 | base: command === 'build' ? './' : '/', 6 | plugins: [vue()], 7 | publicDir: 'public', 8 | // server: { 9 | // port: 8081, 10 | // }, 11 | define: { 12 | 'process.env': { 13 | NODE_ENV: mode, 14 | }, 15 | }, 16 | optimizeDeps: { 17 | exclude: ['vue-demi'], 18 | }, 19 | })); 20 | -------------------------------------------------------------------------------- /playground/vue3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "vite --host", 6 | "build": "vite build" 7 | }, 8 | "dependenciesMeta": { 9 | "ol-plot-vue": { 10 | "injected": true 11 | } 12 | }, 13 | "dependencies": { 14 | "vue": "^3.2.25", 15 | "ol": "6.12.0", 16 | "ol-plot-vue": "workspace:*" 17 | }, 18 | "devDependencies": { 19 | "vite": "^4.4.7", 20 | "@vitejs/plugin-vue": "^4.1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/vue2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "v2", 3 | "scripts": { 4 | "dev": "npx vue-demi-switch 2 && vite", 5 | "build": "vite build", 6 | "postbuild": "node index.js" 7 | }, 8 | "dependencies": { 9 | "@vue/composition-api": "^1.7.1", 10 | "vite": "^4.4.7", 11 | "vite-plugin-dts": "^3.4.0", 12 | "vite-plugin-vue2": "^2.0.3", 13 | "vue": "2.6.14", 14 | "vue-demi": "^0.14.1", 15 | "vue-template-compiler": "2.6.14", 16 | "fs-extra": "^11.1.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /playground/vue2/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import { createVuePlugin } from 'vite-plugin-vue2'; 3 | 4 | export default defineConfig(({ mode }) => ({ 5 | plugins: [createVuePlugin()], 6 | publicDir: 'public', 7 | // server: { 8 | // port: 8081, 9 | // }, 10 | resolve: { 11 | alias: { 12 | vue: 'vue/dist/vue.esm.js', 13 | }, 14 | }, 15 | define: { 16 | 'process.env': { 17 | NODE_ENV: mode, 18 | }, 19 | }, 20 | optimizeDeps: { 21 | exclude: ['vue-demi'], 22 | }, 23 | })); 24 | -------------------------------------------------------------------------------- /packages/ol-plot/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "baseUrl": ".", 6 | "rootDir": "src", 7 | "module": "esnext", 8 | "target": "esnext", 9 | "lib": [ 10 | "esnext", 11 | "dom" 12 | ], 13 | "paths": { 14 | "@/*": ["src/*"] 15 | }, 16 | "skipLibCheck": true, 17 | "suppressImplicitAnyIndexErrors": false 18 | }, 19 | "include": [ 20 | "src/**/*.ts", 21 | "src/**/*.json", 22 | "package.json", 23 | "vite.config.ts", 24 | "typings.d.ts" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/index.ts: -------------------------------------------------------------------------------- 1 | import plot from './plot.vue'; 2 | 3 | // 存储组件列表 4 | const components = [plot]; 5 | 6 | // 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册 7 | const install = function (app: any) { 8 | // 遍历注册全局组件 9 | components.map((component) => app.component(component.name, component)); 10 | }; 11 | 12 | export default { 13 | install, 14 | plot, 15 | }; 16 | 17 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 18 | // @ts-ignore 19 | if (typeof window !== 'undefined' && window.Vue) { 20 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment 21 | // @ts-ignore 22 | window.Vue.use(plot); 23 | } 24 | -------------------------------------------------------------------------------- /playground/vue2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue2", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "vite --host", 6 | "build": "vite build", 7 | "build:lib": "vue-demi-switch 2 && vite build --config vite.lib.ts" 8 | }, 9 | "dependenciesMeta": { 10 | "ol-plot-vue": { 11 | "injected": true 12 | } 13 | }, 14 | "dependencies": { 15 | "@vue/composition-api": "^1.7.1", 16 | "vue": "2.6.14", 17 | "vue-demi": "^0.14.0", 18 | "vue-template-compiler": "2.6.14", 19 | "ol": "^7.3.0", 20 | "ol-plot-vue": "workspace:*" 21 | }, 22 | "devDependencies": { 23 | "vite": "^4.4.7", 24 | "vite-plugin-vue2": "^2.0.3" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.1.2 (2018.01.09) 2 | 3 | * 完善标绘要素,支持JSON序列化和反序列化,支持恢复要素编辑,支持样式保存和还原。 4 | * 完善部分使用文档。 5 | 6 | ## 2.1.1 (2018.01.07) 7 | 8 | * 修改为rollup打包方式,减少一半体积。 9 | * 修复一些bug 10 | 11 | ## 2.1.1 (2017.09.13) 12 | 13 | * 新增三个旗面标绘算法,修复单箭头,集结地等标绘报错问题 14 | * 修复样式处理,新增标绘GeoJSON恢复处理算法(恢复后禁止编辑) 15 | 16 | ## 2.1.0 (2017.09.13) 17 | 18 | * 添加文本标绘,添加矢量要素获取为GeoJSON 19 | * 优化标绘算法,处理相关bug 20 | 21 | ## 2.0.0 (2017.08.20) 22 | 23 | * 从HMap中提取标绘插件,独立项目,直接兼容到openlayers3和4. 24 | * 优化部分算法和事件处理,完善相关文档说明。(借鉴了部分超图开源符号标绘库) 25 | 26 | ## 1.0.1 (2017.08.17) 27 | 28 | * 找回丢失仓库 29 | * 重构项目,去除goog依赖,避免和openlayers类库冲突,去除不必要文件依赖,格式化相关代码 30 | * 修改打包方式,修改gulp配置,增加umd打包。发布到npm。 31 | 32 | ## 1.0.0 (2016.11.26) 33 | 34 | * 迁移项目,增加自定义圆标绘方法 35 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Arrow/AssaultDirection.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/24. 3 | * @desc 粗单直箭头 4 | * @Inherits FineArrow 5 | */ 6 | import { PlotTypes } from '@/utils/PlotTypes'; 7 | import FineArrow from './FineArrow'; 8 | 9 | class AssaultDirection extends FineArrow { 10 | constructor(coordinates, points, params) { 11 | super(coordinates, points, params); 12 | this.tailWidthFactor = 0.2; 13 | this.neckWidthFactor = 0.25; 14 | this.headWidthFactor = 0.3; 15 | this.type = PlotTypes.ASSAULT_DIRECTION; 16 | this.headAngle = Math.PI / 4; 17 | this.neckAngle = Math.PI * 0.17741; 18 | if (points && points.length > 0) { 19 | this.setPoints(points); 20 | } else if (coordinates && coordinates.length > 0) { 21 | this.setCoordinates(coordinates); 22 | } 23 | this.set('params', params); 24 | } 25 | } 26 | 27 | export default AssaultDirection; 28 | -------------------------------------------------------------------------------- /packages/ol-plot/src/index.ts: -------------------------------------------------------------------------------- 1 | import './less/index.less'; 2 | import { Observable } from 'ol'; 3 | import PlotDraw from './core/PlotDraw'; 4 | import PlotEdit from './core/PlotEdit'; 5 | import PlotUtils from './core/PlotUtils'; 6 | import { PlotTypes } from './utils/PlotTypes'; 7 | import * as Geometry from './geometry'; 8 | 9 | import StyleFactory from './utils/factory'; 10 | 11 | class olPlot extends Observable { 12 | static PlotTypes = PlotTypes; 13 | 14 | static Geometry = Geometry; 15 | 16 | static StyleFactory = StyleFactory; 17 | 18 | public plotDraw: PlotDraw; 19 | 20 | public plotEdit: PlotEdit; 21 | 22 | public plotUtils: PlotUtils; 23 | 24 | constructor(map, options) { 25 | super(); 26 | this.plotDraw = new PlotDraw(map, options, this); 27 | this.plotEdit = new PlotEdit(map); 28 | this.plotUtils = new PlotUtils(map, options, this); 29 | } 30 | } 31 | 32 | export default olPlot; 33 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "forceConsistentCasingInFileNames": true, 5 | "allowJs": true, 6 | "sourceMap": true, 7 | "esModuleInterop": true, 8 | "declarationMap": true, 9 | "experimentalDecorators": true, 10 | "strictNullChecks": true, 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true, 13 | "noUnusedLocals": true, 14 | "moduleResolution": "node", 15 | "module": "esnext", 16 | "target": "esnext", 17 | "jsx": "preserve", 18 | "lib": [ 19 | "esnext", 20 | "dom" 21 | ], 22 | "types": ["node", "vitest"], 23 | "allowSyntheticDefaultImports": true 24 | }, 25 | "include": [ 26 | "playground/*/src/**/*.ts", 27 | "playground/*/vite.config.ts", 28 | "packages/*/src/**/*.ts", 29 | "packages/*/vite.config.ts", 30 | "packages/*/typings.d.ts", 31 | "packages/*/__tests__/**/*.ts" 32 | ], 33 | "exclude": [ 34 | "**/node_modules/**", 35 | "**/dist/**" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # ol-plot贡献指南 2 | 3 | ## 版本 4 | 5 | | 主版本号 | 次版本号 | 修订号 | 6 | | ------------- | -------------------------- | -------------------- | 7 | | 破坏性变更 | 功能添加,无破坏性变更 | Bug修正,无破坏性变更 | 8 | 9 | ### 版本号递增规则如下: 10 | 11 | - 主版本号:当你做了不兼容的 API 修改, 12 | - 次版本号:当你做了向下兼容的功能性新增, 13 | - 修订号:当你做了向下兼容的问题修正. 14 | 15 | ## Issue 规范 16 | 17 | - issue 仅用于提交 Bug 或 Feature 以及设计相关的内容,其它内容可能会被直接关闭。 18 | 19 | - 在提交 issue 之前,请搜索相关内容是否已被提出。 20 | 21 | - 请说明使用的ol-plot的版本号,并提供操作系统和浏览器信息。推荐使用 [JSFiddle](https://jsfiddle.net/) 或者[codepen](https://codepen.io/)生成在线 demo,这能够更直观地重现问题。 22 | 23 | ## Pull Request 规范 24 | - 请先 fork 一份到自己的项目下,不要直接在仓库下建分支。 25 | 26 | - commit 信息要以# [记录] + messages 27 | 28 | - **不要提交** `dist` 里面打包的文件。 29 | 30 | - 执行 `npm run dev && npm run build` 后可以正确打包文件。 31 | 32 | - 提交 PR 前请 rebase,确保 commit 记录的整洁。 33 | 34 | - 确保 PR 是提交到 `dev` 分支,而不是 `master` 分支。 35 | 36 | - 如果是修复 bug,请在 PR 中给出描述信息。 37 | 38 | 39 | ## 开发环境搭建 40 | 41 | 首先你需要 Node.js 16+ 和 PNPM 7+ 42 | ```shell 43 | git clone https://github.com/sakitam-fdd/ol-plot.git 44 | pnpm i 45 | pnpm run dev 46 | pnpm run build 47 | ``` 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 sakitam-fdd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /packages/ol-plot/src/constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/22. 3 | * @desc 常用变量 4 | */ 5 | export const FITTING_COUNT = 100; 6 | export const HALF_PI = Math.PI / 2; 7 | export const ZERO_TOLERANCE = 0.0001; 8 | export const TWO_PI = Math.PI * 2; 9 | export const BASE_LAYERNAME = 'ol-plot-vector-layer'; // 矢量图层名,(唯一标识) 10 | export const BASE_HELP_CONTROL_POINT_ID = 'plot-helper-control-point-div'; // 控制点要素的基类id 11 | export const BASE_HELP_HIDDEN = 'plot-helper-hidden-div'; // 父类隐藏容器 12 | export const DEF_TEXT_STYEL = { 13 | // 默认文本框样式 14 | borderRadius: '2px', 15 | fontSize: '12px', 16 | outline: 0, 17 | overflow: 'hidden', 18 | boxSizing: 'border-box', 19 | border: '1px solid #eeeeee', 20 | fontFamily: 21 | 'Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Noto Sans CJK SC,WenQuanYi Micro Hei,Arial,sans-serif', 22 | color: '#010500', 23 | fontWeight: 400, 24 | padding: '3px', 25 | fontStretch: 'normal', 26 | lineHeight: 'normal', 27 | textAlign: 'left', 28 | marginLeft: 'auto', 29 | marginRight: 'auto', 30 | width: 'auto', 31 | height: 'auto', 32 | background: 'rgb(255, 255, 255)', 33 | fontStyle: '', 34 | fontVariant: '', 35 | }; 36 | -------------------------------------------------------------------------------- /packages/ol-plot/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ol-plot 2 | 3 | ## 4.1.10 4 | 5 | ### Patch Changes 6 | 7 | - [`dda6ab2`](https://github.com/sakitam-fdd/ol-plot/commit/dda6ab237db2293fe53f5d4195681cfd341f2b6a) Thanks [@sakitam-fdd](https://github.com/sakitam-fdd)! - fix: RectAngle fill options 8 | 9 | ## 4.1.9 10 | 11 | ### Patch Changes 12 | 13 | - [`6f4c382`](https://github.com/sakitam-fdd/ol-plot/commit/6f4c3827b1195d91d180a9cbee1c124ce45d0be2) Thanks [@sakitam-fdd](https://github.com/sakitam-fdd)! - fix bugs 14 | 15 | ## 4.1.8 16 | 17 | ### Patch Changes 18 | 19 | - 4adb920: fix: draw event 20 | 21 | ## 4.1.7 22 | 23 | ### Patch Changes 24 | 25 | - b8a8055: feat: add TextArea event (drawStart, drawEnd) 26 | 27 | ## 4.1.6 28 | 29 | ### Patch Changes 30 | 31 | - 0f8524c: fix: PlotType export and Rect draw 32 | 33 | ## 4.1.5 34 | 35 | ### Patch Changes 36 | 37 | - 8180246: fix: ci error 38 | 39 | ## 4.1.4 40 | 41 | ### Patch Changes 42 | 43 | - 68913ec: bump version 44 | 45 | ## 4.1.3 46 | 47 | ### Patch Changes 48 | 49 | - 4169a63: fix vue2 50 | 51 | ## 4.1.2 52 | 53 | ### Patch Changes 54 | 55 | - 7ff6a0f: fix pkg main field 56 | 57 | ## 4.1.1 58 | 59 | ### Patch Changes 60 | 61 | - dce5cdc: fix bugs 62 | 63 | ## 4.1.0 64 | 65 | ### Minor Changes 66 | 67 | - 21ef6f7: add new shape 68 | 69 | ## 4.0.0 70 | 71 | ### Major Changes 72 | 73 | - 9095a5b: update version 74 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "rootDir": "src", 5 | "target": "esnext", 6 | "module": "esnext", 7 | "moduleResolution": "node", 8 | "strict": true, 9 | "alwaysStrict": false, 10 | "noImplicitAny": false, 11 | "noImplicitThis": false, 12 | "strictBindCallApply": false, 13 | "strictNullChecks": false, 14 | "strictFunctionTypes": false, 15 | "strictPropertyInitialization": false, 16 | "useDefineForClassFields": true, 17 | "noUnusedLocals": false, 18 | "noUnusedParameters": false, 19 | "noImplicitReturns": false, 20 | "noFallthroughCasesInSwitch": true, 21 | "composite": true, 22 | "experimentalDecorators": true, 23 | "allowSyntheticDefaultImports": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "allowJs": true, 26 | "checkJs": false, 27 | "jsx": "preserve", 28 | "sourceMap": true, 29 | "resolveJsonModule": true, 30 | "isolatedModules": true, 31 | "esModuleInterop": true, 32 | "lib": ["esnext", "dom", "dom.iterable", "webworker"], 33 | "skipLibCheck": true, 34 | "suppressImplicitAnyIndexErrors": false, 35 | "paths": { 36 | "~/*": ["./*"], 37 | "@/*": ["src/*"] 38 | } 39 | }, 40 | "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "vite.config.*", "vitest.config.*", "./env.d.ts", "package.json"] 41 | } -------------------------------------------------------------------------------- /packages/ol-plot-vue/vue2/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "rootDir": "src", 5 | "target": "esnext", 6 | "module": "esnext", 7 | "moduleResolution": "node", 8 | "strict": true, 9 | "alwaysStrict": false, 10 | "noImplicitAny": false, 11 | "noImplicitThis": false, 12 | "strictBindCallApply": false, 13 | "strictNullChecks": false, 14 | "strictFunctionTypes": false, 15 | "strictPropertyInitialization": false, 16 | "useDefineForClassFields": true, 17 | "noUnusedLocals": false, 18 | "noUnusedParameters": false, 19 | "noImplicitReturns": false, 20 | "noFallthroughCasesInSwitch": true, 21 | "composite": true, 22 | "experimentalDecorators": true, 23 | "allowSyntheticDefaultImports": true, 24 | "forceConsistentCasingInFileNames": true, 25 | "allowJs": true, 26 | "checkJs": false, 27 | "jsx": "preserve", 28 | "sourceMap": true, 29 | "resolveJsonModule": true, 30 | "isolatedModules": true, 31 | "esModuleInterop": true, 32 | "lib": ["esnext", "dom", "dom.iterable", "webworker"], 33 | "skipLibCheck": true, 34 | "suppressImplicitAnyIndexErrors": false, 35 | "disableSizeLimit": true, 36 | "paths": { 37 | "~/*": ["./*"], 38 | "@/*": ["../src/*"] 39 | } 40 | }, 41 | "include": ["../src/**/*.ts", "../src/**/*.tsx", "../src/**/*.vue", "vite.config.*", "vitest.config.*", "../env.d.ts", "../package.json"] 42 | } 43 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/20. 3 | * @desc 标绘图形构造类 4 | */ 5 | import Point from '@/geometry/Point/Point'; 6 | import Pennant from '@/geometry/Point/Pennant'; 7 | import Polyline from './Polyline/Polyline'; 8 | import Arc from './Arc/Arc'; 9 | import Circle from './Circle/Circle'; 10 | import Curve from './Polyline/Curve'; 11 | import FreeHandLine from './Polyline/FreeHandLine'; 12 | import RectAngle from './Polygon/RectAngle'; 13 | import Ellipse from './Circle/Ellipse'; 14 | import Lune from './Polygon/Lune'; 15 | import Sector from './Polygon/Sector'; 16 | import ClosedCurve from './Polygon/ClosedCurve'; 17 | import Polygon from './Polygon/Polygon'; 18 | import FreePolygon from './Polygon/FreePolygon'; 19 | import AttackArrow from './Arrow/AttackArrow'; 20 | import DoubleArrow from './Arrow/DoubleArrow'; 21 | import StraightArrow from './Arrow/StraightArrow'; 22 | import FineArrow from './Arrow/FineArrow'; 23 | import AssaultDirection from './Arrow/AssaultDirection'; 24 | import TailedAttackArrow from './Arrow/TailedAttackArrow'; 25 | import SquadCombat from './Arrow/SquadCombat'; 26 | import TailedSquadCombat from './Arrow/TailedSquadCombat'; 27 | import GatheringPlace from './Polygon/GatheringPlace'; 28 | import RectFlag from './Flag/RectFlag'; 29 | import TriangleFlag from './Flag/TriangleFlag'; 30 | import CurveFlag from './Flag/CurveFlag'; 31 | import PlotTextBox from './Text/PlotTextBox'; 32 | import RectInclined1 from './Polygon/Rectinclined1'; 33 | import RectInclined2 from './Polygon/Rectinclined2'; 34 | 35 | export { 36 | Point, 37 | Pennant, 38 | Polyline, 39 | Arc, 40 | Circle, 41 | Curve, 42 | FreeHandLine, 43 | RectAngle, 44 | Ellipse, 45 | Lune, 46 | Sector, 47 | ClosedCurve, 48 | Polygon, 49 | FreePolygon, 50 | AttackArrow, 51 | DoubleArrow, 52 | StraightArrow, 53 | FineArrow, 54 | AssaultDirection, 55 | TailedAttackArrow, 56 | SquadCombat, 57 | TailedSquadCombat, 58 | GatheringPlace, 59 | RectFlag, 60 | TriangleFlag, 61 | CurveFlag, 62 | PlotTextBox, 63 | RectInclined1, 64 | RectInclined2, 65 | }; 66 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | 3 | import { defineConfig } from 'vite'; 4 | import type { UserConfigExport } from 'vite'; 5 | import vue from '@vitejs/plugin-vue'; 6 | import dts from 'vite-plugin-dts'; 7 | 8 | const name = 'ol-plot-vue'; 9 | export default defineConfig((env) => { 10 | const defaultConfig: UserConfigExport = { 11 | plugins: [ 12 | vue(), 13 | dts({ 14 | // outputDir: 'types', 15 | rollupTypes: true, 16 | staticImport: true, 17 | insertTypesEntry: true, 18 | cleanVueFileName: true, 19 | }), 20 | ], 21 | build: { 22 | cssCodeSplit: false, 23 | minify: env.mode === 'minify' ? 'esbuild' : false, 24 | lib: { 25 | entry: resolve(__dirname, 'src/index.ts'), 26 | name: 'VOlPlot', 27 | formats: ['es', 'cjs', 'umd'], 28 | fileName: (format) => { 29 | if (env.mode === 'minify') { 30 | return format === 'umd' ? `${name}.min.js` : `${name}.${format}.min.js`; 31 | } 32 | return format === 'umd' ? `${name}.js` : `${name}.${format}.js`; 33 | }, 34 | }, 35 | rollupOptions: { 36 | external: (id) => /^ol/.test(id) || id === 'vue' || id === 'vue-demi', 37 | output: { 38 | globals: { 39 | vue: 'Vue', 40 | 'vue-demi': 'VueDemi', 41 | ol: 'ol', 42 | 'ol/style': 'ol.style', 43 | 'ol/layer': 'ol.layer', 44 | 'ol/source': 'ol.source', 45 | 'ol/geom': 'ol.geom', 46 | 'ol/geom/Polygon': 'ol.geom.Polygon', 47 | 'ol/color': 'ol.color', 48 | 'ol/extent': 'ol.extent', 49 | 'ol/events/Event': 'ol.events.Event', 50 | 'ol/interaction/Draw': 'ol.interaction.Draw', 51 | 'ol/interaction/DragPan': 'ol.interaction.DragPan', 52 | 'ol/interaction/DoubleClickZoom': 'ol.interaction.DoubleClickZoom', 53 | }, 54 | }, 55 | }, 56 | }, 57 | optimizeDeps: { 58 | exclude: ['vue-demi'], 59 | }, 60 | test: { 61 | environment: 'happy-dom', 62 | }, 63 | }; 64 | return defaultConfig; 65 | }); 66 | -------------------------------------------------------------------------------- /playground/vue3/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 44 | 45 | 91 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/vue2/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | 3 | import { defineConfig } from 'vite'; 4 | import type { UserConfigExport } from 'vite'; 5 | import { createVuePlugin } from 'vite-plugin-vue2'; 6 | import dts from 'vite-plugin-dts'; 7 | 8 | const name = 'ol-plot-vue'; 9 | 10 | export default defineConfig((env) => { 11 | const defaultConfig: UserConfigExport = { 12 | plugins: [ 13 | createVuePlugin(), 14 | dts({ 15 | // outputDir: 'types', 16 | entryRoot: resolve(__dirname, '..'), 17 | rollupTypes: true, 18 | staticImport: true, 19 | insertTypesEntry: true, 20 | cleanVueFileName: true, 21 | }), 22 | ], 23 | build: { 24 | cssCodeSplit: false, 25 | minify: env.mode === 'minify' ? 'esbuild' : false, 26 | lib: { 27 | entry: resolve(__dirname, '../src/index.ts'), 28 | name: 'VOlPlot', 29 | formats: ['es', 'cjs', 'umd'], 30 | fileName: (format) => { 31 | if (env.mode === 'minify') { 32 | return format === 'umd' ? `${name}.min.js` : `${name}.${format}.min.js`; 33 | } 34 | return format === 'umd' ? `${name}.js` : `${name}.${format}.js`; 35 | }, 36 | }, 37 | rollupOptions: { 38 | external: (id) => /^ol/.test(id) || id === 'vue' || id === 'vue-demi', 39 | output: { 40 | globals: { 41 | vue: 'Vue', 42 | 'vue-demi': 'VueDemi', 43 | ol: 'ol', 44 | 'ol/style': 'ol.style', 45 | 'ol/layer': 'ol.layer', 46 | 'ol/source': 'ol.source', 47 | 'ol/geom': 'ol.geom', 48 | 'ol/geom/Polygon': 'ol.geom.Polygon', 49 | 'ol/color': 'ol.color', 50 | 'ol/extent': 'ol.extent', 51 | 'ol/events/Event': 'ol.events.Event', 52 | 'ol/interaction/Draw': 'ol.interaction.Draw', 53 | 'ol/interaction/DragPan': 'ol.interaction.DragPan', 54 | 'ol/interaction/DoubleClickZoom': 'ol.interaction.DoubleClickZoom', 55 | }, 56 | dir: 'dist', 57 | }, 58 | }, 59 | }, 60 | optimizeDeps: { 61 | exclude: ['vue-demi'], 62 | }, 63 | }; 64 | return defaultConfig; 65 | }); 66 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/scripts/postinstall.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const spawn = require('cross-spawn'); 5 | const pkg = require('../package.json'); 6 | 7 | function loadModule(name) { 8 | try { 9 | return require(name); 10 | } catch (e) { 11 | return undefined; 12 | } 13 | } 14 | 15 | const Vue = loadModule('vue'); 16 | 17 | const dir = path.resolve(__dirname, '..', 'dist'); 18 | 19 | function copy(name, targetName, version) { 20 | const src = path.join(dir, `v${version}`, name); 21 | const dest = path.join(dir, targetName); 22 | const content = fs.readFileSync(src, 'utf-8'); 23 | try { 24 | fs.unlinkSync(dest); 25 | } catch (error) {} 26 | fs.writeFileSync(dest, content, 'utf-8'); 27 | } 28 | 29 | async function switchVersion(version) { 30 | copy('ol-plot-vue.cjs.js', 'ol-plot-vue.cjs.js', version); 31 | copy('ol-plot-vue.es.js', 'ol-plot-vue.es.js', version); 32 | copy('ol-plot-vue.js', 'ol-plot-vue.js', version); 33 | if (version === 2) { 34 | copy('ol-plot-vue.es.d.ts', 'index.d.ts', version); 35 | } else { 36 | copy('index.d.ts', 'index.d.ts', version); 37 | } 38 | 39 | copy('style.css', 'style.css', version); 40 | } 41 | 42 | async function checkVersionExists(version) { 43 | const d = path.join(dir, `v${version}`); 44 | const state = fs.existsSync(d); 45 | 46 | if (state) { 47 | // await spawn.sync('pnpm', [`build:vue${version}`], { stdio: 'inherit' }); 48 | await switchVersion(version); 49 | } 50 | } 51 | 52 | async function run() { 53 | console.log(`[ol-plot-vue] Vue version ${Vue.version}`); 54 | if (!Vue || typeof Vue.version !== 'string') { 55 | console.warn('[ol-plot-vue] Vue is not found. Please run "pnpm install vue" to install.'); 56 | } else if (Vue.version.startsWith('2.')) { 57 | console.log('[ol-plot-vue] Switch main field for Vue 2'); 58 | await checkVersionExists(2); 59 | // await switchVersion(2); 60 | } else { 61 | console.log('[ol-plot-vue] Switch main field for Vue 3'); 62 | await checkVersionExists(3); 63 | // await switchVersion(3); 64 | } 65 | 66 | fs.writeFileSync(path.resolve(__dirname, '../package.json'), JSON.stringify(pkg, null, 2), { 67 | encoding: 'utf-8', 68 | }); 69 | } 70 | 71 | run().then(() => { 72 | process.exit(0); 73 | }); 74 | -------------------------------------------------------------------------------- /playground/vue2/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 51 | 52 | 98 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ol-plot-vue 2 | 3 | ## 1.1.12 4 | 5 | ### Patch Changes 6 | 7 | - [`5a3fcec`](https://github.com/sakitam-fdd/ol-plot/commit/5a3fcec886eb5cd30012c3ebd36c0a9614a84dce) Thanks [@sakitam-fdd](https://github.com/sakitam-fdd)! - fix plot activeToolPanel 8 | 9 | ## 1.1.11 10 | 11 | ### Patch Changes 12 | 13 | - Updated dependencies [[`dda6ab2`](https://github.com/sakitam-fdd/ol-plot/commit/dda6ab237db2293fe53f5d4195681cfd341f2b6a)]: 14 | - ol-plot@4.1.10 15 | 16 | ## 1.1.10 17 | 18 | ### Patch Changes 19 | 20 | - [`6f4c382`](https://github.com/sakitam-fdd/ol-plot/commit/6f4c3827b1195d91d180a9cbee1c124ce45d0be2) Thanks [@sakitam-fdd](https://github.com/sakitam-fdd)! - fix bugs 21 | 22 | - Updated dependencies [[`6f4c382`](https://github.com/sakitam-fdd/ol-plot/commit/6f4c3827b1195d91d180a9cbee1c124ce45d0be2)]: 23 | - ol-plot@4.1.9 24 | 25 | ## 1.1.9 26 | 27 | ### Patch Changes 28 | 29 | - Updated dependencies [4adb920] 30 | - ol-plot@4.1.8 31 | 32 | ## 1.1.8 33 | 34 | ### Patch Changes 35 | 36 | - Updated dependencies [b8a8055] 37 | - ol-plot@4.1.7 38 | 39 | ## 1.1.7 40 | 41 | ### Patch Changes 42 | 43 | - Updated dependencies [0f8524c] 44 | - ol-plot@4.1.6 45 | 46 | ## 1.1.6 47 | 48 | ### Patch Changes 49 | 50 | - 8180246: fix: ci error 51 | - Updated dependencies [8180246] 52 | - ol-plot@4.1.5 53 | 54 | ## 1.1.5 55 | 56 | ### Patch Changes 57 | 58 | - Updated dependencies [68913ec] 59 | - ol-plot@4.1.4 60 | 61 | ## 1.1.4 62 | 63 | ### Patch Changes 64 | 65 | - 0f1accd: fix version 66 | 67 | ## 1.1.3 68 | 69 | ### Patch Changes 70 | 71 | - 4169a63: fix vue2 72 | - Updated dependencies [4169a63] 73 | - ol-plot@4.1.3 74 | 75 | ## 1.1.2 76 | 77 | ### Patch Changes 78 | 79 | - 7ff6a0f: fix pkg main field 80 | - Updated dependencies [7ff6a0f] 81 | - ol-plot@4.1.2 82 | 83 | ## 1.1.1 84 | 85 | ### Patch Changes 86 | 87 | - dce5cdc: fix bugs 88 | - Updated dependencies [dce5cdc] 89 | - ol-plot@4.1.1 90 | 91 | ## 1.1.0 92 | 93 | ### Minor Changes 94 | 95 | - 21ef6f7: add new shape 96 | 97 | ### Patch Changes 98 | 99 | - Updated dependencies [21ef6f7] 100 | - ol-plot@4.1.0 101 | 102 | ## 1.0.0 103 | 104 | ### Major Changes 105 | 106 | - 9095a5b: update version 107 | 108 | ### Patch Changes 109 | 110 | - Updated dependencies [9095a5b] 111 | - ol-plot@4.0.0 112 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polyline/Polyline.ts: -------------------------------------------------------------------------------- 1 | import { Map } from 'ol'; 2 | import { LineString } from 'ol/geom'; 3 | 4 | import { PlotTypes } from '@/utils/PlotTypes'; 5 | import type { Point } from '@/utils/utils'; 6 | 7 | class Polyline extends LineString { 8 | type: PlotTypes; 9 | 10 | fixPointCount: number; 11 | 12 | map: any; 13 | 14 | points: Point[]; 15 | 16 | freehand: boolean; 17 | 18 | constructor(coordinates, points, params) { 19 | super([]); 20 | this.type = PlotTypes.POLYLINE; 21 | this.freehand = false; 22 | this.set('params', params); 23 | if (points && points.length > 0) { 24 | this.setPoints(points); 25 | } else if (coordinates && coordinates.length > 0) { 26 | this.setCoordinates(coordinates); 27 | } 28 | } 29 | 30 | /** 31 | * 获取标绘类型 32 | * @returns {*} 33 | */ 34 | getPlotType() { 35 | return this.type; 36 | } 37 | 38 | /** 39 | * 执行动作 40 | */ 41 | generate() { 42 | this.setCoordinates(this.points); 43 | } 44 | 45 | /** 46 | * 设置地图对象 47 | * @param map 48 | */ 49 | setMap(map) { 50 | if (map && map instanceof Map) { 51 | this.map = map; 52 | } else { 53 | throw new Error('传入的不是地图对象!'); 54 | } 55 | } 56 | 57 | /** 58 | * 获取当前地图对象 59 | * @returns {ol.Map|*} 60 | */ 61 | getMap() { 62 | return this.map; 63 | } 64 | 65 | /** 66 | * 判断是否是Plot 67 | * @returns {boolean} 68 | */ 69 | isPlot() { 70 | return true; 71 | } 72 | 73 | /** 74 | * 设置坐标点 75 | * @param value 76 | */ 77 | setPoints(value) { 78 | this.points = !value ? [] : value; 79 | if (this.points.length >= 1) { 80 | this.generate(); 81 | } 82 | } 83 | 84 | /** 85 | * 获取坐标点 86 | * @returns {Array.} 87 | */ 88 | getPoints() { 89 | return this.points.slice(0); 90 | } 91 | 92 | /** 93 | * 获取点数量 94 | * @returns {Number} 95 | */ 96 | getPointCount() { 97 | return this.points.length; 98 | } 99 | 100 | /** 101 | * 更新当前坐标 102 | * @param point 103 | * @param index 104 | */ 105 | updatePoint(point, index) { 106 | if (index >= 0 && index < this.points.length) { 107 | this.points[index] = point; 108 | this.generate(); 109 | } 110 | } 111 | 112 | /** 113 | * 更新最后一个坐标 114 | * @param point 115 | */ 116 | updateLastPoint(point) { 117 | this.updatePoint(point, this.points.length - 1); 118 | } 119 | 120 | /** 121 | * 结束绘制 122 | */ 123 | finishDrawing() {} 124 | } 125 | 126 | export default Polyline; 127 | -------------------------------------------------------------------------------- /packages/ol-plot/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ol-plot", 3 | "version": "4.1.10", 4 | "description": "ol plot", 5 | "keywords": [ 6 | "javascript", 7 | "webgis", 8 | "canvas", 9 | "ol", 10 | "openlayers", 11 | "map", 12 | "plot", 13 | "map", 14 | "vis", 15 | "gis" 16 | ], 17 | "author": "sakitam-fdd ", 18 | "license": "MIT", 19 | "main": "dist/ol-plot.es.js", 20 | "module": "dist/ol-plot.es.js", 21 | "unpkg": "dist/ol-plot.js", 22 | "commonjs": "dist/ol-plot.cjs.js", 23 | "style": "dist/ol-plot.css", 24 | "types": "dist/index.d.ts", 25 | "namespace": "olPlot", 26 | "files": [ 27 | "dist", 28 | "LICENSE", 29 | "README.md", 30 | "package.json" 31 | ], 32 | "exports": { 33 | ".": { 34 | "types": "./dist/index.d.ts", 35 | "node": { 36 | "import": { 37 | "production": "./dist/ol-plot.es.js", 38 | "development": "./dist/ol-plot.es.js", 39 | "default": "./dist/ol-plot.es.js" 40 | }, 41 | "require": { 42 | "production": "./dist/ol-plot.cjs.js", 43 | "development": "./dist/ol-plot.cjs.js", 44 | "default": "./dist/ol-plot.cjs.js" 45 | } 46 | }, 47 | "import": "./dist/ol-plot.es.js", 48 | "require": "./dist/ol-plot.cjs.js" 49 | }, 50 | "./dist/*.css": { 51 | "import": "./dist/*.css", 52 | "require": "./dist/*.css" 53 | }, 54 | "./package.json": "./package.json" 55 | }, 56 | "private": false, 57 | "sideEffects": [ 58 | "*.css" 59 | ], 60 | "repository": { 61 | "type": "git", 62 | "url": "git+https://github.com/sakitam-fdd/ol-plot.git", 63 | "directory": "packages/ol-plot" 64 | }, 65 | "scripts": { 66 | "clean": "rimraf dist", 67 | "dev": "vite build --mode watch", 68 | "build": "vite build --mode production", 69 | "build:minify": "vite build --mode minify", 70 | "lint": "eslint --ext .js,.ts,.tsx src", 71 | "prettier": "prettier --parser=typescript --write **/*.{js,ts,md}", 72 | "test": "pnpm run build && pnpm run test-only", 73 | "test-only": "vitest run", 74 | "coverage": "vitest run --coverage" 75 | }, 76 | "bugs": { 77 | "url": "https://github.com/sakitam-fdd/ol-plot/issues" 78 | }, 79 | "homepage": "https://github.com/sakitam-fdd/ol-plot#readme", 80 | "peerDependencies": { 81 | "ol": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" 82 | }, 83 | "dependencies": { 84 | "autosize": "^6.0.1" 85 | }, 86 | "devDependencies": { 87 | "ol": "^6.15.0", 88 | "vite": "^4.4.7" 89 | }, 90 | "publishConfig": { 91 | "access": "public" 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "packages/*" 5 | ], 6 | "scripts": { 7 | "preinstall": "npx only-allow pnpm", 8 | "dev": "pnpm run -r dev", 9 | "build": "pnpm run -r build", 10 | "build:minify": "pnpm run -r build:minify", 11 | "build:vue2": "cd packages/ol-plot-vue/vue2 && yarn && yarn build && cd ../../../", 12 | "copy-file": "cd packages/ol-plot-vue && pnpm postbuild && cd ../../", 13 | "docs": "vitepress dev docs", 14 | "docs:api": "pnpm run -r api --filter docs", 15 | "docs:build": "vitepress build docs", 16 | "docs:serve": "vitepress serve docs", 17 | "version": "changeset version", 18 | "changeset": "changeset", 19 | "release": "pnpm --filter \"./packages/**\" build && pnpm --filter \"./packages/**\" build:minify && pnpm build:vue2 && pnpm copy-file && pnpm changeset publish", 20 | "lint": "eslint packages/*/src/**/* --ext .js,.ts,.tsx", 21 | "prettier": "prettier --parser=typescript --write **/*.{js,ts,md}", 22 | "test": "pnpm run -r test", 23 | "test-only": "pnpm run -r test-only", 24 | "coverage": "pnpm run -r coverage" 25 | }, 26 | "devDependencies": { 27 | "@aurorafe/eslint-config-base": "^1.0.1", 28 | "@aurorafe/eslint-config-ts": "^1.0.1", 29 | "@aurorafe/eslint-config-vue": "^1.0.1", 30 | "@changesets/changelog-github": "^0.4.8", 31 | "@changesets/cli": "^2.25.0", 32 | "@types/node": "^18.6.4", 33 | "@typescript-eslint/eslint-plugin": "^5.40.1", 34 | "@typescript-eslint/parser": "^5.40.1", 35 | "@vitest/coverage-v8": "0.34.1", 36 | "canvas": "^2.10.2", 37 | "jsdom": "^20.0.3", 38 | "esbuild": "^0.15.12", 39 | "eslint": "^8.30.0", 40 | "less": "^4.1.3", 41 | "prettier": "^2.7.1", 42 | "terser": "^5.17.1", 43 | "typescript": "5.0.4", 44 | "typedoc": "^0.24.4", 45 | "typedoc-plugin-markdown": "^3.15.1", 46 | "vite": "^4.4.7", 47 | "vitest": "^0.34.1", 48 | "vitepress": "^1.0.0-beta.7", 49 | "vite-plugin-dts": "^3.4.0", 50 | "rollup-plugin-dts": "^5.3.0", 51 | "vite-plugin-eslint": "^1.8.1", 52 | "vite-plugin-externals": "^0.6.2", 53 | "wait-for-expect": "3.0.2", 54 | "lint-staged": "^13.0.3", 55 | "rimraf": "^3.0.2" 56 | }, 57 | "engines": { 58 | "node": ">=18.16.1" 59 | }, 60 | "husky": { 61 | "hooks": { 62 | "pre-commit": "pnpm run lint", 63 | "pre-push": "pnpm run test" 64 | } 65 | }, 66 | "lint-staged": { 67 | "*.js": [ 68 | "prettier --write", 69 | "git add" 70 | ], 71 | "*.ts?(x)": [ 72 | "prettier --parser=typescript --write", 73 | "git add" 74 | ] 75 | }, 76 | "license": "MIT" 77 | } 78 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Arrow/SquadCombat.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/26. 3 | * @desc 分队战斗行动 4 | * @Inherits AttackArrow 5 | */ 6 | 7 | import { PlotTypes } from '@/utils/PlotTypes'; 8 | import AttackArrow from './AttackArrow'; 9 | import * as PlotUtils from '../../utils/utils'; 10 | import * as Constants from '../../constants'; 11 | 12 | class SquadCombat extends AttackArrow { 13 | constructor(coordinates, points, params) { 14 | super(coordinates, points, params); 15 | this.type = PlotTypes.SQUAD_COMBAT; 16 | this.headHeightFactor = 0.18; 17 | this.headWidthFactor = 0.3; 18 | this.neckHeightFactor = 0.85; 19 | this.neckWidthFactor = 0.15; 20 | this.tailWidthFactor = 0.1; 21 | this.set('params', params); 22 | if (points && points.length > 0) { 23 | this.setPoints(points); 24 | } else if (coordinates && coordinates.length > 0) { 25 | this.setCoordinates(coordinates); 26 | } 27 | } 28 | 29 | /** 30 | * 执行动作 31 | */ 32 | generate() { 33 | try { 34 | const count = this.getPointCount(); 35 | if (count < 2) { 36 | return false; 37 | // eslint-disable-next-line no-else-return 38 | } else { 39 | const pnts = this.getPoints(); 40 | const tailPnts = this.getTailPoints(pnts); 41 | const headPnts = this.getArrowHeadPoints(pnts, tailPnts[0], tailPnts[1]); 42 | if (headPnts && headPnts.length > 4) { 43 | const neckLeft = headPnts[0]; 44 | const neckRight = headPnts[4]; 45 | const bodyPnts = this.getArrowBodyPoints(pnts, neckLeft, neckRight, this.tailWidthFactor); 46 | // eslint-disable-next-line @typescript-eslint/no-shadow 47 | const count = bodyPnts.length; 48 | let leftPnts = [tailPnts[0]].concat(bodyPnts.slice(0, count / 2)); 49 | leftPnts.push(neckLeft); 50 | let rightPnts = [tailPnts[1]].concat(bodyPnts.slice(count / 2, count)); 51 | rightPnts.push(neckRight); 52 | leftPnts = PlotUtils.getQBSplinePoints(leftPnts); 53 | rightPnts = PlotUtils.getQBSplinePoints(rightPnts); 54 | this.setCoordinates([leftPnts.concat(headPnts, rightPnts.reverse())]); 55 | } 56 | } 57 | } catch (e) { 58 | console.log(e); 59 | } 60 | } 61 | 62 | getTailPoints(points) { 63 | const allLen = PlotUtils.getBaseLength(points); 64 | const tailWidth = allLen * this.tailWidthFactor; 65 | const tailLeft = PlotUtils.getThirdPoint(points[1], points[0], Constants.HALF_PI, tailWidth, false); 66 | const tailRight = PlotUtils.getThirdPoint(points[1], points[0], Constants.HALF_PI, tailWidth, true); 67 | return [tailLeft, tailRight]; 68 | } 69 | } 70 | 71 | export default SquadCombat; 72 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polygon/FreePolygon.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/24. 3 | * @desc 自由面 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import type { Point } from '@/utils/utils'; 10 | 11 | class FreePolygon extends Polygon { 12 | type: PlotTypes; 13 | 14 | fixPointCount: WithUndef; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | constructor(coordinates, points, params) { 23 | super([]); 24 | this.type = PlotTypes.FREE_POLYGON; 25 | this.freehand = true; 26 | this.set('params', params); 27 | if (points && points.length > 0) { 28 | this.setPoints(points); 29 | } else if (coordinates && coordinates.length > 0) { 30 | this.setCoordinates(coordinates); 31 | } 32 | } 33 | 34 | /** 35 | * 获取标绘类型 36 | * @returns {*} 37 | */ 38 | getPlotType() { 39 | return this.type; 40 | } 41 | 42 | /** 43 | * 执行动作 44 | */ 45 | generate() { 46 | this.setCoordinates([this.points]); 47 | } 48 | 49 | /** 50 | * 设置地图对象 51 | * @param map 52 | */ 53 | setMap(map) { 54 | if (map && map instanceof Map) { 55 | this.map = map; 56 | } else { 57 | throw new Error('传入的不是地图对象!'); 58 | } 59 | } 60 | 61 | /** 62 | * 获取当前地图对象 63 | * @returns {Map|*} 64 | */ 65 | getMap() { 66 | return this.map; 67 | } 68 | 69 | /** 70 | * 判断是否是Plot 71 | * @returns {boolean} 72 | */ 73 | isPlot() { 74 | return true; 75 | } 76 | 77 | /** 78 | * 设置坐标点 79 | * @param value 80 | */ 81 | setPoints(value) { 82 | this.points = !value ? [] : value; 83 | if (this.points.length >= 1) { 84 | this.generate(); 85 | } 86 | } 87 | 88 | /** 89 | * 获取坐标点 90 | * @returns {Array.} 91 | */ 92 | getPoints() { 93 | return this.points.slice(0); 94 | } 95 | 96 | /** 97 | * 获取点数量 98 | * @returns {Number} 99 | */ 100 | getPointCount() { 101 | return this.points.length; 102 | } 103 | 104 | /** 105 | * 更新当前坐标 106 | * @param point 107 | * @param index 108 | */ 109 | updatePoint(point, index) { 110 | if (index >= 0 && index < this.points.length) { 111 | this.points[index] = point; 112 | this.generate(); 113 | } 114 | } 115 | 116 | /** 117 | * 更新最后一个坐标 118 | * @param point 119 | */ 120 | updateLastPoint(point) { 121 | this.updatePoint(point, this.points.length - 1); 122 | } 123 | 124 | /** 125 | * 结束绘制 126 | */ 127 | finishDrawing() {} 128 | } 129 | 130 | export default FreePolygon; 131 | -------------------------------------------------------------------------------- /playground/single/src/index.ts: -------------------------------------------------------------------------------- 1 | import 'ol/ol.css'; 2 | import 'ol-plot/dist/ol-plot.css'; 3 | import { Map, View } from 'ol'; 4 | import { Tile } from 'ol/layer'; 5 | import { OSM } from 'ol/source'; 6 | 7 | import Plot from 'ol-plot'; 8 | 9 | const map = new Map({ 10 | layers: [ 11 | new Tile({ 12 | source: new OSM({ 13 | url: 'https://a.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', 14 | }), 15 | }), 16 | ], 17 | view: new View({ 18 | // center: [108.93, 34.27], 19 | center: [12095486.34146684, 4085090.6140265367], 20 | projection: 'EPSG:3857', 21 | zoom: 5, 22 | }), 23 | target: 'map', 24 | }); 25 | 26 | /* eslint-disable-next-line */ 27 | const plot = new Plot(map, { 28 | zoomToExtent: true, 29 | }); 30 | 31 | map.on('click', (event) => { 32 | // eslint-disable-next-line @typescript-eslint/no-shadow 33 | const feature = map.forEachFeatureAtPixel(event.pixel, (feature) => feature); 34 | if (feature && feature.get('isPlot') && !plot.plotDraw.isDrawing()) { 35 | plot.plotEdit.activate(feature); 36 | } else { 37 | plot.plotEdit.deactivate(); 38 | } 39 | }); 40 | 41 | // 绘制结束后,添加到FeatureOverlay显示。 42 | function onDrawEnd(event) { 43 | console.log(event); 44 | const feature = event.feature; 45 | // 开始编辑 46 | plot.plotEdit.activate(feature); 47 | } 48 | 49 | let isActive = true; 50 | 51 | // 你的外部图层事件 52 | map.on('click', (e) => { 53 | if (isActive) return; 54 | console.log('click'); 55 | // 你的逻辑 56 | }); 57 | 58 | plot.plotDraw.on('drawStart', (e) => { 59 | isActive = true; 60 | }); 61 | 62 | plot.plotDraw.on('drawEnd', (e) => { 63 | console.log('drawEnd'); 64 | isActive = false; 65 | }); 66 | 67 | plot.plotDraw.on('drawStart', (e) => { 68 | console.log(e); 69 | }); 70 | plot.plotDraw.on('drawEnd', onDrawEnd); 71 | 72 | plot.plotEdit.on('activePlotChange', (e) => { 73 | console.log(e); 74 | }); 75 | plot.plotEdit.on('deactivatePlot', (e) => { 76 | console.log(e); 77 | }); 78 | 79 | plot.on('activeTextArea', (event) => { 80 | const style = event.overlay.getStyle(); 81 | console.log(style); 82 | }); 83 | plot.on('deactivateTextArea', (event) => { 84 | const style = event.overlay.getStyle(); 85 | console.log(style); 86 | }); 87 | 88 | // 指定标绘类型,开始绘制。 89 | function activate(type) { 90 | plot.plotEdit.deactivate(); 91 | plot.plotDraw.activate(type); 92 | } 93 | 94 | function getFeatures() { 95 | const features = plot.plotUtils.getFeatures(); 96 | plot.plotUtils.removeAllFeatures(); 97 | plot.plotEdit.deactivate(); 98 | plot.plotUtils.addFeatures(features); 99 | } 100 | 101 | window.plot = plot; 102 | window.activate = activate; 103 | window.getFeatures = getFeatures; 104 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polyline/FreeHandLine.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/24. 3 | * @desc 自由线 4 | * @Inherits ol.geom.LineString 5 | */ 6 | import { Map } from 'ol'; 7 | import { LineString } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import type { Point } from '@/utils/utils'; 10 | 11 | class FreeHandLine extends LineString { 12 | type: PlotTypes; 13 | 14 | fixPointCount: number; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | constructor(coordinates, points, params) { 23 | super([]); 24 | this.type = PlotTypes.FREEHANDLINE; 25 | this.freehand = true; 26 | this.set('params', params); 27 | if (points && points.length > 0) { 28 | this.setPoints(points); 29 | } else if (coordinates && coordinates.length > 0) { 30 | this.setCoordinates(coordinates); 31 | } 32 | } 33 | 34 | /** 35 | * 获取标绘类型 36 | * @returns {*} 37 | */ 38 | getPlotType() { 39 | return this.type; 40 | } 41 | 42 | /** 43 | * 执行动作 44 | */ 45 | generate() { 46 | this.setCoordinates(this.points); 47 | } 48 | 49 | /** 50 | * 设置地图对象 51 | * @param map 52 | */ 53 | setMap(map) { 54 | if (map && map instanceof Map) { 55 | this.map = map; 56 | } else { 57 | throw new Error('传入的不是地图对象!'); 58 | } 59 | } 60 | 61 | /** 62 | * 获取当前地图对象 63 | * @returns {ol.Map|*} 64 | */ 65 | getMap() { 66 | return this.map; 67 | } 68 | 69 | /** 70 | * 判断是否是Plot 71 | * @returns {boolean} 72 | */ 73 | isPlot() { 74 | return true; 75 | } 76 | 77 | /** 78 | * 设置坐标点 79 | * @param value 80 | */ 81 | setPoints(value) { 82 | this.points = !value ? [] : value; 83 | if (this.points.length >= 1) { 84 | this.generate(); 85 | } 86 | } 87 | 88 | /** 89 | * 获取坐标点 90 | * @returns {Array.} 91 | */ 92 | getPoints() { 93 | return this.points.slice(0); 94 | } 95 | 96 | /** 97 | * 获取点数量 98 | * @returns {Number} 99 | */ 100 | getPointCount() { 101 | return this.points.length; 102 | } 103 | 104 | /** 105 | * 更新当前坐标 106 | * @param point 107 | * @param index 108 | */ 109 | updatePoint(point, index) { 110 | if (index >= 0 && index < this.points.length) { 111 | this.points[index] = point; 112 | this.generate(); 113 | } 114 | } 115 | 116 | /** 117 | * 更新最后一个坐标 118 | * @param point 119 | */ 120 | updateLastPoint(point) { 121 | this.updatePoint(point, this.points.length - 1); 122 | } 123 | 124 | /** 125 | * 结束绘制 126 | */ 127 | finishDrawing() {} 128 | } 129 | 130 | export default FreeHandLine; 131 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Point/Pennant.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/15. 3 | * @desc 点要素 4 | */ 5 | import { Map } from 'ol'; 6 | import { Point } from 'ol/geom'; 7 | import { PlotTypes } from '@/utils/PlotTypes'; 8 | import type { Point as TPoint } from '@/utils/utils'; 9 | 10 | class Pennant extends Point { 11 | type: PlotTypes; 12 | 13 | fixPointCount: WithUndef; 14 | 15 | map: any; 16 | 17 | points: TPoint[]; 18 | 19 | freehand: boolean; 20 | 21 | options: any; 22 | 23 | constructor(coordinates, point, params) { 24 | super([]); 25 | this.type = PlotTypes.PENNANT; 26 | this.options = params || {}; 27 | this.freehand = false; 28 | this.fixPointCount = undefined; 29 | this.set('params', this.options); 30 | if (point && point.length > 0) { 31 | this.setPoints(point); 32 | } else if (coordinates && coordinates.length > 0) { 33 | this.setCoordinates(coordinates); 34 | } 35 | } 36 | 37 | /** 38 | * 获取标绘类型 39 | * @returns {*} 40 | */ 41 | getPlotType() { 42 | return this.type; 43 | } 44 | 45 | generate() { 46 | this.setCoordinates(this.points); 47 | } 48 | 49 | /** 50 | * 设置地图对象 51 | * @param map 52 | */ 53 | setMap(map) { 54 | if (map && map instanceof Map) { 55 | this.map = map; 56 | } else { 57 | throw new Error('传入的不是地图对象!'); 58 | } 59 | } 60 | 61 | /** 62 | * 获取当前地图对象 63 | * @returns {{}|*} 64 | */ 65 | getMap() { 66 | return this.map; 67 | } 68 | 69 | /** 70 | * 判断是否是Plot 71 | * @returns {boolean} 72 | */ 73 | isPlot() { 74 | return true; 75 | } 76 | 77 | /** 78 | * 设置坐标点 79 | * @param value 80 | */ 81 | setPoints(value) { 82 | this.points = !value ? [] : value; 83 | if (this.points.length >= 1) { 84 | this.generate(); 85 | } 86 | } 87 | 88 | /** 89 | * 获取坐标点 90 | * @returns {Array.} 91 | */ 92 | getPoints() { 93 | return this.points.slice(0); 94 | } 95 | 96 | /** 97 | * 获取点数量 98 | * @returns {Number} 99 | */ 100 | getPointCount() { 101 | return this.points.length; 102 | } 103 | 104 | /** 105 | * 更新当前坐标 106 | * @param point 107 | * @param index 108 | */ 109 | updatePoint(point, index) { 110 | if (index >= 0 && index < this.points.length) { 111 | this.points[index] = point; 112 | this.generate(); 113 | } 114 | } 115 | 116 | /** 117 | * 更新最后一个坐标 118 | * @param point 119 | */ 120 | updateLastPoint(point) { 121 | this.updatePoint(point, this.points.length - 1); 122 | } 123 | 124 | /** 125 | * 结束绘制 126 | */ 127 | finishDrawing() {} 128 | } 129 | 130 | export default Pennant; 131 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Point/Point.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/15. 3 | * @desc 点要素 4 | */ 5 | import { Map } from 'ol'; 6 | import { Point as $Point } from 'ol/geom'; 7 | import { PlotTypes } from '@/utils/PlotTypes'; 8 | import type { Point as TPoint } from '@/utils/utils'; 9 | 10 | class Point extends $Point { 11 | type: PlotTypes; 12 | 13 | fixPointCount: number; 14 | 15 | map: any; 16 | 17 | points: TPoint[]; 18 | 19 | freehand: boolean; 20 | 21 | options: any; 22 | 23 | constructor(coordinates, point, params) { 24 | super([]); 25 | this.type = PlotTypes.POINT; 26 | this.options = params || {}; 27 | this.freehand = false; 28 | this.set('params', this.options); 29 | this.fixPointCount = 1; 30 | if (point && point.length > 0) { 31 | this.setPoints(point); 32 | } else if (coordinates && coordinates.length > 0) { 33 | this.setCoordinates(coordinates); 34 | } 35 | } 36 | 37 | /** 38 | * 获取标绘类型 39 | * @returns {*} 40 | */ 41 | getPlotType() { 42 | return this.type; 43 | } 44 | 45 | generate() { 46 | const pnt = this.points[0]; 47 | this.setCoordinates(pnt as unknown as any[]); 48 | } 49 | 50 | /** 51 | * 设置地图对象 52 | * @param map 53 | */ 54 | setMap(map) { 55 | if (map && map instanceof Map) { 56 | this.map = map; 57 | } else { 58 | throw new Error('传入的不是地图对象!'); 59 | } 60 | } 61 | 62 | /** 63 | * 获取当前地图对象 64 | * @returns {{}|*} 65 | */ 66 | getMap() { 67 | return this.map; 68 | } 69 | 70 | /** 71 | * 判断是否是Plot 72 | * @returns {boolean} 73 | */ 74 | isPlot() { 75 | return true; 76 | } 77 | 78 | /** 79 | * 设置坐标点 80 | * @param value 81 | */ 82 | setPoints(value) { 83 | this.points = !value ? [] : value; 84 | if (this.points.length >= 1) { 85 | this.generate(); 86 | } 87 | } 88 | 89 | /** 90 | * 获取坐标点 91 | * @returns {Array.} 92 | */ 93 | getPoints() { 94 | return this.points.slice(0); 95 | } 96 | 97 | /** 98 | * 获取点数量 99 | * @returns {Number} 100 | */ 101 | getPointCount() { 102 | return this.points.length; 103 | } 104 | 105 | /** 106 | * 更新当前坐标 107 | * @param point 108 | * @param index 109 | */ 110 | updatePoint(point, index) { 111 | if (index >= 0 && index < this.points.length) { 112 | this.points[index] = point; 113 | this.generate(); 114 | } 115 | } 116 | 117 | /** 118 | * 更新最后一个坐标 119 | * @param point 120 | */ 121 | updateLastPoint(point) { 122 | this.updatePoint(point, this.points.length - 1); 123 | } 124 | 125 | /** 126 | * 结束绘制 127 | */ 128 | finishDrawing() {} 129 | } 130 | 131 | export default Point; 132 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polygon/Polygon.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/24. 3 | * @desc 多边形 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon as $Polygon } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import type { Point } from '@/utils/utils'; 10 | 11 | class Polygon extends $Polygon { 12 | type: PlotTypes; 13 | 14 | fixPointCount: WithUndef; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | constructor(coordinates, points, params) { 23 | super([]); 24 | this.type = PlotTypes.POLYGON; 25 | this.set('params', params); 26 | if (points && points.length > 0) { 27 | this.setPoints(points); 28 | } else if (coordinates && coordinates.length > 0) { 29 | this.setCoordinates(coordinates); 30 | } 31 | } 32 | 33 | /** 34 | * 获取标绘类型 35 | * @returns {*} 36 | */ 37 | getPlotType() { 38 | return this.type; 39 | } 40 | 41 | /** 42 | * 执行动作 43 | */ 44 | generate() { 45 | const count = this.getPointCount(); 46 | if (count < 2) { 47 | return false; 48 | } 49 | this.setCoordinates([this.points]); 50 | } 51 | 52 | /** 53 | * 设置地图对象 54 | * @param map 55 | */ 56 | setMap(map) { 57 | if (map && map instanceof Map) { 58 | this.map = map; 59 | } else { 60 | throw new Error('传入的不是地图对象!'); 61 | } 62 | } 63 | 64 | /** 65 | * 获取当前地图对象 66 | * @returns {Map|*} 67 | */ 68 | getMap() { 69 | return this.map; 70 | } 71 | 72 | /** 73 | * 判断是否是Plot 74 | * @returns {boolean} 75 | */ 76 | isPlot() { 77 | return true; 78 | } 79 | 80 | /** 81 | * 设置坐标点 82 | * @param value 83 | */ 84 | setPoints(value) { 85 | this.points = !value ? [] : value; 86 | if (this.points.length >= 1) { 87 | this.generate(); 88 | } 89 | } 90 | 91 | /** 92 | * 获取坐标点 93 | * @returns {Array.} 94 | */ 95 | getPoints() { 96 | return this.points.slice(0); 97 | } 98 | 99 | /** 100 | * 获取点数量 101 | * @returns {Number} 102 | */ 103 | getPointCount() { 104 | return this.points.length; 105 | } 106 | 107 | /** 108 | * 更新当前坐标 109 | * @param point 110 | * @param index 111 | */ 112 | updatePoint(point, index) { 113 | if (index >= 0 && index < this.points.length) { 114 | this.points[index] = point; 115 | this.generate(); 116 | } 117 | } 118 | 119 | /** 120 | * 更新最后一个坐标 121 | * @param point 122 | */ 123 | updateLastPoint(point) { 124 | this.updatePoint(point, this.points.length - 1); 125 | } 126 | 127 | /** 128 | * 结束绘制 129 | */ 130 | finishDrawing() {} 131 | } 132 | 133 | export default Polygon; 134 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ol-plot-vue", 3 | "version": "1.1.12", 4 | "description": "openlayers 标绘 Vue 组件", 5 | "main": "dist/ol-plot-vue.es.js", 6 | "module": "dist/ol-plot-vue.es.js", 7 | "unpkg": "dist/ol-plot-vue.js", 8 | "commonjs": "dist/ol-plot-vue.cjs.js", 9 | "types": "dist/index.d.ts", 10 | "style": "dist/style.css", 11 | "exports": { 12 | ".": { 13 | "types": "./dist/index.d.ts", 14 | "node": { 15 | "import": { 16 | "production": "./dist/ol-plot-vue.es.js", 17 | "development": "./dist/ol-plot-vue.es.js", 18 | "default": "./dist/ol-plot-vue.es.js" 19 | }, 20 | "require": { 21 | "production": "./dist/ol-plot-vue.cjs.js", 22 | "development": "./dist/ol-plot-vue.cjs.js", 23 | "default": "./dist/ol-plot-vue.cjs.js" 24 | } 25 | }, 26 | "import": "./dist/ol-plot-vue.es.js", 27 | "require": "./dist/ol-plot-vue.cjs.js" 28 | }, 29 | "./dist/*.css": { 30 | "import": "./dist/*.css", 31 | "require": "./dist/*.css" 32 | }, 33 | "./package.json": "./package.json" 34 | }, 35 | "sideEffects": [ 36 | "*.css" 37 | ], 38 | "keywords": [ 39 | "javascript", 40 | "webgis", 41 | "canvas", 42 | "ol", 43 | "openlayers", 44 | "map", 45 | "plot", 46 | "map", 47 | "vis", 48 | "gis", 49 | "vue" 50 | ], 51 | "author": "sakitam-fdd ", 52 | "license": "MIT", 53 | "homepage": "https://github.com/sakitam-fdd/ol-plot", 54 | "private": false, 55 | "scripts": { 56 | "dev": "vite build --mode watch", 57 | "build": "pnpm run build-only", 58 | "postbuild": "node scripts/postbuild.js", 59 | "build-only": "vite build", 60 | "type-check": "vue-tsc --noEmit", 61 | "build:vue2": "vue-demi-switch 2 && cd vue2 && yarn && pnpm build", 62 | "build:vue3": "vue-demi-switch 3 && pnpm run build", 63 | "postinstall": "node scripts/postinstall.js" 64 | }, 65 | "peerDependencies": { 66 | "@vue/composition-api": "^1.4.0", 67 | "vue": "^2.6.0 || >=3.0.0" 68 | }, 69 | "peerDependenciesMeta": { 70 | "vue": { 71 | "optional": true 72 | }, 73 | "@vue/composition-api": { 74 | "optional": true 75 | } 76 | }, 77 | "dependenciesMeta": { 78 | "ol-plot": { 79 | "injected": true 80 | } 81 | }, 82 | "dependencies": { 83 | "vue-demi": "^0.14.0", 84 | "@vueuse/core": "^10.0.2", 85 | "ol-plot": "workspace:*" 86 | }, 87 | "devDependencies": { 88 | "@types/node": "^18.15.13", 89 | "@vitejs/plugin-vue": "^4.1.0", 90 | "@vitejs/plugin-vue2": "^2.2.0", 91 | "cross-spawn": "^7.0.3", 92 | "vue": "^3.2.47", 93 | "vite": "^4.4.7", 94 | "vue-tsc": "^1.4.1", 95 | "fs-extra": "^11.1.1" 96 | }, 97 | "publishConfig": { 98 | "access": "public" 99 | } 100 | } -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Arrow/TailedAttackArrow.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/26. 3 | * @desc 进攻方向(尾) 4 | * @Inherits AttackArrow 5 | */ 6 | 7 | import { PlotTypes } from '@/utils/PlotTypes'; 8 | import AttackArrow from './AttackArrow'; 9 | import * as PlotUtils from '../../utils/utils'; 10 | 11 | class TailedAttackArrow extends AttackArrow { 12 | constructor(coordinates, points, params) { 13 | super(coordinates, points, params); 14 | this.type = PlotTypes.TAILED_ATTACK_ARROW; 15 | this.headHeightFactor = 0.18; 16 | this.headWidthFactor = 0.3; 17 | this.neckHeightFactor = 0.85; 18 | this.neckWidthFactor = 0.15; 19 | this.tailWidthFactor = 0.1; 20 | this.headTailFactor = 0.8; 21 | this.swallowTailFactor = 1; 22 | this.swallowTailPnt = null; 23 | this.set('params', params); 24 | if (points && points.length > 0) { 25 | this.setPoints(points); 26 | } else if (coordinates && coordinates.length > 0) { 27 | this.setCoordinates(coordinates); 28 | } 29 | } 30 | 31 | /** 32 | * 执行动作 33 | */ 34 | generate() { 35 | try { 36 | const points = this.getPointCount(); 37 | if (points < 2) { 38 | return false; 39 | } 40 | if (points === 2) { 41 | this.setCoordinates([this.points]); 42 | return false; 43 | } 44 | const pnts = this.getPoints(); 45 | let [tailLeft, tailRight] = [pnts[0], pnts[1]]; 46 | if (PlotUtils.isClockWise(pnts[0], pnts[1], pnts[2])) { 47 | tailLeft = pnts[1]; 48 | tailRight = pnts[0]; 49 | } 50 | const midTail = PlotUtils.Mid(tailLeft, tailRight); 51 | const bonePnts = [midTail].concat(pnts.slice(2)); 52 | const headPnts = this.getArrowHeadPoints(bonePnts, tailLeft, tailRight); 53 | if (headPnts && headPnts.length > 4) { 54 | const [neckLeft, neckRight] = [headPnts[0], headPnts[4]]; 55 | const tailWidth = PlotUtils.MathDistance(tailLeft, tailRight); 56 | const allLen = PlotUtils.getBaseLength(bonePnts); 57 | const len = allLen * this.tailWidthFactor * this.swallowTailFactor; 58 | this.swallowTailPnt = PlotUtils.getThirdPoint(bonePnts[1], bonePnts[0], 0, len, true); 59 | const factor = tailWidth / allLen; 60 | const bodyPnts = this.getArrowBodyPoints(bonePnts, neckLeft, neckRight, factor); 61 | const count = bodyPnts.length; 62 | let leftPnts = [tailLeft].concat(bodyPnts.slice(0, count / 2)); 63 | leftPnts.push(neckLeft); 64 | let rightPnts = [tailRight].concat(bodyPnts.slice(count / 2, count)); 65 | rightPnts.push(neckRight); 66 | leftPnts = PlotUtils.getQBSplinePoints(leftPnts); 67 | rightPnts = PlotUtils.getQBSplinePoints(rightPnts); 68 | this.setCoordinates([leftPnts.concat(headPnts, rightPnts.reverse(), [this.swallowTailPnt, leftPnts[0]])]); 69 | } 70 | } catch (e) { 71 | console.log(e); 72 | } 73 | } 74 | } 75 | 76 | export default TailedAttackArrow; 77 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Arrow/TailedSquadCombat.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/26. 3 | * @desc 分队战斗行动(尾) 4 | * @Inherits AttackArrow 5 | */ 6 | 7 | import { PlotTypes } from '../../utils/PlotTypes'; 8 | import AttackArrow from './AttackArrow'; 9 | import * as PlotUtils from '../../utils/utils'; 10 | import * as Constants from '../../constants'; 11 | 12 | class TailedSquadCombat extends AttackArrow { 13 | constructor(coordinates, points, params) { 14 | super(coordinates, points, params); 15 | this.type = PlotTypes.TAILED_SQUAD_COMBAT; 16 | this.headHeightFactor = 0.18; 17 | this.headWidthFactor = 0.3; 18 | this.neckHeightFactor = 0.85; 19 | this.neckWidthFactor = 0.15; 20 | this.tailWidthFactor = 0.1; 21 | this.swallowTailFactor = 1; 22 | this.swallowTailPnt = null; 23 | this.set('params', params); 24 | if (points && points.length > 0) { 25 | this.setPoints(points); 26 | } else if (coordinates && coordinates.length > 0) { 27 | this.setCoordinates(coordinates); 28 | } 29 | } 30 | 31 | /** 32 | * 执行动作 33 | */ 34 | generate() { 35 | try { 36 | const count = this.getPointCount(); 37 | if (count < 2) { 38 | return false; 39 | // eslint-disable-next-line no-else-return 40 | } else { 41 | const pnts = this.getPoints(); 42 | const tailPnts = this.getTailPoints(pnts); 43 | const headPnts = this.getArrowHeadPoints(pnts, tailPnts[0], tailPnts[2]); 44 | if (headPnts && headPnts.length > 4) { 45 | const neckLeft = headPnts[0]; 46 | const neckRight = headPnts[4]; 47 | const bodyPnts = this.getArrowBodyPoints(pnts, neckLeft, neckRight, this.tailWidthFactor); 48 | // eslint-disable-next-line @typescript-eslint/no-shadow 49 | const count = bodyPnts.length; 50 | let leftPnts = [tailPnts[0]].concat(bodyPnts.slice(0, count / 2)); 51 | leftPnts.push(neckLeft); 52 | let rightPnts = [tailPnts[2]].concat(bodyPnts.slice(count / 2, count)); 53 | rightPnts.push(neckRight); 54 | leftPnts = PlotUtils.getQBSplinePoints(leftPnts); 55 | rightPnts = PlotUtils.getQBSplinePoints(rightPnts); 56 | this.setCoordinates([leftPnts.concat(headPnts, rightPnts.reverse(), [tailPnts[1], leftPnts[0]])]); 57 | } 58 | } 59 | } catch (e) { 60 | console.log(e); 61 | } 62 | } 63 | 64 | getTailPoints(points) { 65 | const allLen = PlotUtils.getBaseLength(points); 66 | const tailWidth = allLen * this.tailWidthFactor; 67 | const tailLeft = PlotUtils.getThirdPoint(points[1], points[0], Constants.HALF_PI, tailWidth, false); 68 | const tailRight = PlotUtils.getThirdPoint(points[1], points[0], Constants.HALF_PI, tailWidth, true); 69 | const len = tailWidth * this.swallowTailFactor; 70 | const swallowTailPnt = PlotUtils.getThirdPoint(points[1], points[0], 0, len, true); 71 | return [tailLeft, swallowTailPnt, tailRight]; 72 | } 73 | } 74 | 75 | export default TailedSquadCombat; 76 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polyline/Curve.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/22. 3 | * @desc 标绘曲线算法 4 | */ 5 | import { Map } from 'ol'; 6 | import { LineString } from 'ol/geom'; 7 | import { PlotTypes } from '@/utils/PlotTypes'; 8 | import type { Point } from '@/utils/utils'; 9 | import * as PlotUtils from '../../utils/utils'; 10 | 11 | class Curve extends LineString { 12 | type: PlotTypes; 13 | 14 | fixPointCount: number; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | t: number; 23 | 24 | constructor(coordinates, points, params) { 25 | super([]); 26 | this.type = PlotTypes.CURVE; 27 | this.t = 0.3; 28 | this.set('params', params); 29 | if (points && points.length > 0) { 30 | this.setPoints(points); 31 | } else if (coordinates && coordinates.length > 0) { 32 | this.setCoordinates(coordinates); 33 | } 34 | } 35 | 36 | /** 37 | * 获取标绘类型 38 | * @returns {*} 39 | */ 40 | getPlotType() { 41 | return this.type; 42 | } 43 | 44 | /** 45 | * 执行动作 46 | */ 47 | generate() { 48 | const count = this.getPointCount(); 49 | if (count < 2) { 50 | return false; 51 | } 52 | if (count === 2) { 53 | this.setCoordinates(this.points); 54 | } else { 55 | const points = PlotUtils.getCurvePoints(this.t, this.points); 56 | this.setCoordinates(points); 57 | } 58 | } 59 | 60 | /** 61 | * 设置地图对象 62 | * @param map 63 | */ 64 | setMap(map) { 65 | if (map && map instanceof Map) { 66 | this.map = map; 67 | } else { 68 | throw new Error('传入的不是地图对象!'); 69 | } 70 | } 71 | 72 | /** 73 | * 获取当前地图对象 74 | * @returns {ol.Map|*} 75 | */ 76 | getMap() { 77 | return this.map; 78 | } 79 | 80 | /** 81 | * 判断是否是Plot 82 | * @returns {boolean} 83 | */ 84 | isPlot() { 85 | return true; 86 | } 87 | 88 | /** 89 | * 设置坐标点 90 | * @param value 91 | */ 92 | setPoints(value) { 93 | this.points = !value ? [] : value; 94 | if (this.points.length >= 1) { 95 | this.generate(); 96 | } 97 | } 98 | 99 | /** 100 | * 获取坐标点 101 | * @returns {Array.} 102 | */ 103 | getPoints() { 104 | return this.points.slice(0); 105 | } 106 | 107 | /** 108 | * 获取点数量 109 | * @returns {Number} 110 | */ 111 | getPointCount() { 112 | return this.points.length; 113 | } 114 | 115 | /** 116 | * 更新当前坐标 117 | * @param point 118 | * @param index 119 | */ 120 | updatePoint(point, index) { 121 | if (index >= 0 && index < this.points.length) { 122 | this.points[index] = point; 123 | this.generate(); 124 | } 125 | } 126 | 127 | /** 128 | * 更新最后一个坐标 129 | * @param point 130 | */ 131 | updateLastPoint(point) { 132 | this.updatePoint(point, this.points.length - 1); 133 | } 134 | 135 | /** 136 | * 结束绘制 137 | */ 138 | finishDrawing() {} 139 | } 140 | 141 | export default Curve; 142 | -------------------------------------------------------------------------------- /packages/ol-plot/src/utils/layerUtils.ts: -------------------------------------------------------------------------------- 1 | import { Style, Circle, Stroke, Fill } from 'ol/style'; 2 | 3 | import { Group, type Layer, Vector } from 'ol/layer'; 4 | 5 | import { Vector as VectorSource } from 'ol/source'; 6 | 7 | /** 8 | * 通过layerName获取图层 9 | * @param map 10 | * @param layerName 11 | * @returns {*} 12 | */ 13 | const getLayerByLayerName = function (map, layerName): WithNull { 14 | try { 15 | let targetLayer = null; 16 | if (map) { 17 | const layers = map.getLayers().getArray(); 18 | // eslint-disable-next-line @typescript-eslint/no-use-before-define 19 | targetLayer = getLayerInternal(layers, 'layerName', layerName); 20 | } 21 | return targetLayer; 22 | } catch (e) { 23 | console.log(e); 24 | return null; 25 | } 26 | }; 27 | 28 | /** 29 | * 内部处理获取图层方法 30 | * @param layers 31 | * @param key 32 | * @param value 33 | * @returns {*} 34 | */ 35 | const getLayerInternal = function (layers, key, value) { 36 | let _target = null; 37 | if (layers.length > 0) { 38 | layers.every((layer) => { 39 | if (layer instanceof Group) { 40 | const ly = layer.getLayers().getArray(); 41 | _target = getLayerInternal(ly, key, value); 42 | return !_target; 43 | } 44 | if (layer.get(key) === value) { 45 | _target = layer; 46 | return false; 47 | } 48 | return true; 49 | }); 50 | } 51 | return _target; 52 | }; 53 | 54 | /** 55 | * 创建临时图层 56 | * @param map 57 | * @param layerName 58 | * @param params 59 | * @returns {*} 60 | */ 61 | const createVectorLayer = function (map, layerName, params) { 62 | try { 63 | if (map) { 64 | let vectorLayer = getLayerByLayerName(map, layerName); 65 | if (!(vectorLayer instanceof Vector)) { 66 | vectorLayer = null; 67 | } 68 | if (!vectorLayer) { 69 | if (params && params.create) { 70 | vectorLayer = new Vector({ 71 | // @ts-ignore this is unsafe 72 | layerName, 73 | params, 74 | layerType: 'vector', 75 | source: new VectorSource({ 76 | wrapX: false, 77 | }), 78 | style: new Style({ 79 | fill: new Fill({ 80 | color: 'rgba(67, 110, 238, 0.4)', 81 | }), 82 | stroke: new Stroke({ 83 | color: '#4781d9', 84 | width: 2, 85 | }), 86 | image: new Circle({ 87 | radius: 7, 88 | fill: new Fill({ 89 | color: '#ffcc33', 90 | }), 91 | }), 92 | }), 93 | }); 94 | } 95 | } 96 | if (map && vectorLayer) { 97 | if (params && params.hasOwnProperty('selectable')) { 98 | vectorLayer.set('selectable', params.selectable); 99 | } 100 | // 图层只添加一次 101 | const _vectorLayer = getLayerByLayerName(map, layerName); 102 | if (!_vectorLayer || !(_vectorLayer instanceof Vector)) { 103 | map.addLayer(vectorLayer); 104 | } 105 | } 106 | return vectorLayer; 107 | } 108 | } catch (e) { 109 | console.error(e); 110 | } 111 | }; 112 | 113 | export { createVectorLayer, getLayerByLayerName }; 114 | -------------------------------------------------------------------------------- /packages/ol-plot/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import path, { resolve } from 'path'; 3 | import { fileURLToPath } from 'url'; 4 | import dts from 'vite-plugin-dts'; 5 | import eslint from 'vite-plugin-eslint'; 6 | import { viteExternalsPlugin } from 'vite-plugin-externals'; 7 | 8 | const ROOT = fileURLToPath(import.meta.url); 9 | 10 | const r = (p: string) => resolve(ROOT, '..', p); 11 | 12 | const name = 'ol-plot'; 13 | 14 | // https://vitejs.dev/config/ 15 | export default defineConfig(({ command, mode }) => ({ 16 | base: './', 17 | publicDir: 'assets', 18 | build: { 19 | outDir: 'dist', 20 | assetsDir: 'images', 21 | assetsInlineLimit: 0, // @link https://cn.vitejs.dev/config/#build-assetsinlinelimit 22 | watch: mode === 'watch' ? {} : null, 23 | minify: mode === 'minify' ? 'esbuild' : false, 24 | sourcemap: mode !== 'minify', 25 | brotliSize: true, // @link https://cn.vitejs.dev/config/#build-brotlisize 26 | // @link https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/css.ts#L483 27 | cssCodeSplit: false, // @link https://cn.vitejs.dev/config/#build-csscodesplit 28 | emptyOutDir: false, 29 | lib: { 30 | entry: r('src/index.ts'), 31 | name: 'olPlot', 32 | formats: ['es', 'cjs', 'umd'], 33 | fileName: (format) => { 34 | if (mode === 'minify') { 35 | return format === 'umd' ? `${name}.min.js` : `${name}.${format}.min.js`; 36 | } 37 | return format === 'umd' ? `${name}.js` : `${name}.${format}.js`; 38 | }, 39 | }, 40 | rollupOptions: { 41 | output: { 42 | // assetFileNames: '[name].[ext]', 43 | assetFileNames: 'ol-plot.[ext]', // hack for css file 44 | globals: { 45 | ol: 'ol', 46 | 'ol/style': 'ol.style', 47 | 'ol/layer': 'ol.layer', 48 | 'ol/source': 'ol.source', 49 | 'ol/geom': 'ol.geom', 50 | 'ol/geom/Polygon': 'ol.geom.Polygon', 51 | 'ol/color': 'ol.color', 52 | 'ol/extent': 'ol.extent', 53 | 'ol/events/Event': 'ol.events.Event', 54 | 'ol/interaction/Draw': 'ol.interaction.Draw', 55 | 'ol/interaction/DragPan': 'ol.interaction.DragPan', 56 | 'ol/interaction/DoubleClickZoom': 'ol.interaction.DoubleClickZoom', 57 | }, 58 | }, 59 | external: (id) => /^ol/.test(id), 60 | }, 61 | }, 62 | plugins: [ 63 | dts({ 64 | rollupTypes: true, 65 | staticImport: true, 66 | insertTypesEntry: true 67 | }), 68 | viteExternalsPlugin(), 69 | ...(mode === 'watch' ? [eslint()] : []), 70 | ], 71 | css: { 72 | preprocessorOptions: { 73 | less: { 74 | globalVars: {}, 75 | // 支持内联 JavaScript 76 | javascriptEnabled: true, 77 | // 重写 less 变量,定制样式 78 | // modifyVars: themeVariables, 79 | sourceMap: false, 80 | }, 81 | }, 82 | modules: { 83 | localsConvention: 'camelCase', 84 | }, 85 | }, 86 | resolve: { 87 | alias: { 88 | '@': path.resolve(__dirname, 'src'), 89 | }, 90 | }, 91 | test: { 92 | testTimeout: 50000, 93 | // setupFiles: '../../vitest/setupTest.ts', 94 | coverage: { 95 | reporter: ['lcov', 'html'], 96 | }, 97 | threads: false, 98 | }, 99 | })); 100 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polygon/RectAngle.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/24. 3 | * @desc 规则矩形 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon } from 'ol/geom'; 8 | import { fromExtent } from 'ol/geom/Polygon'; 9 | import { boundingExtent } from 'ol/extent'; 10 | import { PlotTypes } from '@/utils/PlotTypes'; 11 | import type { Point } from '@/utils/utils'; 12 | 13 | class RectAngle extends Polygon { 14 | type: PlotTypes; 15 | 16 | fixPointCount: WithUndef; 17 | 18 | map: any; 19 | 20 | points: Point[]; 21 | 22 | freehand: boolean; 23 | 24 | isFill: boolean; 25 | 26 | constructor(coordinates, points, params) { 27 | super([]); 28 | this.type = PlotTypes.RECTANGLE; 29 | this.fixPointCount = 2; 30 | this.set('params', params); 31 | this.isFill = params.isFill === false ? params.isFill : true; 32 | if (points && points.length > 0) { 33 | this.setPoints(points); 34 | } else if (coordinates && coordinates.length > 0) { 35 | this.setCoordinates(coordinates); 36 | } 37 | } 38 | 39 | /** 40 | * 获取标绘类型 41 | * @returns {*} 42 | */ 43 | getPlotType() { 44 | return this.type; 45 | } 46 | 47 | /** 48 | * 执行动作 49 | */ 50 | generate() { 51 | if (this.points.length === 2) { 52 | let coordinates: any; 53 | if (this.isFill) { 54 | const extent = boundingExtent(this.points); 55 | const polygon = fromExtent(extent); 56 | coordinates = polygon.getCoordinates(); 57 | } else { 58 | const start = this.points[0]; 59 | const end = this.points[1]; 60 | coordinates = [start, [start[0], end[1]], end, [end[0], start[1]], start]; 61 | } 62 | this.setCoordinates(coordinates); 63 | } 64 | } 65 | 66 | /** 67 | * 设置地图对象 68 | * @param map 69 | */ 70 | setMap(map) { 71 | if (map && map instanceof Map) { 72 | this.map = map; 73 | } else { 74 | throw new Error('传入的不是地图对象!'); 75 | } 76 | } 77 | 78 | /** 79 | * 获取当前地图对象 80 | * @returns {Map|*} 81 | */ 82 | getMap() { 83 | return this.map; 84 | } 85 | 86 | /** 87 | * 判断是否是Plot 88 | * @returns {boolean} 89 | */ 90 | isPlot() { 91 | return true; 92 | } 93 | 94 | /** 95 | * 设置坐标点 96 | * @param value 97 | */ 98 | setPoints(value) { 99 | this.points = !value ? [] : value; 100 | if (this.points.length >= 1) { 101 | this.generate(); 102 | } 103 | } 104 | 105 | /** 106 | * 获取坐标点 107 | * @returns {Array.} 108 | */ 109 | getPoints() { 110 | return this.points.slice(0); 111 | } 112 | 113 | /** 114 | * 获取点数量 115 | * @returns {Number} 116 | */ 117 | getPointCount() { 118 | return this.points.length; 119 | } 120 | 121 | /** 122 | * 更新当前坐标 123 | * @param point 124 | * @param index 125 | */ 126 | updatePoint(point, index) { 127 | if (index >= 0 && index < this.points.length) { 128 | this.points[index] = point; 129 | this.generate(); 130 | } 131 | } 132 | 133 | /** 134 | * 更新最后一个坐标 135 | * @param point 136 | */ 137 | updateLastPoint(point) { 138 | this.updatePoint(point, this.points.length - 1); 139 | } 140 | 141 | /** 142 | * 结束绘制 143 | */ 144 | finishDrawing() {} 145 | } 146 | 147 | export default RectAngle; 148 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polygon/Sector.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/25. 3 | * @desc 扇形 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon as $Polygon } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import * as PlotUtils from '@/utils/utils'; 10 | import type { Point } from '@/utils/utils'; 11 | 12 | class Sector extends $Polygon { 13 | type: PlotTypes; 14 | 15 | fixPointCount: WithUndef; 16 | 17 | map: any; 18 | 19 | points: Point[]; 20 | 21 | freehand: boolean; 22 | 23 | constructor(coordinates, points, params) { 24 | super([]); 25 | this.type = PlotTypes.SECTOR; 26 | this.fixPointCount = 3; 27 | this.set('params', params); 28 | if (points && points.length > 0) { 29 | this.setPoints(points); 30 | } else if (coordinates && coordinates.length > 0) { 31 | this.setCoordinates(coordinates); 32 | } 33 | } 34 | 35 | /** 36 | * 获取标绘类型 37 | * @returns {*} 38 | */ 39 | getPlotType() { 40 | return this.type; 41 | } 42 | 43 | /** 44 | * 执行动作 45 | */ 46 | generate() { 47 | const points = this.getPointCount(); 48 | if (points < 2) { 49 | return false; 50 | } 51 | if (points === 2) { 52 | this.setCoordinates([this.points]); 53 | } else { 54 | const pnts = this.getPoints(); 55 | const [center, pnt2, pnt3] = [pnts[0], pnts[1], pnts[2]]; 56 | const radius = PlotUtils.MathDistance(pnt2, center); 57 | const startAngle = PlotUtils.getAzimuth(pnt2, center); 58 | const endAngle = PlotUtils.getAzimuth(pnt3, center); 59 | const pList = PlotUtils.getArcPoints(center, radius, startAngle, endAngle); 60 | pList.push(center, pList[0]); 61 | this.setCoordinates([pList]); 62 | } 63 | } 64 | 65 | /** 66 | * 设置地图对象 67 | * @param map 68 | */ 69 | setMap(map) { 70 | if (map && map instanceof Map) { 71 | this.map = map; 72 | } else { 73 | throw new Error('传入的不是地图对象!'); 74 | } 75 | } 76 | 77 | /** 78 | * 获取当前地图对象 79 | * @returns {ol.Map|*} 80 | */ 81 | getMap() { 82 | return this.map; 83 | } 84 | 85 | /** 86 | * 判断是否是Plot 87 | * @returns {boolean} 88 | */ 89 | isPlot() { 90 | return true; 91 | } 92 | 93 | /** 94 | * 设置坐标点 95 | * @param value 96 | */ 97 | setPoints(value) { 98 | this.points = !value ? [] : value; 99 | if (this.points.length >= 1) { 100 | this.generate(); 101 | } 102 | } 103 | 104 | /** 105 | * 获取坐标点 106 | * @returns {Array.} 107 | */ 108 | getPoints() { 109 | return this.points.slice(0); 110 | } 111 | 112 | /** 113 | * 获取点数量 114 | * @returns {Number} 115 | */ 116 | getPointCount() { 117 | return this.points.length; 118 | } 119 | 120 | /** 121 | * 更新当前坐标 122 | * @param point 123 | * @param index 124 | */ 125 | updatePoint(point, index) { 126 | if (index >= 0 && index < this.points.length) { 127 | this.points[index] = point; 128 | this.generate(); 129 | } 130 | } 131 | 132 | /** 133 | * 更新最后一个坐标 134 | * @param point 135 | */ 136 | updateLastPoint(point) { 137 | this.updatePoint(point, this.points.length - 1); 138 | } 139 | 140 | /** 141 | * 结束绘制 142 | */ 143 | finishDrawing() {} 144 | } 145 | 146 | export default Sector; 147 | -------------------------------------------------------------------------------- /packages/ol-plot/src/utils/PlotTypes.ts: -------------------------------------------------------------------------------- 1 | import type Point from '@/geometry/Point/Point'; 2 | import type Pennant from '@/geometry/Point/Pennant'; 3 | import type Polyline from '@/geometry/Polyline/Polyline'; 4 | import type Arc from '@/geometry/Arc/Arc'; 5 | import type Circle from '@/geometry/Circle/Circle'; 6 | import type Curve from '@/geometry/Polyline/Curve'; 7 | import type FreeHandLine from '@/geometry/Polyline/FreeHandLine'; 8 | import type RectAngle from '@/geometry/Polygon/RectAngle'; 9 | import type Ellipse from '@/geometry/Circle/Ellipse'; 10 | import type Lune from '@/geometry/Polygon/Lune'; 11 | import type Sector from '@/geometry/Polygon/Sector'; 12 | import type ClosedCurve from '@/geometry/Polygon/ClosedCurve'; 13 | import type Polygon from '@/geometry/Polygon/Polygon'; 14 | import type FreePolygon from '@/geometry/Polygon/FreePolygon'; 15 | import type AttackArrow from '@/geometry/Arrow/AttackArrow'; 16 | import type DoubleArrow from '@/geometry/Arrow/DoubleArrow'; 17 | import type StraightArrow from '@/geometry/Arrow/StraightArrow'; 18 | import type FineArrow from '@/geometry/Arrow/FineArrow'; 19 | import type AssaultDirection from '@/geometry/Arrow/AssaultDirection'; 20 | import type TailedAttackArrow from '@/geometry/Arrow/TailedAttackArrow'; 21 | import type SquadCombat from '@/geometry/Arrow/SquadCombat'; 22 | import type TailedSquadCombat from '@/geometry/Arrow/TailedSquadCombat'; 23 | import type GatheringPlace from '@/geometry/Polygon/GatheringPlace'; 24 | import type RectFlag from '@/geometry/Flag/RectFlag'; 25 | import type TriangleFlag from '@/geometry/Flag/TriangleFlag'; 26 | import type CurveFlag from '@/geometry/Flag/CurveFlag'; 27 | // import type PlotTextBox from '../Geometry/Text/PlotTextBox'; 28 | import type RectInclined1 from '@/geometry/Polygon/Rectinclined1'; 29 | import type RectInclined2 from '@/geometry/Polygon/Rectinclined2'; 30 | 31 | export type PlotTypesSource = 32 | | Point 33 | | Pennant 34 | | Polyline 35 | | Arc 36 | | Circle 37 | | Curve 38 | | FreeHandLine 39 | | RectAngle 40 | | Ellipse 41 | | Lune 42 | | Sector 43 | | ClosedCurve 44 | | Polygon 45 | | FreePolygon 46 | | AttackArrow 47 | | DoubleArrow 48 | | StraightArrow 49 | | FineArrow 50 | | AssaultDirection 51 | | TailedAttackArrow 52 | | SquadCombat 53 | | TailedSquadCombat 54 | | GatheringPlace 55 | | RectFlag 56 | | TriangleFlag 57 | | CurveFlag 58 | // | PlotTextBox 59 | | RectInclined1 60 | | RectInclined2; 61 | 62 | export enum PlotTypes { 63 | TEXTAREA = 'TextArea', 64 | ARC = 'Arc', 65 | CURVE = 'Curve', 66 | GATHERING_PLACE = 'GatheringPlace', 67 | POLYLINE = 'Polyline', 68 | FREEHANDLINE = 'FreeHandLine', 69 | POINT = 'Point', 70 | PENNANT = 'Pennant', 71 | RECTANGLE = 'RectAngle', 72 | CIRCLE = 'Circle', 73 | ELLIPSE = 'Ellipse', 74 | LUNE = 'Lune', 75 | SECTOR = 'Sector', 76 | CLOSED_CURVE = 'ClosedCurve', 77 | POLYGON = 'Polygon', 78 | FREE_POLYGON = 'FreePolygon', 79 | ATTACK_ARROW = 'AttackArrow', 80 | DOUBLE_ARROW = 'DoubleArrow', 81 | STRAIGHT_ARROW = 'StraightArrow', 82 | FINE_ARROW = 'FineArrow', 83 | ASSAULT_DIRECTION = 'AssaultDirection', 84 | TAILED_SQUAD_COMBAT = 'TailedSquadCombat', 85 | TAILED_ATTACK_ARROW = 'TailedAttackArrow', 86 | SQUAD_COMBAT = 'SquadCombat', 87 | RECTFLAG = 'RectFlag', 88 | TRIANGLEFLAG = 'TriangleFlag', 89 | CURVEFLAG = 'CurveFlag', 90 | RECTINCLINED1 = 'RectInclined1', 91 | RECTINCLINED2 = 'RectInclined2', 92 | } 93 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Circle/Circle.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/22. 3 | * @desc 标绘画圆算法,继承面要素相关方法和属性 4 | */ 5 | import { Map } from 'ol'; 6 | import { Polygon } from 'ol/geom'; 7 | import type { Point } from '@/utils/utils'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import * as PlotUtils from '../../utils/utils'; 10 | 11 | class Circle extends Polygon { 12 | type: PlotTypes; 13 | 14 | fixPointCount: WithUndef; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | constructor(coordinates, points, params) { 23 | super([]); 24 | this.type = PlotTypes.CIRCLE; 25 | this.fixPointCount = 2; 26 | this.set('params', params); 27 | if (points && points.length > 0) { 28 | this.setPoints(points); 29 | } else if (coordinates && coordinates.length > 0) { 30 | this.setCoordinates(coordinates); 31 | } 32 | } 33 | 34 | /** 35 | * 获取标绘类型 36 | * @returns {*} 37 | */ 38 | getPlotType() { 39 | return this.type; 40 | } 41 | 42 | generate() { 43 | const count = this.getPointCount(); 44 | if (count < 2) { 45 | return false; 46 | } 47 | const center = this.points[0]; 48 | const radius = PlotUtils.MathDistance(center as Point, this.points[1]); 49 | this.setCoordinates([this.generatePoints(center, radius)]); 50 | } 51 | 52 | /** 53 | * 对圆边线进行插值 54 | * @param center 55 | * @param radius 56 | * @returns {null} 57 | */ 58 | generatePoints(center, radius) { 59 | let [x, y, angle] = [0, 0, 0]; 60 | const points: Point[] = []; 61 | for (let i = 0; i <= 100; i++) { 62 | angle = (Math.PI * 2 * i) / 100; 63 | x = center[0] + radius * Math.cos(angle); 64 | y = center[1] + radius * Math.sin(angle); 65 | points.push([x, y]); 66 | } 67 | return points; 68 | } 69 | 70 | /** 71 | * 设置地图对象 72 | * @param map 73 | */ 74 | setMap(map) { 75 | if (map && map instanceof Map) { 76 | this.map = map; 77 | } else { 78 | throw new Error('传入的不是地图对象!'); 79 | } 80 | } 81 | 82 | /** 83 | * 获取当前地图对象 84 | * @returns {{}|*} 85 | */ 86 | getMap() { 87 | return this.map; 88 | } 89 | 90 | /** 91 | * 判断是否是Plot 92 | * @returns {boolean} 93 | */ 94 | isPlot() { 95 | return true; 96 | } 97 | 98 | /** 99 | * 设置坐标点 100 | * @param value 101 | */ 102 | setPoints(value) { 103 | this.points = !value ? [] : value; 104 | if (this.points.length >= 1) { 105 | this.generate(); 106 | } 107 | } 108 | 109 | /** 110 | * 获取坐标点 111 | * @returns {Array.} 112 | */ 113 | getPoints() { 114 | return this.points.slice(0); 115 | } 116 | 117 | /** 118 | * 获取点数量 119 | * @returns {Number} 120 | */ 121 | getPointCount() { 122 | return this.points.length; 123 | } 124 | 125 | /** 126 | * 更新当前坐标 127 | * @param point 128 | * @param index 129 | */ 130 | updatePoint(point, index) { 131 | if (index >= 0 && index < this.points.length) { 132 | this.points[index] = point; 133 | this.generate(); 134 | } 135 | } 136 | 137 | /** 138 | * 更新最后一个坐标 139 | * @param point 140 | */ 141 | updateLastPoint(point) { 142 | this.updatePoint(point, this.points.length - 1); 143 | } 144 | 145 | /** 146 | * 结束绘制 147 | */ 148 | finishDrawing() {} 149 | } 150 | 151 | export default Circle; 152 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Flag/TriangleFlag.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/9/13. 3 | * @desc 三角旗标(使用两个控制点直接创建三角旗标) 4 | */ 5 | import { Map } from 'ol'; 6 | import { Polygon } from 'ol/geom'; 7 | 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import type { Point } from '@/utils/utils'; 10 | 11 | class TriangleFlag extends Polygon { 12 | type: PlotTypes; 13 | 14 | fixPointCount: WithUndef; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | constructor(coordinates, points, params) { 23 | super([]); 24 | this.type = PlotTypes.TRIANGLEFLAG; 25 | this.fixPointCount = 2; 26 | this.set('params', params); 27 | if (points && points.length > 0) { 28 | this.setPoints(points); 29 | } else if (coordinates && coordinates.length > 0) { 30 | this.setCoordinates(coordinates); 31 | } 32 | } 33 | 34 | /** 35 | * 获取标绘类型 36 | * @returns {*} 37 | */ 38 | getPlotType() { 39 | return this.type; 40 | } 41 | 42 | /** 43 | * 执行动作 44 | */ 45 | generate() { 46 | const count = this.getPointCount(); 47 | if (count < 2) { 48 | return false; 49 | } 50 | this.setCoordinates([this.calculatePonits(this.points)]); 51 | } 52 | 53 | /** 54 | * 插值点数据 55 | * @param points 56 | * @returns {Array} 57 | */ 58 | calculatePonits(points) { 59 | let components: Point[] = []; 60 | // 至少需要两个控制点 61 | if (points.length > 1) { 62 | // 取第一个 63 | const startPoint = points[0]; 64 | // 取最后一个 65 | const endPoint = points[points.length - 1]; 66 | const point1 = [endPoint[0], (startPoint[1] + endPoint[1]) / 2]; 67 | const point2 = [startPoint[0], (startPoint[1] + endPoint[1]) / 2]; 68 | const point3 = [startPoint[0], endPoint[1]]; 69 | components = [startPoint, point1, point2, point3]; 70 | } 71 | return components; 72 | } 73 | 74 | /** 75 | * 设置地图对象 76 | * @param map 77 | */ 78 | setMap(map) { 79 | if (map && map instanceof Map) { 80 | this.map = map; 81 | } else { 82 | throw new Error('传入的不是地图对象!'); 83 | } 84 | } 85 | 86 | /** 87 | * 获取当前地图对象 88 | * @returns {Map|*} 89 | */ 90 | getMap() { 91 | return this.map; 92 | } 93 | 94 | /** 95 | * 判断是否是Plot 96 | * @returns {boolean} 97 | */ 98 | isPlot() { 99 | return true; 100 | } 101 | 102 | /** 103 | * 设置坐标点 104 | * @param value 105 | */ 106 | setPoints(value) { 107 | this.points = !value ? [] : value; 108 | if (this.points.length >= 1) { 109 | this.generate(); 110 | } 111 | } 112 | 113 | /** 114 | * 获取坐标点 115 | * @returns {Array.} 116 | */ 117 | getPoints() { 118 | return this.points.slice(0); 119 | } 120 | 121 | /** 122 | * 获取点数量 123 | * @returns {Number} 124 | */ 125 | getPointCount() { 126 | return this.points.length; 127 | } 128 | 129 | /** 130 | * 更新当前坐标 131 | * @param point 132 | * @param index 133 | */ 134 | updatePoint(point, index) { 135 | if (index >= 0 && index < this.points.length) { 136 | this.points[index] = point; 137 | this.generate(); 138 | } 139 | } 140 | 141 | /** 142 | * 更新最后一个坐标 143 | * @param point 144 | */ 145 | updateLastPoint(point) { 146 | this.updatePoint(point, this.points.length - 1); 147 | } 148 | 149 | /** 150 | * 结束绘制 151 | */ 152 | finishDrawing() {} 153 | } 154 | 155 | export default TriangleFlag; 156 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Flag/RectFlag.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/9/13. 3 | * @desc 直角旗标(使用两个控制点直接创建直角旗标) 4 | */ 5 | import { Map } from 'ol'; 6 | import { Polygon } from 'ol/geom'; 7 | import { PlotTypes } from '@/utils/PlotTypes'; 8 | import type { Point } from '@/utils/utils'; 9 | 10 | class RectFlag extends Polygon { 11 | type: PlotTypes; 12 | 13 | fixPointCount: WithUndef; 14 | 15 | map: any; 16 | 17 | points: Point[]; 18 | 19 | freehand: boolean; 20 | 21 | constructor(coordinates, points, params) { 22 | super([]); 23 | this.type = PlotTypes.RECTFLAG; 24 | this.fixPointCount = 2; 25 | this.set('params', params); 26 | if (points && points.length > 0) { 27 | this.setPoints(points); 28 | } else if (coordinates && coordinates.length > 0) { 29 | this.setCoordinates(coordinates); 30 | } 31 | } 32 | 33 | /** 34 | * 获取标绘类型 35 | * @returns {*} 36 | */ 37 | getPlotType() { 38 | return this.type; 39 | } 40 | 41 | /** 42 | * 执行动作 43 | */ 44 | generate() { 45 | const count = this.getPointCount(); 46 | if (count < 2) { 47 | return false; 48 | } 49 | this.setCoordinates([this.calculatePonits(this.points)]); 50 | } 51 | 52 | /** 53 | * 插值点数据 54 | * @param points 55 | * @returns {Array} 56 | */ 57 | calculatePonits(points) { 58 | let components: Point[] = []; 59 | // 至少需要两个控制点 60 | if (points.length > 1) { 61 | // 取第一个 62 | const startPoint = points[0]; 63 | // 取最后一个 64 | const endPoint = points[points.length - 1]; 65 | const point1 = [endPoint[0], startPoint[1]]; 66 | const point2 = [endPoint[0], (startPoint[1] + endPoint[1]) / 2]; 67 | const point3 = [startPoint[0], (startPoint[1] + endPoint[1]) / 2]; 68 | const point4 = [startPoint[0], endPoint[1]]; 69 | components = [startPoint, point1, point2, point3, point4]; 70 | } 71 | return components; 72 | } 73 | 74 | /** 75 | * 设置地图对象 76 | * @param map 77 | */ 78 | setMap(map) { 79 | if (map && map instanceof Map) { 80 | this.map = map; 81 | } else { 82 | throw new Error('传入的不是地图对象!'); 83 | } 84 | } 85 | 86 | /** 87 | * 获取当前地图对象 88 | * @returns {Map|*} 89 | */ 90 | getMap() { 91 | return this.map; 92 | } 93 | 94 | /** 95 | * 判断是否是Plot 96 | * @returns {boolean} 97 | */ 98 | isPlot() { 99 | return true; 100 | } 101 | 102 | /** 103 | * 设置坐标点 104 | * @param value 105 | */ 106 | setPoints(value) { 107 | this.points = !value ? [] : value; 108 | if (this.points.length >= 1) { 109 | this.generate(); 110 | } 111 | } 112 | 113 | /** 114 | * 获取坐标点 115 | * @returns {Array.} 116 | */ 117 | getPoints() { 118 | return this.points.slice(0); 119 | } 120 | 121 | /** 122 | * 获取点数量 123 | * @returns {Number} 124 | */ 125 | getPointCount() { 126 | return this.points.length; 127 | } 128 | 129 | /** 130 | * 更新当前坐标 131 | * @param point 132 | * @param index 133 | */ 134 | updatePoint(point, index) { 135 | if (index >= 0 && index < this.points.length) { 136 | this.points[index] = point; 137 | this.generate(); 138 | } 139 | } 140 | 141 | /** 142 | * 更新最后一个坐标 143 | * @param point 144 | */ 145 | updateLastPoint(point) { 146 | this.updatePoint(point, this.points.length - 1); 147 | } 148 | 149 | /** 150 | * 结束绘制 151 | */ 152 | finishDrawing() {} 153 | } 154 | 155 | export default RectFlag; 156 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Arrow/StraightArrow.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/24. 3 | * @desc 细直箭头 4 | */ 5 | import { Map } from 'ol'; 6 | import { LineString } from 'ol/geom'; 7 | import { PlotTypes } from '@/utils/PlotTypes'; 8 | import * as PlotUtils from '@/utils/utils'; 9 | import type { Point } from '@/utils/utils'; 10 | 11 | class StraightArrow extends LineString { 12 | type: PlotTypes; 13 | 14 | fixPointCount: WithUndef; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | maxArrowLength: number; 23 | 24 | arrowLengthScale: number; 25 | 26 | constructor(coordinates, points, params) { 27 | super([]); 28 | this.type = PlotTypes.STRAIGHT_ARROW; 29 | this.fixPointCount = 2; 30 | this.maxArrowLength = 3000000; 31 | this.arrowLengthScale = 5; 32 | this.set('params', params); 33 | if (points && points.length > 0) { 34 | this.setPoints(points); 35 | } else if (coordinates && coordinates.length > 0) { 36 | this.setCoordinates(coordinates); 37 | } 38 | } 39 | 40 | /** 41 | * 获取标绘类型 42 | * @returns {*} 43 | */ 44 | getPlotType() { 45 | return this.type; 46 | } 47 | 48 | /** 49 | * 执行动作 50 | */ 51 | generate() { 52 | try { 53 | const count = this.getPointCount(); 54 | if (count < 2) { 55 | return false; 56 | } 57 | const pnts = this.getPoints(); 58 | const [pnt1, pnt2] = [pnts[0], pnts[1]]; 59 | const distance = PlotUtils.MathDistance(pnt1, pnt2); 60 | let len = distance / this.arrowLengthScale; 61 | len = len > this.maxArrowLength ? this.maxArrowLength : len; 62 | const leftPnt = PlotUtils.getThirdPoint(pnt1, pnt2, Math.PI / 6, len, false); 63 | const rightPnt = PlotUtils.getThirdPoint(pnt1, pnt2, Math.PI / 6, len, true); 64 | this.setCoordinates([pnt1, pnt2, leftPnt, pnt2, rightPnt]); 65 | } catch (e) { 66 | console.log(e); 67 | } 68 | } 69 | 70 | /** 71 | * 设置地图对象 72 | * @param map 73 | */ 74 | setMap(map) { 75 | if (map && map instanceof Map) { 76 | this.map = map; 77 | } else { 78 | throw new Error('传入的不是地图对象!'); 79 | } 80 | } 81 | 82 | /** 83 | * 获取当前地图对象 84 | * @returns {{}|*} 85 | */ 86 | getMap() { 87 | return this.map; 88 | } 89 | 90 | /** 91 | * 判断是否是Plot 92 | * @returns {boolean} 93 | */ 94 | isPlot() { 95 | return true; 96 | } 97 | 98 | /** 99 | * 设置坐标点 100 | * @param value 101 | */ 102 | setPoints(value) { 103 | this.points = !value ? [] : value; 104 | if (this.points.length >= 1) { 105 | this.generate(); 106 | } 107 | } 108 | 109 | /** 110 | * 获取坐标点 111 | * @returns {Array.} 112 | */ 113 | getPoints() { 114 | return this.points.slice(0); 115 | } 116 | 117 | /** 118 | * 获取点数量 119 | * @returns {Number} 120 | */ 121 | getPointCount() { 122 | return this.points.length; 123 | } 124 | 125 | /** 126 | * 更新当前坐标 127 | * @param point 128 | * @param index 129 | */ 130 | updatePoint(point, index) { 131 | if (index >= 0 && index < this.points.length) { 132 | this.points[index] = point; 133 | this.generate(); 134 | } 135 | } 136 | 137 | /** 138 | * 更新最后一个坐标 139 | * @param point 140 | */ 141 | updateLastPoint(point) { 142 | this.updatePoint(point, this.points.length - 1); 143 | } 144 | 145 | /** 146 | * 结束绘制 147 | */ 148 | finishDrawing() {} 149 | } 150 | 151 | export default StraightArrow; 152 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Arc/Arc.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/22. 3 | * @desc 标绘画弓形算法,继承线要素相关方法和属性 4 | */ 5 | import { Map } from 'ol'; 6 | import { LineString } from 'ol/geom'; 7 | import { PlotTypes } from '@/utils/PlotTypes'; 8 | import * as PlotUtils from '@/utils/utils'; 9 | import type { Point } from '@/utils/utils'; 10 | 11 | class Arc extends LineString { 12 | type: PlotTypes; 13 | 14 | fixPointCount: number; 15 | 16 | freehand: boolean; 17 | 18 | map: any; 19 | 20 | points: Point[]; 21 | 22 | constructor(coordinates, points, params) { 23 | super([]); 24 | this.type = PlotTypes.ARC; 25 | this.fixPointCount = 3; 26 | this.set('params', params); 27 | if (points && points.length > 0) { 28 | this.setPoints(points); 29 | } else if (coordinates && coordinates.length > 0) { 30 | this.setCoordinates(coordinates); 31 | } 32 | } 33 | 34 | /** 35 | * 获取标绘类型 36 | * @returns {*} 37 | */ 38 | getPlotType() { 39 | return this.type; 40 | } 41 | 42 | /** 43 | * 执行动作 44 | */ 45 | generate() { 46 | const count = this.getPointCount(); 47 | if (count < 2) return; 48 | if (count === 2) { 49 | this.setCoordinates(this.points); 50 | } else { 51 | // eslint-disable-next-line 52 | let [pnt1, pnt2, pnt3, startAngle, endAngle] = [this.points[0], this.points[1], this.points[2], 0, 0]; 53 | const center = PlotUtils.getCircleCenterOfThreePoints(pnt1, pnt2, pnt3); 54 | const radius = PlotUtils.MathDistance(pnt1, center); 55 | const angle1 = PlotUtils.getAzimuth(pnt1, center); 56 | const angle2 = PlotUtils.getAzimuth(pnt2, center); 57 | if (PlotUtils.isClockWise(pnt1, pnt2, pnt3)) { 58 | startAngle = angle2; 59 | endAngle = angle1; 60 | } else { 61 | startAngle = angle1; 62 | endAngle = angle2; 63 | } 64 | this.setCoordinates(PlotUtils.getArcPoints(center, radius, startAngle, endAngle)); 65 | } 66 | } 67 | 68 | /** 69 | * 设置地图对象 70 | * @param map 71 | */ 72 | setMap(map) { 73 | if (map && map instanceof Map) { 74 | this.map = map; 75 | } else { 76 | throw new Error('传入的不是地图对象!'); 77 | } 78 | } 79 | 80 | /** 81 | * 获取当前地图对象 82 | * @returns {ol.Map|*} 83 | */ 84 | getMap() { 85 | return this.map; 86 | } 87 | 88 | /** 89 | * 判断是否是Plot 90 | * @returns {boolean} 91 | */ 92 | isPlot() { 93 | return true; 94 | } 95 | 96 | /** 97 | * 设置坐标点 98 | * @param value 99 | */ 100 | setPoints(value) { 101 | this.points = !value ? [] : value; 102 | if (this.points.length >= 1) { 103 | this.generate(); 104 | } 105 | } 106 | 107 | /** 108 | * 获取坐标点 109 | * @returns {Array.} 110 | */ 111 | getPoints() { 112 | return this.points.slice(0); 113 | } 114 | 115 | /** 116 | * 获取点数量 117 | * @returns {Number} 118 | */ 119 | getPointCount() { 120 | return this.points.length; 121 | } 122 | 123 | /** 124 | * 更新当前坐标 125 | * @param point 126 | * @param index 127 | */ 128 | updatePoint(point, index) { 129 | if (index >= 0 && index < this.points.length) { 130 | this.points[index] = point; 131 | this.generate(); 132 | } 133 | } 134 | 135 | /** 136 | * 更新最后一个坐标 137 | * @param point 138 | */ 139 | updateLastPoint(point) { 140 | this.updatePoint(point, this.points.length - 1); 141 | } 142 | 143 | /** 144 | * 结束绘制 145 | */ 146 | finishDrawing() {} 147 | } 148 | 149 | export default Arc; 150 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Circle/Ellipse.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/22. 3 | * @desc 标绘画圆算法,继承面要素相关方法和属性 4 | */ 5 | import { Map } from 'ol'; 6 | import { Polygon } from 'ol/geom'; 7 | import type { Point as TPoint } from '@/utils/utils'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import * as Constants from '../../constants'; 10 | import * as PlotUtils from '../../utils/utils'; 11 | 12 | class Ellipse extends Polygon { 13 | type: PlotTypes; 14 | 15 | fixPointCount: number; 16 | 17 | map: any; 18 | 19 | points: TPoint[]; 20 | 21 | freehand: boolean; 22 | 23 | constructor(coordinates, points, params) { 24 | super([]); 25 | this.type = PlotTypes.ELLIPSE; 26 | this.fixPointCount = 2; 27 | this.set('params', params); 28 | if (points && points.length > 0) { 29 | this.setPoints(points); 30 | } else if (coordinates && coordinates.length > 0) { 31 | this.setCoordinates(coordinates); 32 | } 33 | } 34 | 35 | /** 36 | * 获取标绘类型 37 | * @returns {*} 38 | */ 39 | getPlotType() { 40 | return this.type; 41 | } 42 | 43 | generate() { 44 | if (this.getPointCount() < 2) { 45 | return false; 46 | } 47 | const [pnt1, pnt2] = [this.points[0], this.points[1]]; 48 | const center = PlotUtils.Mid(pnt1, pnt2); 49 | const majorRadius = Math.abs((pnt1[0] - pnt2[0]) / 2); 50 | const minorRadius = Math.abs((pnt1[1] - pnt2[1]) / 2); 51 | const res = this.generatePoints(center, majorRadius, minorRadius); 52 | this.setCoordinates([res]); 53 | } 54 | 55 | /** 56 | * 对圆边线进行插值 57 | * @param center 58 | * @param majorRadius 59 | * @param minorRadius 60 | * @returns {*} 61 | */ 62 | generatePoints(center, majorRadius, minorRadius) { 63 | // eslint-disable-next-line 64 | let [x, y, angle] = [0, 0, 0]; 65 | const points: TPoint[] = []; 66 | for (let i = 0; i <= Constants.FITTING_COUNT; i++) { 67 | angle = (Math.PI * 2 * i) / Constants.FITTING_COUNT; 68 | x = center[0] + majorRadius * Math.cos(angle); 69 | y = center[1] + minorRadius * Math.sin(angle); 70 | points.push([x, y]); 71 | } 72 | return points; 73 | } 74 | 75 | /** 76 | * 设置地图对象 77 | * @param map 78 | */ 79 | setMap(map) { 80 | if (map && map instanceof Map) { 81 | this.map = map; 82 | } else { 83 | throw new Error('传入的不是地图对象!'); 84 | } 85 | } 86 | 87 | /** 88 | * 获取当前地图对象 89 | * @returns {{}|*} 90 | */ 91 | getMap() { 92 | return this.map; 93 | } 94 | 95 | /** 96 | * 判断是否是Plot 97 | * @returns {boolean} 98 | */ 99 | isPlot() { 100 | return true; 101 | } 102 | 103 | /** 104 | * 设置坐标点 105 | * @param value 106 | */ 107 | setPoints(value) { 108 | this.points = !value ? [] : value; 109 | if (this.points.length >= 1) { 110 | this.generate(); 111 | } 112 | } 113 | 114 | /** 115 | * 获取坐标点 116 | * @returns {Array.} 117 | */ 118 | getPoints() { 119 | return this.points.slice(0); 120 | } 121 | 122 | /** 123 | * 获取点数量 124 | * @returns {Number} 125 | */ 126 | getPointCount() { 127 | return this.points.length; 128 | } 129 | 130 | /** 131 | * 更新当前坐标 132 | * @param point 133 | * @param index 134 | */ 135 | updatePoint(point, index) { 136 | if (index >= 0 && index < this.points.length) { 137 | this.points[index] = point; 138 | this.generate(); 139 | } 140 | } 141 | 142 | /** 143 | * 更新最后一个坐标 144 | * @param point 145 | */ 146 | updateLastPoint(point) { 147 | this.updatePoint(point, this.points.length - 1); 148 | } 149 | 150 | /** 151 | * 结束绘制 152 | */ 153 | finishDrawing() {} 154 | } 155 | 156 | export default Ellipse; 157 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polygon/Lune.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/24. 3 | * @desc 弓形 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import * as Constants from '@/constants'; 10 | import * as PlotUtils from '@/utils/utils'; 11 | import type { Point } from '@/utils/utils'; 12 | 13 | class Lune extends Polygon { 14 | type: PlotTypes; 15 | 16 | fixPointCount: WithUndef; 17 | 18 | map: any; 19 | 20 | points: Point[]; 21 | 22 | freehand: boolean; 23 | 24 | constructor(coordinates, points, params) { 25 | super([]); 26 | this.type = PlotTypes.LUNE; 27 | this.fixPointCount = 3; 28 | this.set('params', params); 29 | if (points && points.length > 0) { 30 | this.setPoints(points); 31 | } else if (coordinates && coordinates.length > 0) { 32 | this.setCoordinates(coordinates); 33 | } 34 | } 35 | 36 | /** 37 | * 获取标绘类型 38 | * @returns {*} 39 | */ 40 | getPlotType() { 41 | return this.type; 42 | } 43 | 44 | /** 45 | * 执行动作 46 | */ 47 | generate() { 48 | if (this.getPointCount() < 2) { 49 | return false; 50 | } 51 | let pnts = this.getPoints(); 52 | if (this.getPointCount() === 2) { 53 | const mid = PlotUtils.Mid(pnts[0], pnts[1]); 54 | const d = PlotUtils.MathDistance(pnts[0], mid); 55 | const pnt = PlotUtils.getThirdPoint(pnts[0], mid, Constants.HALF_PI, d); 56 | pnts.push(pnt); 57 | } 58 | // eslint-disable-next-line 59 | let [pnt1, pnt2, pnt3, startAngle, endAngle] = [pnts[0], pnts[1], pnts[2], 0, 0]; 60 | const center = PlotUtils.getCircleCenterOfThreePoints(pnt1, pnt2, pnt3); 61 | const radius = PlotUtils.MathDistance(pnt1, center); 62 | const angle1 = PlotUtils.getAzimuth(pnt1, center); 63 | const angle2 = PlotUtils.getAzimuth(pnt2, center); 64 | if (PlotUtils.isClockWise(pnt1, pnt2, pnt3)) { 65 | startAngle = angle2; 66 | endAngle = angle1; 67 | } else { 68 | startAngle = angle1; 69 | endAngle = angle2; 70 | } 71 | pnts = PlotUtils.getArcPoints(center, radius, startAngle, endAngle); 72 | pnts.push(pnts[0]); 73 | this.setCoordinates([pnts]); 74 | } 75 | 76 | /** 77 | * 设置地图对象 78 | * @param map 79 | */ 80 | setMap(map) { 81 | if (map && map instanceof Map) { 82 | this.map = map; 83 | } else { 84 | throw new Error('传入的不是地图对象!'); 85 | } 86 | } 87 | 88 | /** 89 | * 获取当前地图对象 90 | * @returns {Map|*} 91 | */ 92 | getMap() { 93 | return this.map; 94 | } 95 | 96 | /** 97 | * 判断是否是Plot 98 | * @returns {boolean} 99 | */ 100 | isPlot() { 101 | return true; 102 | } 103 | 104 | /** 105 | * 设置坐标点 106 | * @param value 107 | */ 108 | setPoints(value) { 109 | this.points = !value ? [] : value; 110 | if (this.points.length >= 1) { 111 | this.generate(); 112 | } 113 | } 114 | 115 | /** 116 | * 获取坐标点 117 | * @returns {Array.} 118 | */ 119 | getPoints() { 120 | return this.points.slice(0); 121 | } 122 | 123 | /** 124 | * 获取点数量 125 | * @returns {Number} 126 | */ 127 | getPointCount() { 128 | return this.points.length; 129 | } 130 | 131 | /** 132 | * 更新当前坐标 133 | * @param point 134 | * @param index 135 | */ 136 | updatePoint(point, index) { 137 | if (index >= 0 && index < this.points.length) { 138 | this.points[index] = point; 139 | this.generate(); 140 | } 141 | } 142 | 143 | /** 144 | * 更新最后一个坐标 145 | * @param point 146 | */ 147 | updateLastPoint(point) { 148 | this.updatePoint(point, this.points.length - 1); 149 | } 150 | 151 | /** 152 | * 结束绘制 153 | */ 154 | finishDrawing() {} 155 | } 156 | 157 | export default Lune; 158 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polygon/ClosedCurve.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/25. 3 | * @desc 闭合曲面 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import * as PlotUtils from '@/utils/utils'; 10 | import * as Constants from '@/constants'; 11 | import type { Point } from '@/utils/utils'; 12 | 13 | class ClosedCurve extends Polygon { 14 | type: PlotTypes; 15 | 16 | fixPointCount: WithUndef; 17 | 18 | map: any; 19 | 20 | points: Point[]; 21 | 22 | freehand: boolean; 23 | 24 | t: number; 25 | 26 | constructor(coordinates, points, params) { 27 | super([]); 28 | this.type = PlotTypes.CLOSED_CURVE; 29 | this.t = 0.3; 30 | this.set('params', params); 31 | if (points && points.length > 0) { 32 | this.setPoints(points); 33 | } else if (coordinates && coordinates.length > 0) { 34 | this.setCoordinates(coordinates); 35 | } 36 | } 37 | 38 | /** 39 | * 获取标绘类型 40 | * @returns {*} 41 | */ 42 | getPlotType() { 43 | return this.type; 44 | } 45 | 46 | /** 47 | * 执行动作 48 | */ 49 | generate() { 50 | const points = this.getPointCount(); 51 | if (points < 2) { 52 | return false; 53 | } 54 | if (points === 2) { 55 | this.setCoordinates([this.points]); 56 | } else { 57 | const pnts = this.getPoints(); 58 | pnts.push(pnts[0], pnts[1]); 59 | let normals: Point[] = []; 60 | const pList: Point[] = []; 61 | for (let i = 0; i < pnts.length - 2; i++) { 62 | const normalPoints = PlotUtils.getBisectorNormals(this.t, pnts[i], pnts[i + 1], pnts[i + 2]); 63 | normals = normals.concat(normalPoints); 64 | } 65 | const count = normals.length; 66 | normals = [normals[count - 1]].concat(normals.slice(0, count - 1)); 67 | for (let i = 0; i < pnts.length - 2; i++) { 68 | const pnt1 = pnts[i]; 69 | const pnt2 = pnts[i + 1]; 70 | pList.push(pnt1); 71 | for (let t = 0; t <= Constants.FITTING_COUNT; t++) { 72 | const pnt = PlotUtils.getCubicValue( 73 | t / Constants.FITTING_COUNT, 74 | pnt1, 75 | normals[i * 2], 76 | normals[i * 2 + 1], 77 | pnt2, 78 | ); 79 | pList.push(pnt); 80 | } 81 | pList.push(pnt2); 82 | } 83 | this.setCoordinates([pList]); 84 | } 85 | } 86 | 87 | /** 88 | * 设置地图对象 89 | * @param map 90 | */ 91 | setMap(map) { 92 | if (map && map instanceof Map) { 93 | this.map = map; 94 | } else { 95 | throw new Error('传入的不是地图对象!'); 96 | } 97 | } 98 | 99 | /** 100 | * 获取当前地图对象 101 | * @returns {Map|*} 102 | */ 103 | getMap() { 104 | return this.map; 105 | } 106 | 107 | /** 108 | * 判断是否是Plot 109 | * @returns {boolean} 110 | */ 111 | isPlot() { 112 | return true; 113 | } 114 | 115 | /** 116 | * 设置坐标点 117 | * @param value 118 | */ 119 | setPoints(value) { 120 | this.points = !value ? [] : value; 121 | if (this.points.length >= 1) { 122 | this.generate(); 123 | } 124 | } 125 | 126 | /** 127 | * 获取坐标点 128 | * @returns {Array.} 129 | */ 130 | getPoints() { 131 | return this.points.slice(0); 132 | } 133 | 134 | /** 135 | * 获取点数量 136 | * @returns {Number} 137 | */ 138 | getPointCount() { 139 | return this.points.length; 140 | } 141 | 142 | /** 143 | * 更新当前坐标 144 | * @param point 145 | * @param index 146 | */ 147 | updatePoint(point, index) { 148 | if (index >= 0 && index < this.points.length) { 149 | this.points[index] = point; 150 | this.generate(); 151 | } 152 | } 153 | 154 | /** 155 | * 更新最后一个坐标 156 | * @param point 157 | */ 158 | updateLastPoint(point) { 159 | this.updatePoint(point, this.points.length - 1); 160 | } 161 | 162 | /** 163 | * 结束绘制 164 | */ 165 | finishDrawing() {} 166 | } 167 | 168 | export default ClosedCurve; 169 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polygon/Rectinclined2.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by wh on 2023.6.1 3 | * @desc 斜矩形2 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon as $Polygon } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import type { Point } from '@/utils/utils'; 10 | 11 | class Rectinclined extends $Polygon { 12 | type: PlotTypes; 13 | 14 | fixPointCount: WithUndef; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | constructor(coordinates, points, params) { 23 | super([]); 24 | this.type = PlotTypes.RECTINCLINED2; 25 | this.fixPointCount = 3; 26 | this.set('params', params); 27 | if (points && points.length > 0) { 28 | this.setPoints(points); 29 | } else if (coordinates && coordinates.length > 0) { 30 | this.setCoordinates(coordinates); 31 | } 32 | } 33 | 34 | /** 35 | * 获取标绘类型 36 | * @returns {*} 37 | */ 38 | getPlotType() { 39 | return this.type; 40 | } 41 | 42 | /** 43 | * 执行动作 44 | */ 45 | generate() { 46 | const points = this.getPointCount(); 47 | if (points < 2) { 48 | return false; 49 | } 50 | if (points === 2) { 51 | this.setCoordinates([this.points]); 52 | } else { 53 | const pnts = this.getPoints(); 54 | const [pnt1, pnt2, mouse] = [pnts[0], pnts[1], pnts[2]]; 55 | const intersect = this.calculateIntersectionPoint(pnt1, pnt2, mouse); 56 | const pnt4 = this.calculateFourthPoint(pnt1, intersect, mouse); 57 | const pList: Point[] = []; 58 | pList.push(pnt1, intersect, mouse, pnt4, pnt1); 59 | this.setCoordinates([pList]); 60 | } 61 | } 62 | 63 | /** 64 | * 已知p1,p2,p3点求矩形的p4点 65 | * @param {*} p1 66 | * @param {*} p2 67 | * @param {*} p3 68 | */ 69 | calculateFourthPoint(p1, p2, p3): Point { 70 | const x = p1[0] + p3[0] - p2[0]; 71 | const y = p1[1] + p3[1] - p2[1]; 72 | return [x, y]; 73 | } 74 | 75 | /** 76 | * 已知p1点和p2点,求p3点到p1p2垂线的交点 77 | * @param {*} p1 78 | * @param {*} p2 79 | * @param {*} p3 80 | */ 81 | calculateIntersectionPoint(p1, p2, p3): Point { 82 | const v = { 83 | x: p2[0] - p1[0], 84 | y: p2[1] - p1[1], 85 | }; 86 | const u = { 87 | x: p3[0] - p1[0], 88 | y: p3[1] - p1[1], 89 | }; 90 | const projectionLength = (u.x * v.x + u.y * v.y) / (v.x * v.x + v.y * v.y); 91 | const intersectionPoint: { x: number; y: number } = { 92 | x: p1[0] + v.x * projectionLength, 93 | y: p1[1] + v.y * projectionLength, 94 | }; 95 | return [intersectionPoint.x, intersectionPoint.y]; 96 | } 97 | 98 | /** 99 | * 设置地图对象 100 | * @param map 101 | */ 102 | setMap(map) { 103 | if (map && map instanceof Map) { 104 | this.map = map; 105 | } else { 106 | throw new Error('传入的不是地图对象!'); 107 | } 108 | } 109 | 110 | /** 111 | * 获取当前地图对象 112 | * @returns {ol.Map|*} 113 | */ 114 | getMap() { 115 | return this.map; 116 | } 117 | 118 | /** 119 | * 判断是否是Plot 120 | * @returns {boolean} 121 | */ 122 | isPlot() { 123 | return true; 124 | } 125 | 126 | /** 127 | * 设置坐标点 128 | * @param value 129 | */ 130 | setPoints(value) { 131 | this.points = !value ? [] : value; 132 | if (this.points.length >= 1) { 133 | this.generate(); 134 | } 135 | } 136 | 137 | /** 138 | * 获取坐标点 139 | * @returns {Array.} 140 | */ 141 | getPoints() { 142 | return this.points.slice(0); 143 | } 144 | 145 | /** 146 | * 获取点数量 147 | * @returns {Number} 148 | */ 149 | getPointCount() { 150 | return this.points.length; 151 | } 152 | 153 | /** 154 | * 更新当前坐标 155 | * @param point 156 | * @param index 157 | */ 158 | updatePoint(point, index) { 159 | if (index >= 0 && index < this.points.length) { 160 | this.points[index] = point; 161 | this.generate(); 162 | } 163 | } 164 | 165 | /** 166 | * 更新最后一个坐标 167 | * @param point 168 | */ 169 | updateLastPoint(point) { 170 | this.updatePoint(point, this.points.length - 1); 171 | } 172 | 173 | /** 174 | * 结束绘制 175 | */ 176 | finishDrawing() {} 177 | } 178 | 179 | export default Rectinclined; 180 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Arrow/FineArrow.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/24. 3 | * @desc 粗单尖头箭头 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import * as PlotUtils from '@/utils/utils'; 10 | import * as Constants from '@/constants'; 11 | import type { Point } from '@/utils/utils'; 12 | 13 | class FineArrow extends Polygon { 14 | type: PlotTypes; 15 | 16 | fixPointCount: WithUndef; 17 | 18 | map: any; 19 | 20 | points: Point[]; 21 | 22 | freehand: boolean; 23 | 24 | neckAngle: number; 25 | 26 | headAngle: number; 27 | 28 | headWidthFactor: number; 29 | 30 | neckWidthFactor: number; 31 | 32 | tailWidthFactor: number; 33 | 34 | constructor(coordinates, points, params) { 35 | super([]); 36 | this.type = PlotTypes.FINE_ARROW; 37 | this.tailWidthFactor = 0.1; 38 | this.neckWidthFactor = 0.2; 39 | this.headWidthFactor = 0.25; 40 | this.headAngle = Math.PI / 8.5; 41 | this.neckAngle = Math.PI / 13; 42 | this.fixPointCount = 2; 43 | this.set('params', params); 44 | if (points && points.length > 0) { 45 | this.setPoints(points); 46 | } else if (coordinates && coordinates.length > 0) { 47 | this.setCoordinates(coordinates); 48 | } 49 | } 50 | 51 | /** 52 | * 获取标绘类型 53 | * @returns {*} 54 | */ 55 | getPlotType() { 56 | return this.type; 57 | } 58 | 59 | /** 60 | * 执行动作 61 | */ 62 | generate() { 63 | try { 64 | const cont = this.getPointCount(); 65 | if (cont < 2) { 66 | return false; 67 | } 68 | const pnts = this.getPoints(); 69 | const [pnt1, pnt2] = [pnts[0], pnts[1]]; 70 | const len = PlotUtils.getBaseLength(pnts); 71 | const tailWidth = len * this.tailWidthFactor; 72 | const neckWidth = len * this.neckWidthFactor; 73 | const headWidth = len * this.headWidthFactor; 74 | const tailLeft = PlotUtils.getThirdPoint(pnt2, pnt1, Constants.HALF_PI, tailWidth, true); 75 | const tailRight = PlotUtils.getThirdPoint(pnt2, pnt1, Constants.HALF_PI, tailWidth, false); 76 | const headLeft = PlotUtils.getThirdPoint(pnt1, pnt2, this.headAngle, headWidth, false); 77 | const headRight = PlotUtils.getThirdPoint(pnt1, pnt2, this.headAngle, headWidth, true); 78 | const neckLeft = PlotUtils.getThirdPoint(pnt1, pnt2, this.neckAngle, neckWidth, false); 79 | const neckRight = PlotUtils.getThirdPoint(pnt1, pnt2, this.neckAngle, neckWidth, true); 80 | const pList = [tailLeft, neckLeft, headLeft, pnt2, headRight, neckRight, tailRight]; 81 | this.setCoordinates([pList]); 82 | } catch (e) { 83 | console.log(e); 84 | } 85 | } 86 | 87 | /** 88 | * 设置地图对象 89 | * @param map 90 | */ 91 | setMap(map) { 92 | if (map && map instanceof Map) { 93 | this.map = map; 94 | } else { 95 | throw new Error('传入的不是地图对象!'); 96 | } 97 | } 98 | 99 | /** 100 | * 获取当前地图对象 101 | * @returns {Map|*} 102 | */ 103 | getMap() { 104 | return this.map; 105 | } 106 | 107 | /** 108 | * 判断是否是Plot 109 | * @returns {boolean} 110 | */ 111 | isPlot() { 112 | return true; 113 | } 114 | 115 | /** 116 | * 设置坐标点 117 | * @param value 118 | */ 119 | setPoints(value) { 120 | this.points = !value ? [] : value; 121 | if (this.points.length >= 1) { 122 | this.generate(); 123 | } 124 | } 125 | 126 | /** 127 | * 获取坐标点 128 | * @returns {Array.} 129 | */ 130 | getPoints() { 131 | return this.points.slice(0); 132 | } 133 | 134 | /** 135 | * 获取点数量 136 | * @returns {Number} 137 | */ 138 | getPointCount() { 139 | return this.points.length; 140 | } 141 | 142 | /** 143 | * 更新当前坐标 144 | * @param point 145 | * @param index 146 | */ 147 | updatePoint(point, index) { 148 | if (index >= 0 && index < this.points.length) { 149 | this.points[index] = point; 150 | this.generate(); 151 | } 152 | } 153 | 154 | /** 155 | * 更新最后一个坐标 156 | * @param point 157 | */ 158 | updateLastPoint(point) { 159 | this.updatePoint(point, this.points.length - 1); 160 | } 161 | 162 | /** 163 | * 结束绘制 164 | */ 165 | finishDrawing() {} 166 | } 167 | 168 | export default FineArrow; 169 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polygon/GatheringPlace.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/27. 3 | * @desc 集结地 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import * as PlotUtils from '@/utils/utils'; 10 | import * as Constants from '@/constants'; 11 | import type { Point } from '@/utils/utils'; 12 | 13 | class GatheringPlace extends Polygon { 14 | type: PlotTypes; 15 | 16 | fixPointCount: WithUndef; 17 | 18 | map: any; 19 | 20 | points: Point[]; 21 | 22 | freehand: boolean; 23 | 24 | t: number; 25 | 26 | constructor(coordinates, points, params) { 27 | super([]); 28 | this.type = PlotTypes.GATHERING_PLACE; 29 | this.t = 0.4; 30 | this.fixPointCount = 3; 31 | this.set('params', params); 32 | if (points && points.length > 0) { 33 | this.setPoints(points); 34 | } else if (coordinates && coordinates.length > 0) { 35 | this.setCoordinates(coordinates); 36 | } 37 | } 38 | 39 | /** 40 | * 获取标绘类型 41 | * @returns {*} 42 | */ 43 | getPlotType() { 44 | return this.type; 45 | } 46 | 47 | /** 48 | * 执行动作 49 | */ 50 | generate() { 51 | let pnts = this.getPoints(); 52 | const points = this.getPointCount(); 53 | if (pnts.length < 2) { 54 | return false; 55 | } 56 | if (points === 2) { 57 | const mid = PlotUtils.Mid(pnts[0], pnts[1]); 58 | const d = PlotUtils.MathDistance(pnts[0], mid) / 0.9; 59 | const pnt = PlotUtils.getThirdPoint(pnts[0], mid, Constants.HALF_PI, d, true); 60 | pnts = [pnts[0], pnt, pnts[1]]; 61 | } 62 | const mid = PlotUtils.Mid(pnts[0], pnts[2]); 63 | pnts.push(mid, pnts[0], pnts[1]); 64 | let normals: Point[] = []; 65 | let pnt1, pnt2, pnt3; 66 | const pList: Point[] = []; 67 | for (let i = 0; i < pnts.length - 2; i++) { 68 | pnt1 = pnts[i]; 69 | pnt2 = pnts[i + 1]; 70 | pnt3 = pnts[i + 2]; 71 | const normalPoints = PlotUtils.getBisectorNormals(this.t, pnt1, pnt2, pnt3); 72 | normals = normals.concat(normalPoints); 73 | } 74 | const count = normals.length; 75 | normals = [normals[count - 1]].concat(normals.slice(0, count - 1)); 76 | for (let i = 0; i < pnts.length - 2; i++) { 77 | pnt1 = pnts[i]; 78 | pnt2 = pnts[i + 1]; 79 | pList.push(pnt1); 80 | for (let t = 0; t <= Constants.FITTING_COUNT; t++) { 81 | const pnt = PlotUtils.getCubicValue( 82 | t / Constants.FITTING_COUNT, 83 | pnt1, 84 | normals[i * 2], 85 | normals[i * 2 + 1], 86 | pnt2, 87 | ); 88 | pList.push(pnt); 89 | } 90 | pList.push(pnt2); 91 | } 92 | this.setCoordinates([pList]); 93 | } 94 | 95 | /** 96 | * 设置地图对象 97 | * @param map 98 | */ 99 | setMap(map) { 100 | if (map && map instanceof Map) { 101 | this.map = map; 102 | } else { 103 | throw new Error('传入的不是地图对象!'); 104 | } 105 | } 106 | 107 | /** 108 | * 获取当前地图对象 109 | * @returns {Map|*} 110 | */ 111 | getMap() { 112 | return this.map; 113 | } 114 | 115 | /** 116 | * 判断是否是Plot 117 | * @returns {boolean} 118 | */ 119 | isPlot() { 120 | return true; 121 | } 122 | 123 | /** 124 | * 设置坐标点 125 | * @param value 126 | */ 127 | setPoints(value) { 128 | this.points = !value ? [] : value; 129 | if (this.points.length >= 1) { 130 | this.generate(); 131 | } 132 | } 133 | 134 | /** 135 | * 获取坐标点 136 | * @returns {Array.} 137 | */ 138 | getPoints() { 139 | return this.points.slice(0); 140 | } 141 | 142 | /** 143 | * 获取点数量 144 | * @returns {Number} 145 | */ 146 | getPointCount() { 147 | return this.points.length; 148 | } 149 | 150 | /** 151 | * 更新当前坐标 152 | * @param point 153 | * @param index 154 | */ 155 | updatePoint(point, index) { 156 | if (index >= 0 && index < this.points.length) { 157 | this.points[index] = point; 158 | this.generate(); 159 | } 160 | } 161 | 162 | /** 163 | * 更新最后一个坐标 164 | * @param point 165 | */ 166 | updateLastPoint(point) { 167 | this.updatePoint(point, this.points.length - 1); 168 | } 169 | 170 | /** 171 | * 结束绘制 172 | */ 173 | finishDrawing() {} 174 | } 175 | 176 | export default GatheringPlace; 177 | -------------------------------------------------------------------------------- /packages/ol-plot/src/less/index.less: -------------------------------------------------------------------------------- 1 | .plot-helper-control-point-div { 2 | width: 10px; 3 | height: 10px; 4 | border: 1px solid #000; 5 | border-radius: 100%; 6 | background-color: #ffffff; 7 | opacity: 0.6; 8 | cursor: move; 9 | } 10 | 11 | .ol-plot-text-editor { 12 | position: relative; 13 | textarea { 14 | resize: none; 15 | } 16 | &-close { 17 | position: absolute; 18 | top: -8px; 19 | right: -8px; 20 | display: none; 21 | width: 16px; 22 | height: 16px; 23 | border: 2px solid #585858; 24 | border-radius: 16px; 25 | box-sizing: border-box; 26 | background-color: #ffffff; 27 | &:before { 28 | position: absolute; 29 | bottom: 0px; 30 | left: 5px; 31 | content: ''; 32 | width: 2px; 33 | height: 100%; 34 | background-color: #585858; 35 | display: inline-block; 36 | transform: rotate(-45deg); 37 | } 38 | &:after { 39 | position: absolute; 40 | bottom: 0px; 41 | left: 5px; 42 | content: ''; 43 | width: 2px; 44 | height: 100%; 45 | background-color: #585858; 46 | display: inline-block; 47 | transform: rotate(45deg); 48 | } 49 | &:hover { 50 | cursor: pointer; 51 | border: 2px solid #1b9de8; 52 | &:before { 53 | background-color: #1b9de8; 54 | } 55 | &:after { 56 | background-color: #1b9de8; 57 | } 58 | } 59 | } 60 | &-resize { 61 | display: none; 62 | position: absolute; 63 | bottom: 4px; 64 | right: 0px; 65 | width: 14px; 66 | height: 14px; 67 | box-sizing: border-box; 68 | background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpENkUzQkZBOEY5Q0UxMUU3ODk3MjhBNDExQzVGQzdDMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpENkUzQkZBOUY5Q0UxMUU3ODk3MjhBNDExQzVGQzdDMyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQ2RTNCRkE2RjlDRTExRTc4OTcyOEE0MTFDNUZDN0MzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkQ2RTNCRkE3RjlDRTExRTc4OTcyOEE0MTFDNUZDN0MzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+naaIiwAAAIRJREFUeNpiYCAeOADxfyh2+P//PwMIMzFQCFhIUPsBiA8iscGAkVybQc4HAYq9gMuACUC8H4phwABJzICQwQeQQpy2sTDwgciC5LePQHwBKcD4oWxY3AsAsT6UfRE5LcAC5sCABCLIC47oyRMICqBORgYXkNRegMcCLDSpnRKJBgABBgB5djrWUPTZYwAAAABJRU5ErkJggg==") 0px 0px no-repeat; 69 | background-size: 100%; 70 | &:hover { 71 | cursor: pointer; 72 | border-color: #1b9de8; 73 | background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQyIDc5LjE2MDkyNCwgMjAxNy8wNy8xMy0wMTowNjozOSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozN0Y5MDFFMUY5Q0YxMUU3QkNEREEwRjQ4NjU5MjYxNiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozN0Y5MDFFMkY5Q0YxMUU3QkNEREEwRjQ4NjU5MjYxNiI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjM3RjkwMURGRjlDRjExRTdCQ0REQTBGNDg2NTkyNjE2IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjM3RjkwMUUwRjlDRjExRTdCQ0REQTBGNDg2NTkyNjE2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+FiWm3QAAAOtJREFUeNrMU0EOgjAQpLQHbnLRkPgI+YHwFA0P0JfIXROeov4AH0EgXtQbh5Z1t1IhRhMCHNxDd7LZbLczU2Z1DG+fB9xmR8KqgjCPvBNh2xoYomsjF/xuVer8xnWwvjcDwDgDvj5hfihiTAvCWeSFupZcfWRv93qPvcUz/c0BAx+PZbukpHJRhcBgUx+swh+QSA5DYYEzeGSrWWoIU8AmhIv1VGvvJjfXAamJLZm4YNJeENqeoGgkNWqS0DAxb0jUWzqy9I2VHSVJmZGsTB/j056WzTdtqfTawklxi9DgRvGajN4yDh3wFGAA+e1f3BQ3XV8AAAAASUVORK5CYII=") 0px 0px no-repeat; 74 | background-size: 100%; 75 | } 76 | } 77 | &:hover { 78 | .ol-plot-text-editor-close { 79 | display: inline-block; 80 | } 81 | .ol-plot-text-editor-resize { 82 | display: inline-block; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Flag/CurveFlag.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/9/13. 3 | * @desc 曲线旗标 4 | */ 5 | import { Map } from 'ol'; 6 | import { Polygon } from 'ol/geom'; 7 | import { PlotTypes } from '@/utils/PlotTypes'; 8 | import type { Point } from '@/utils/utils'; 9 | import { getBezierPoints } from '@/utils/utils'; 10 | 11 | class CurveFlag extends Polygon { 12 | type: PlotTypes; 13 | 14 | fixPointCount: WithUndef; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | constructor(coordinates, points, params) { 23 | super([]); 24 | this.type = PlotTypes.CURVEFLAG; 25 | this.fixPointCount = 2; 26 | this.set('params', params); 27 | if (points && points.length > 0) { 28 | this.setPoints(points); 29 | } else if (coordinates && coordinates.length > 0) { 30 | this.setCoordinates(coordinates); 31 | } 32 | } 33 | 34 | /** 35 | * 获取标绘类型 36 | * @returns {*} 37 | */ 38 | getPlotType() { 39 | return this.type; 40 | } 41 | 42 | /** 43 | * 执行动作 44 | */ 45 | generate() { 46 | const count = this.getPointCount(); 47 | if (count < 2) { 48 | return false; 49 | } 50 | this.setCoordinates([this.calculatePonits(this.points)]); 51 | } 52 | 53 | /** 54 | * 插值点数据 55 | * @param points 56 | * @returns {Array} 57 | */ 58 | calculatePonits(points) { 59 | let components: Point[] = []; 60 | // 至少需要两个控制点 61 | if (points.length > 1) { 62 | // 取第一个 63 | const startPoint = points[0]; 64 | // 取最后一个 65 | const endPoint = points[points.length - 1]; 66 | // 上曲线起始点 67 | const point1 = startPoint; 68 | // 上曲线第一控制点 69 | const point2 = [ 70 | (endPoint[0] - startPoint[0]) / 4 + startPoint[0], 71 | (endPoint[1] - startPoint[1]) / 8 + startPoint[1], 72 | ]; 73 | // 上曲线第二个点 74 | const point3 = [(startPoint[0] + endPoint[0]) / 2, startPoint[1]]; 75 | // 上曲线第二控制点 76 | const point4 = [ 77 | ((endPoint[0] - startPoint[0]) * 3) / 4 + startPoint[0], 78 | -(endPoint[1] - startPoint[1]) / 8 + startPoint[1], 79 | ]; 80 | // 上曲线结束点 81 | const point5 = [endPoint[0], startPoint[1]]; 82 | // 下曲线结束点 83 | const point6 = [endPoint[0], (startPoint[1] + endPoint[1]) / 2]; 84 | // 下曲线第二控制点 85 | const point7 = [ 86 | ((endPoint[0] - startPoint[0]) * 3) / 4 + startPoint[0], 87 | ((endPoint[1] - startPoint[1]) * 3) / 8 + startPoint[1], 88 | ]; 89 | // 下曲线第二个点 90 | const point8 = [(startPoint[0] + endPoint[0]) / 2, (startPoint[1] + endPoint[1]) / 2]; 91 | // 下曲线第一控制点 92 | const point9 = [ 93 | (endPoint[0] - startPoint[0]) / 4 + startPoint[0], 94 | ((endPoint[1] - startPoint[1]) * 5) / 8 + startPoint[1], 95 | ]; 96 | // 下曲线起始点 97 | const point10 = [startPoint[0], (startPoint[1] + endPoint[1]) / 2]; 98 | // 旗杆底部点 99 | const point11: Point = [startPoint[0], endPoint[1]]; 100 | // 计算上曲线 101 | const curve1 = getBezierPoints([point1, point2, point3, point4, point5]); 102 | // 计算下曲线 103 | const curve2 = getBezierPoints([point6, point7, point8, point9, point10] as Point[]); 104 | // 合并 105 | components = curve1.concat(curve2); 106 | components.push(point11); 107 | } 108 | return components; 109 | } 110 | 111 | /** 112 | * 设置地图对象 113 | * @param map 114 | */ 115 | setMap(map) { 116 | if (map && map instanceof Map) { 117 | this.map = map; 118 | } else { 119 | throw new Error('传入的不是地图对象!'); 120 | } 121 | } 122 | 123 | /** 124 | * 获取当前地图对象 125 | * @returns {Map|*} 126 | */ 127 | getMap() { 128 | return this.map; 129 | } 130 | 131 | /** 132 | * 判断是否是Plot 133 | * @returns {boolean} 134 | */ 135 | isPlot() { 136 | return true; 137 | } 138 | 139 | /** 140 | * 设置坐标点 141 | * @param value 142 | */ 143 | setPoints(value) { 144 | this.points = !value ? [] : value; 145 | if (this.points.length >= 1) { 146 | this.generate(); 147 | } 148 | } 149 | 150 | /** 151 | * 获取坐标点 152 | * @returns {Array.} 153 | */ 154 | getPoints() { 155 | return this.points.slice(0); 156 | } 157 | 158 | /** 159 | * 获取点数量 160 | * @returns {Number} 161 | */ 162 | getPointCount() { 163 | return this.points.length; 164 | } 165 | 166 | /** 167 | * 更新当前坐标 168 | * @param point 169 | * @param index 170 | */ 171 | updatePoint(point, index) { 172 | if (index >= 0 && index < this.points.length) { 173 | this.points[index] = point; 174 | this.generate(); 175 | } 176 | } 177 | 178 | /** 179 | * 更新最后一个坐标 180 | * @param point 181 | */ 182 | updateLastPoint(point) { 183 | this.updatePoint(point, this.points.length - 1); 184 | } 185 | 186 | /** 187 | * 结束绘制 188 | */ 189 | finishDrawing() {} 190 | } 191 | 192 | export default CurveFlag; 193 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master, dev] 6 | pull_request: 7 | branches: [master, dev] 8 | 9 | jobs: 10 | test: 11 | if: "!contains(github.event.head_commit.message, 'ci skip')" 12 | 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest] 16 | node-version: [18.x] 17 | 18 | runs-on: ${{ matrix.os }} 19 | 20 | # Steps represent a sequence of tasks that will be executed as part of the job 21 | steps: 22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 23 | - uses: actions/checkout@v3 24 | 25 | - uses: actions/setup-node@v3 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | 29 | - name: Cache ~/.pnpm-store 30 | uses: actions/cache@v2 31 | env: 32 | cache-name: cache-pnpm-store 33 | with: 34 | path: ~/.pnpm-store 35 | key: ${{ runner.os }}-${{ matrix.node-version }}-test-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }} 36 | restore-keys: | 37 | ${{ runner.os }}-${{ matrix.node-version }}-test-${{ env.cache-name }}- 38 | ${{ runner.os }}-${{ matrix.node-version }}-test- 39 | ${{ runner.os }}- 40 | - name: Install pnpm 41 | run: npm i -g pnpm@8.6.5 42 | 43 | - name: Install deps 44 | run: pnpm i 45 | 46 | # Runs a set of commands using the runners shell 47 | - name: Build and Test 48 | run: pnpm test && pnpm coverage 49 | # - name: Coveralls 50 | # uses: coverallsapp/github-action@master 51 | # with: 52 | # # https://github.com/coverallsapp/github-action/issues/81 53 | # # https://docs.github.com/en/actions/security-guides/automatic-token-authentication 54 | # git-branch: master 55 | # github-token: ${{ secrets.GITHUB_TOKEN }} 56 | # flag-name: ${{matrix.os}}-node-${{ matrix.node }} 57 | # parallel: true 58 | 59 | release: 60 | runs-on: ubuntu-latest 61 | needs: ['test'] 62 | if: "!contains(github.event.head_commit.message, 'skip-release') && !contains(github.event.head_commit.message, 'skip-ci') && github.event_name != 'pull_request'" 63 | steps: 64 | - uses: actions/checkout@v3 65 | - uses: actions/setup-node@v3 66 | with: 67 | node-version: 18.x 68 | - name: Cache ~/.pnpm-store 69 | uses: actions/cache@v3 70 | env: 71 | cache-name: cache-pnpm-store 72 | with: 73 | path: ~/.pnpm-store 74 | key: ${{ runner.os }}-${{ matrix.node-version }}-release-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }} 75 | restore-keys: | 76 | ${{ runner.os }}-${{ matrix.node-version }}-release-${{ env.cache-name }}- 77 | ${{ runner.os }}-${{ matrix.node-version }}-release- 78 | ${{ runner.os }}- 79 | - run: npm i -g pnpm@8.6.5 80 | - run: pnpm i 81 | 82 | - name: Create Release Pull Request or Publish to npm 83 | id: changesets 84 | uses: changesets/action@master 85 | with: 86 | # This expects you to have a script called release which does a build for your packages and calls changeset publish 87 | publish: pnpm release 88 | commit: 'chore(release): publish' 89 | title: Publish next versions 90 | env: 91 | GITHUB_TOKEN: ${{ secrets.PKG_DEPLOY_TOKEN }} 92 | NPM_TOKEN: ${{ secrets.NPM_PKG_PUBLIC_TOKEN }} 93 | 94 | docs: 95 | runs-on: ubuntu-latest 96 | needs: [ 'test' ] 97 | if: "!contains(github.event.head_commit.message, 'skip-release') && !contains(github.event.head_commit.message, 'skip-ci') && github.event_name != 'pull_request'" 98 | steps: 99 | - uses: actions/checkout@v3 100 | - uses: actions/setup-node@v3 101 | with: 102 | node-version: 18.x 103 | - name: Cache ~/.pnpm-store 104 | uses: actions/cache@v3 105 | env: 106 | cache-name: cache-pnpm-store 107 | with: 108 | path: ~/.pnpm-store 109 | key: ${{ runner.os }}-${{ matrix.node-version }}-release-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }} 110 | restore-keys: | 111 | ${{ runner.os }}-${{ matrix.node-version }}-release-${{ env.cache-name }}- 112 | ${{ runner.os }}-${{ matrix.node-version }}-release- 113 | ${{ runner.os }}- 114 | - run: npm i -g pnpm@8.6.5 115 | - run: pnpm i 116 | - run: pnpm --filter "./packages/ol-plot-vue" build:vue3 && pnpm --filter "./packages/**" build 117 | # ??? 118 | - run: pnpm i 119 | - run: pnpm --filter "./playground/vue3" build 120 | 121 | - name: Deploy 122 | uses: peaceiris/actions-gh-pages@v3 123 | with: 124 | github_token: ${{ secrets.PKG_DEPLOY_TOKEN }} 125 | publish_dir: playground/vue3/dist 126 | cname: blog.sakitam.com 127 | -------------------------------------------------------------------------------- /packages/ol-plot/README.md: -------------------------------------------------------------------------------- 1 | # openlayers 扩展标绘 2 | 3 | [![CI](https://github.com/sakitam-fdd/ol-plot/actions/workflows/ci.yml/badge.svg)](https://github.com/sakitam-fdd/ol-plot/actions/workflows/ci.yml) 4 | [![npm version](https://badgen.net/npm/v/ol-plot)](https://npm.im/ol-plot) 5 | [![npm downloads](https://badgen.net/npm/dm/ol-plot)](https://npm.im/ol-plot) 6 | ![JS gzip size](http://img.badgesize.io/https://unpkg.com/ol-plot/dist/ol-plot.js?compression=gzip&label=gzip%20size:%20JS) 7 | [![GitHub stars](https://img.shields.io/github/stars/sakitam-fdd/ol-plot.svg)](https://github.com/sakitam-fdd/ol-plot/stargazers) 8 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/sakitam-fdd/ol-plot/master/LICENSE) 9 | 10 | 标绘功能,支持openlayers5 / 6 / 7;同时也实现了一个简单的 Vue 组件,请查看 `playground/vue3` 使用,npm 发布的包为 [![npm version](https://badgen.net/npm/v/ol-plot-vue)](https://npm.im/ol-plot-vue) 11 | 12 | ## build 13 | 14 | > 重要: 如果想要使用 Github 上最新的源码,你需要自己构建。 15 | 16 | --- 17 | 18 | ```bash 19 | git clone https://github.com/sakitam-fdd/ol-plot.git 20 | pnpm run dev 21 | pnpm run build 22 | ``` 23 | 24 | ## Use 25 | 26 | > `new olPlot.(map) 初始化标绘绘制工具` 27 | 28 | ### CDN 29 | 30 | ```bash 31 | https://unpkg.com/ol-plot/dist/ol-plot.js 32 | https://unpkg.com/ol-plot/dist/ol-plot.css 33 | ``` 34 | 35 | ### NPM 36 | 37 | ```bash 38 | npm install ol-plot --save 39 | import 'ol-plot/dist/ol-plot.css' 40 | import Plot form 'ol-plot' 41 | ``` 42 | 43 | ## Examples 44 | 45 | [![site](https://github.com/sakitam-fdd/ol-plot/blob/master/playground/vue3/public/image/plot.png?raw=true)](https://sakitam-fdd.github.io/ol-plot) 46 | 47 | [![demo](https://raw.githubusercontent.com/sakitam-fdd/ol-plot/V1.0.0/examples/images/demo.png)](https://codepen.io/sakitam-fdd/pen/QMQydz) 48 | 49 | 其他示例请参看 playground 文件夹 50 | 51 | ## 实例方法 52 | 53 | ### plotDraw Methods 54 | 55 | #### `activate(type, params)` 56 | 57 | > 激活标绘工具 58 | 59 | | key | type | desc | 60 | |:---------|:---------|:-------| 61 | | `type` | `string` | 标绘符号类型 | 62 | | `params` | `Object` | 标绘符号参数 | 63 | 64 | ##### `type` 65 | 66 | > 标绘类型 67 | 68 | ###### type: 69 | 70 | | key | type | desc | 71 | | :---------------------- | :--- |:----------| 72 | | `olPlot.PlotTypes.ARC` | `string` | 弓形 | 73 | | `olPlot.PlotTypes.ELLIPSE` | `string` | 椭圆 | 74 | | `olPlot.PlotTypes.CURVE` | `string` | 曲线 | 75 | | `olPlot.PlotTypes.CLOSED_CURVE` | `string` | 闭合曲面 | 76 | | `olPlot.PlotTypes.LUNE` | `string` | 弓形 | 77 | | `olPlot.PlotTypes.SECTOR` | `string` | 扇形 | 78 | | `olPlot.PlotTypes.GATHERING_PLACE` | `string` | 集结地 | 79 | | `olPlot.PlotTypes.STRAIGHT_ARROW` | `string` | 细直箭头 | 80 | | `olPlot.PlotTypes.ASSAULT_DIRECTION` | `string` | 粗单直箭头 | 81 | | `olPlot.PlotTypes.ATTACK_ARROW` | `string` | 进攻方向 | 82 | | `olPlot.PlotTypes.TAILED_ATTACK_ARROW` | `string` | 进攻方向(尾) | 83 | | `olPlot.PlotTypes.SQUAD_COMBAT` | `string` | 战斗行动 | 84 | | `olPlot.PlotTypes.TAILED_SQUAD_COMBAT` | `string` | 分队战斗行动(尾) | 85 | | `olPlot.PlotTypes.FINE_ARROW` | `string` | 粗单尖头箭头 | 86 | | `olPlot.PlotTypes.CIRCLE` | `string` | 圆 | 87 | | `olPlot.PlotTypes.DOUBLE_ARROW` | `string` | 双箭头 | 88 | | `olPlot.PlotTypes.POLYLINE` | `string` | 线 | 89 | | `olPlot.PlotTypes.FREEHAND_LINE` | `string` | 自由线 | 90 | | `olPlot.PlotTypes.POLYGON` | `string` | 面 | 91 | | `olPlot.PlotTypes.FREEHAND_POLYGON` | `string` | 自由面 | 92 | | `olPlot.PlotTypes.RECTANGLE` | `string` | 矩形 | 93 | | `olPlot.PlotTypes.RectInclined1` | `string` | 斜矩形1 | 94 | | `olPlot.PlotTypes.RectInclined2` | `string` | 斜矩形2 | 95 | | `olPlot.PlotTypes.MARKER` | `string` | 点 | 96 | | `olPlot.PlotTypes.TEXTAREA` | `string` | 文本框 | 97 | 98 | #### `deactivate()` 99 | 100 | 取消绘制工具的激活状态 101 | 102 | ### plotEdit Methods 103 | 104 | #### `activate(feature)` 105 | 106 | | key | type | desc | 107 | | :--- | :--- | :---------- | 108 | | `feature` | `ol.Feature` | 要激活的标绘符号 | 109 | 110 | 激活符号要素编辑 111 | 112 | #### `deactivate()` 113 | 114 | 取消符号要素编辑状态 115 | 116 | ### PlotUtils Methods 117 | 118 | | 方法 | 说明 | 参数 | 119 | | :--- | :--- | :---------- | 120 | | `getFeatures` | 序列化地图上所有符号 | -- | 121 | | `addFeatures` | 反序列化保存的符号 | `features : Array` | 122 | | `removeAllFeatures` | 删除所有符号 | -- | 123 | 124 | 125 | ## 事件 126 | 127 | ### plotDraw 128 | 129 | ```js 130 | plot.plotDraw.on('drawStart', (e) => { 131 | console.log(e); 132 | }); 133 | 134 | plot.plotDraw.on('drawEnd', onDrawEnd); 135 | ``` 136 | 137 | #### drawStart 138 | 139 | 监听符号开始绘制,通过事件类型 ``plotType`` 判断是哪种标绘类型 140 | 141 | #### drawEnd 142 | 143 | 监听符号结束绘制,通过事件类型 ``plotType`` 判断是哪种标绘类型 144 | 145 | ### plotEdit 146 | 147 | ```js 148 | plot.plotEdit.on('activePlotChange', (e) => { 149 | console.log(e); 150 | }); 151 | 152 | plot.plotEdit.on('deactivatePlot', (e) => { 153 | console.log(e); 154 | }); 155 | ``` 156 | 157 | #### activePlotChange 158 | 159 | 激活编辑状态的要素变化事件 160 | 161 | #### deactivatePlot 162 | 163 | 监听要素结束编辑状态 164 | 165 | ### plot 实例事件 166 | 167 | 比较特殊,3.0 版本是绑定在 map 实例上的,从 4.0 版本起需要绑定在 plot 实例上。 168 | 169 | ```js 170 | plot.on('activeTextArea', (e) => { 171 | console.log(e); 172 | }); 173 | 174 | plot.on('deactivateTextArea', (e) => { 175 | console.log(e); 176 | }); 177 | ``` 178 | 179 | #### activeTextArea 180 | 181 | 激活文本框编辑事件 182 | 183 | #### deactivateTextArea 184 | 185 | 取消激活文本框编辑事件 186 | -------------------------------------------------------------------------------- /packages/ol-plot/src/utils/domUtils.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-param-reassign */ 2 | /* eslint no-useless-escape: "off" */ 3 | 4 | const SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; 5 | const MOZ_HACK_REGEXP = /^moz([A-Z])/; 6 | 7 | export const create = function (tagName: string, className?: string, container?: HTMLElement, id?: string) { 8 | const el = document.createElement(tagName); 9 | el.className = className || ''; 10 | if (id) { 11 | el.id = id; 12 | } 13 | if (container) { 14 | container.appendChild(el); 15 | } 16 | return el; 17 | }; 18 | 19 | export const getElement = function (id: string) { 20 | return typeof id === 'string' ? document.getElementById(id) : id; 21 | }; 22 | 23 | export const remove = function (el: HTMLElement, p?: HTMLElement) { 24 | const parent = el.parentNode; 25 | if (parent) { 26 | parent.removeChild(el); 27 | } 28 | }; 29 | 30 | export const empty = function (el: HTMLElement) { 31 | while (el.firstChild) { 32 | el.removeChild(el.firstChild); 33 | } 34 | }; 35 | 36 | export const createHidden = function (tagName: string, parent: HTMLElement, id: string) { 37 | const element = document.createElement(tagName); 38 | element.style.display = 'none'; 39 | if (id) { 40 | element.id = id; 41 | } 42 | if (parent) { 43 | parent.appendChild(element); 44 | } 45 | return element; 46 | }; 47 | 48 | const trim = function (string: string) { 49 | return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, ''); 50 | }; 51 | 52 | const camelCase = function (name: string) { 53 | return name 54 | .replace(SPECIAL_CHARS_REGEXP, (_, separator, letter, offset) => (offset ? letter.toUpperCase() : letter)) 55 | .replace(MOZ_HACK_REGEXP, 'Moz$1'); 56 | }; 57 | 58 | type eventFn = (element: HTMLElement, event: string, handler: any) => void; 59 | 60 | export const on = (function () { 61 | if (document) { 62 | return function (element: HTMLElement, event: string, handler: any) { 63 | if (element && event && handler) { 64 | element.addEventListener(event, handler, false); 65 | } 66 | }; 67 | } 68 | })() as eventFn; 69 | 70 | export const off = (function () { 71 | if (document) { 72 | return function (element: HTMLElement, event: string, handler: any) { 73 | if (element && event) { 74 | element.removeEventListener(event, handler, false); 75 | } 76 | }; 77 | } 78 | })() as eventFn; 79 | 80 | export const once = function (el: HTMLElement, event: string, fn: any) { 81 | const listener = function (...args) { 82 | if (fn) { 83 | fn.apply(this, args); 84 | } 85 | off(el, event, listener); 86 | }; 87 | on(el, event, listener); 88 | }; 89 | 90 | export function hasClass(el: HTMLElement, cls: string) { 91 | if (!el || !cls) return false; 92 | if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.'); 93 | if (el.classList) { 94 | return el.classList.contains(cls); 95 | } 96 | return ` ${el.className} `.indexOf(` ${cls} `) > -1; 97 | } 98 | 99 | export function addClass(el: HTMLElement, cls: string) { 100 | if (!el) return; 101 | let curClass = el.className; 102 | const classes = (cls || '').split(' '); 103 | for (let i = 0, j = classes.length; i < j; i++) { 104 | const clsName = classes[i]; 105 | if (!clsName) continue; 106 | if (el.classList) { 107 | el.classList.add(clsName); 108 | } else if (!hasClass(el, clsName)) { 109 | curClass += ` ${clsName}`; 110 | } 111 | } 112 | if (!el.classList) { 113 | el.className = curClass; 114 | } 115 | } 116 | 117 | export function removeClass(el: HTMLElement, cls: string) { 118 | if (!el || !cls) return; 119 | const classes = cls.split(' '); 120 | let curClass = ` ${el.className} `; 121 | for (let i = 0, j = classes.length; i < j; i++) { 122 | const clsName = classes[i]; 123 | if (!clsName) continue; 124 | if (el.classList) { 125 | el.classList.remove(clsName); 126 | } else if (hasClass(el, clsName)) { 127 | curClass = curClass.replace(` ${clsName} `, ' '); 128 | } 129 | } 130 | if (!el.classList) { 131 | el.className = trim(curClass); 132 | } 133 | } 134 | 135 | export function getStyle(element: HTMLElement, styleName: string) { 136 | if (!element || !styleName) return null; 137 | styleName = camelCase(styleName); 138 | if (styleName === 'float') { 139 | styleName = 'cssFloat'; 140 | } 141 | try { 142 | const computed = document.defaultView?.getComputedStyle(element, ''); 143 | return element.style[styleName] || computed ? computed?.[styleName] : null; 144 | } catch (e) { 145 | return element.style[styleName]; 146 | } 147 | } 148 | 149 | export function setStyle(element: HTMLElement, styleName: string | Object, value: any) { 150 | if (!element || !styleName) return; 151 | if (typeof styleName === 'object') { 152 | // eslint-disable-next-line no-restricted-syntax 153 | for (const prop in styleName) { 154 | if (styleName.hasOwnProperty(prop)) { 155 | setStyle(element, prop, styleName[prop]); 156 | } 157 | } 158 | } else { 159 | styleName = camelCase(styleName) as string; 160 | if (styleName === 'opacity') { 161 | // eslint-disable-next-line no-restricted-globals 162 | element.style.filter = isNaN(value) ? '' : `alpha(opacity=${value * 100})`; 163 | } else { 164 | element.style[styleName as string] = value; 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # openlayers 扩展标绘 2 | 3 | [![CI](https://github.com/sakitam-fdd/ol-plot/actions/workflows/ci.yml/badge.svg)](https://github.com/sakitam-fdd/ol-plot/actions/workflows/ci.yml) 4 | [![npm version](https://badgen.net/npm/v/ol-plot)](https://npm.im/ol-plot) 5 | [![npm downloads](https://badgen.net/npm/dm/ol-plot)](https://npm.im/ol-plot) 6 | ![JS gzip size](http://img.badgesize.io/https://unpkg.com/ol-plot/dist/ol-plot.js?compression=gzip&label=gzip%20size:%20JS) 7 | [![GitHub stars](https://img.shields.io/github/stars/sakitam-fdd/ol-plot.svg)](https://github.com/sakitam-fdd/ol-plot/stargazers) 8 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/sakitam-fdd/ol-plot/master/LICENSE) 9 | 10 | 标绘功能,支持openlayers5 / 6 / 7;同时也实现了一个简单的 Vue 组件,请查看 `playground/vue3` 使用,npm 发布的包为 [![npm version](https://badgen.net/npm/v/ol-plot-vue)](https://npm.im/ol-plot-vue) 11 | 12 | ## build 13 | 14 | > 重要: 如果想要使用 Github 上最新的源码,你需要自己构建。 15 | 16 | --- 17 | 18 | ```bash 19 | git clone https://github.com/sakitam-fdd/ol-plot.git 20 | pnpm run dev 21 | pnpm run build 22 | ``` 23 | 24 | ## Use 25 | 26 | > `new olPlot.(map) 初始化标绘绘制工具` 27 | 28 | ### CDN 29 | 30 | ```bash 31 | https://unpkg.com/ol-plot/dist/ol-plot.js 32 | https://unpkg.com/ol-plot/dist/ol-plot.css 33 | ``` 34 | 35 | ### NPM 36 | 37 | ```bash 38 | npm install ol-plot --save 39 | import 'ol-plot/dist/ol-plot.css' 40 | import Plot form 'ol-plot' 41 | ``` 42 | 43 | ## Examples 44 | 45 | [![site](https://github.com/sakitam-fdd/ol-plot/blob/master/playground/vue3/public/image/plot.png?raw=true)](https://sakitam-fdd.github.io/ol-plot) 46 | 47 | [![demo](https://raw.githubusercontent.com/sakitam-fdd/ol-plot/V1.0.0/examples/images/demo.png)](https://codepen.io/sakitam-fdd/pen/QMQydz) 48 | 49 | 其他示例请参看 playground 文件夹 50 | 51 | ## 实例方法 52 | 53 | ### plotDraw Methods 54 | 55 | #### `activate(type, params)` 56 | 57 | > 激活标绘工具 58 | 59 | | key | type | desc | 60 | |:---------|:---------|:-------| 61 | | `type` | `string` | 标绘符号类型 | 62 | | `params` | `Object` | 标绘符号参数 | 63 | 64 | ##### `type` 65 | 66 | > 标绘类型 67 | 68 | ###### type: 69 | 70 | | key | type | desc | 71 | |:---------------------------------------| :--- |:----------| 72 | | `olPlot.PlotTypes.ARC` | `string` | 弓形 | 73 | | `olPlot.PlotTypes.ELLIPSE` | `string` | 椭圆 | 74 | | `olPlot.PlotTypes.CURVE` | `string` | 曲线 | 75 | | `olPlot.PlotTypes.CLOSED_CURVE` | `string` | 闭合曲面 | 76 | | `olPlot.PlotTypes.LUNE` | `string` | 弓形 | 77 | | `olPlot.PlotTypes.SECTOR` | `string` | 扇形 | 78 | | `olPlot.PlotTypes.GATHERING_PLACE` | `string` | 集结地 | 79 | | `olPlot.PlotTypes.STRAIGHT_ARROW` | `string` | 细直箭头 | 80 | | `olPlot.PlotTypes.ASSAULT_DIRECTION` | `string` | 粗单直箭头 | 81 | | `olPlot.PlotTypes.ATTACK_ARROW` | `string` | 进攻方向 | 82 | | `olPlot.PlotTypes.TAILED_ATTACK_ARROW` | `string` | 进攻方向(尾) | 83 | | `olPlot.PlotTypes.SQUAD_COMBAT` | `string` | 战斗行动 | 84 | | `olPlot.PlotTypes.TAILED_SQUAD_COMBAT` | `string` | 分队战斗行动(尾) | 85 | | `olPlot.PlotTypes.FINE_ARROW` | `string` | 粗单尖头箭头 | 86 | | `olPlot.PlotTypes.CIRCLE` | `string` | 圆 | 87 | | `olPlot.PlotTypes.DOUBLE_ARROW` | `string` | 双箭头 | 88 | | `olPlot.PlotTypes.POLYLINE` | `string` | 线 | 89 | | `olPlot.PlotTypes.FREEHAND_LINE` | `string` | 自由线 | 90 | | `olPlot.PlotTypes.POLYGON` | `string` | 面 | 91 | | `olPlot.PlotTypes.FREEHAND_POLYGON` | `string` | 自由面 | 92 | | `olPlot.PlotTypes.RECTANGLE` | `string` | 矩形 | 93 | | `olPlot.PlotTypes.RectInclined1` | `string` | 斜矩形1 | 94 | | `olPlot.PlotTypes.RectInclined2` | `string` | 斜矩形2 | 95 | | `olPlot.PlotTypes.MARKER` | `string` | 点 | 96 | | `olPlot.PlotTypes.TEXTAREA` | `string` | 文本框 | 97 | 98 | #### `deactivate()` 99 | 100 | 取消绘制工具的激活状态 101 | 102 | ### plotEdit Methods 103 | 104 | #### `activate(feature)` 105 | 106 | | key | type | desc | 107 | | :--- | :--- | :---------- | 108 | | `feature` | `ol.Feature` | 要激活的标绘符号 | 109 | 110 | 激活符号要素编辑 111 | 112 | #### `deactivate()` 113 | 114 | 取消符号要素编辑状态 115 | 116 | ### PlotUtils Methods 117 | 118 | | 方法 | 说明 | 参数 | 119 | | :--- | :--- | :---------- | 120 | | `getFeatures` | 序列化地图上所有符号 | -- | 121 | | `addFeatures` | 反序列化保存的符号 | `features : Array` | 122 | | `removeAllFeatures` | 删除所有符号 | -- | 123 | 124 | 125 | ## 事件 126 | 127 | ### plotDraw 128 | 129 | ```js 130 | plot.plotDraw.on('drawStart', (e) => { 131 | console.log(e); 132 | }); 133 | 134 | plot.plotDraw.on('drawEnd', onDrawEnd); 135 | ``` 136 | 137 | #### drawStart 138 | 139 | 监听符号开始绘制,通过事件类型 ``plotType`` 判断是哪种标绘类型 140 | 141 | #### drawEnd 142 | 143 | 监听符号结束绘制,通过事件类型 ``plotType`` 判断是哪种标绘类型 144 | 145 | ### plotEdit 146 | 147 | ```js 148 | plot.plotEdit.on('activePlotChange', (e) => { 149 | console.log(e); 150 | }); 151 | 152 | plot.plotEdit.on('deactivatePlot', (e) => { 153 | console.log(e); 154 | }); 155 | ``` 156 | 157 | #### activePlotChange 158 | 159 | 激活编辑状态的要素变化事件 160 | 161 | #### deactivatePlot 162 | 163 | 监听要素结束编辑状态 164 | 165 | ### plot 实例事件 166 | 167 | 比较特殊,3.0 版本是绑定在 map 实例上的,从 4.0 版本起需要绑定在 plot 实例上。 168 | 169 | ```js 170 | plot.on('activeTextArea', (e) => { 171 | console.log(e); 172 | }); 173 | 174 | plot.on('deactivateTextArea', (e) => { 175 | console.log(e); 176 | }); 177 | ``` 178 | 179 | #### activeTextArea 180 | 181 | 激活文本框编辑事件 182 | 183 | #### deactivateTextArea 184 | 185 | 取消激活文本框编辑事件 186 | -------------------------------------------------------------------------------- /playground/single/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 军事标绘(ol3-4) 12 | 109 | 110 | 111 |
112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 |
148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /packages/ol-plot/src/geometry/Polygon/Rectinclined1.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by wh on 2023.6.1 3 | * @desc 斜矩形1 4 | * @Inherits ol.geom.Polygon 5 | */ 6 | import { Map } from 'ol'; 7 | import { Polygon as $Polygon } from 'ol/geom'; 8 | import { PlotTypes } from '@/utils/PlotTypes'; 9 | import type { Point } from '@/utils/utils'; 10 | 11 | class Rectinclined extends $Polygon { 12 | type: PlotTypes; 13 | 14 | fixPointCount: WithUndef; 15 | 16 | map: any; 17 | 18 | points: Point[]; 19 | 20 | freehand: boolean; 21 | 22 | constructor(coordinates, points, params) { 23 | super([]); 24 | this.type = PlotTypes.RECTINCLINED1; 25 | this.fixPointCount = 3; 26 | this.set('params', params); 27 | if (points && points.length > 0) { 28 | this.setPoints(points); 29 | } else if (coordinates && coordinates.length > 0) { 30 | this.setCoordinates(coordinates); 31 | } 32 | } 33 | 34 | /** 35 | * 获取标绘类型 36 | * @returns {*} 37 | */ 38 | getPlotType() { 39 | return this.type; 40 | } 41 | 42 | /** 43 | * 执行动作 44 | */ 45 | generate() { 46 | const points = this.getPointCount(); 47 | if (points < 2) { 48 | return false; 49 | } 50 | if (points === 2) { 51 | this.setCoordinates([this.points]); 52 | } else { 53 | const pnts = this.getPoints(); 54 | const [pnt1, pnt2, mouse] = [pnts[0], pnts[1], pnts[2]]; 55 | const d = this.calculatePerpendicularDistance(pnt1, pnt2, mouse); 56 | const direction = this.calculatePositionRelativeToLine(pnt1, pnt2, mouse); 57 | const pnt3 = this.calculatePerpendicularPoint(pnt1, pnt2, direction * d); 58 | const pnt4 = this.calculateFourthPoint(pnt1, pnt2, pnt3); 59 | const pList: Point[] = []; 60 | pList.push(pnt1, pnt2, pnt3, pnt4, pnt1); 61 | this.setCoordinates([pList]); 62 | } 63 | } 64 | 65 | /** 66 | * 已知p1,p2,p3三点,计算p3到p1p2的垂直距离 67 | * @param {*} p1 68 | * @param {*} p2 69 | * @param {*} p3 70 | */ 71 | calculatePerpendicularDistance(p1, p2, p3) { 72 | // 计算向量V的分量 73 | const vx = p2[0] - p1[0]; 74 | const vy = p2[1] - p1[1]; 75 | // 计算P1P3的分量 76 | const px = p3[0] - p1[0]; 77 | const py = p3[1] - p1[1]; 78 | // 计算向量V的模长 79 | const vMagnitude = Math.sqrt(vx * vx + vy * vy); 80 | // 计算点积 81 | const dotProduct = px * vx + py * vy; 82 | // 计算投影长度 83 | const projectionLength = dotProduct / vMagnitude; 84 | // 计算P1P3的模长 85 | const pMagnitude = Math.sqrt(px * px + py * py); 86 | // 计算垂直距离 87 | const perpendicularDistance = Math.sqrt(pMagnitude * pMagnitude - projectionLength * projectionLength); 88 | return perpendicularDistance; 89 | } 90 | 91 | /** 92 | * 已知p1,p2,两点,判断p3点在p1p2的左右,返回-1右侧,0线上,1左侧 93 | * @param {*} p1 94 | * @param {*} p2 95 | * @param {*} p3 96 | */ 97 | calculatePositionRelativeToLine(p1, p2, p3) { 98 | const v1 = { 99 | x: p2[0] - p1[0], 100 | y: p2[1] - p1[1], 101 | }; 102 | const v2 = { 103 | x: p3[0] - p1[0], 104 | y: p3[1] - p1[1], 105 | }; 106 | const crossProduct = v1.x * v2.y - v1.y * v2.x; 107 | const direction = crossProduct > 0 ? 1 : -1; 108 | if (p1[1] > p2[1]) { 109 | return direction; 110 | } 111 | return -direction; 112 | } 113 | 114 | /** 115 | * 已知p1,p2,p3点求矩形的p4点 116 | * @param {*} p1 117 | * @param {*} p2 118 | * @param {*} p3 119 | */ 120 | calculateFourthPoint(p1, p2, p3): Point { 121 | const x = p1[0] + p3[0] - p2[0]; 122 | const y = p1[1] + p3[1] - p2[1]; 123 | return [x, y]; 124 | } 125 | 126 | /** 127 | * 已知p1,p2两点和距离d,求距离p1p2垂直距离为d的点p3 128 | * @param {*} p1 129 | * @param {*} p2 130 | * @param {*} d 131 | */ 132 | calculatePerpendicularPoint(p1, p2, d): Point { 133 | // 计算p1p2的斜率 134 | const m = (p2[1] - p1[1]) / (p2[0] - p1[0]); 135 | 136 | let x, y; 137 | // 计算垂线的斜率 138 | if (m !== 0) { 139 | const perpendicularSlope = -1 / m; 140 | // 根据垂线斜率和已知点p2的坐标,得到垂线方程中的常数项 141 | const c = p2[1] - perpendicularSlope * p2[0]; 142 | // 解垂线方程,求解x和y的值 143 | x = d * Math.sqrt(1 / (1 + perpendicularSlope ** 2)) + p2[0]; 144 | y = perpendicularSlope * x + c; 145 | } else { 146 | x = p2[0]; 147 | y = p2[1] - d; 148 | } 149 | // 返回垂线另一端点的坐标 150 | return [x, y]; 151 | } 152 | 153 | /** 154 | * 设置地图对象 155 | * @param map 156 | */ 157 | setMap(map) { 158 | if (map && map instanceof Map) { 159 | this.map = map; 160 | } else { 161 | throw new Error('传入的不是地图对象!'); 162 | } 163 | } 164 | 165 | /** 166 | * 获取当前地图对象 167 | * @returns {ol.Map|*} 168 | */ 169 | getMap() { 170 | return this.map; 171 | } 172 | 173 | /** 174 | * 判断是否是Plot 175 | * @returns {boolean} 176 | */ 177 | isPlot() { 178 | return true; 179 | } 180 | 181 | /** 182 | * 设置坐标点 183 | * @param value 184 | */ 185 | setPoints(value) { 186 | this.points = !value ? [] : value; 187 | if (this.points.length >= 1) { 188 | this.generate(); 189 | } 190 | } 191 | 192 | /** 193 | * 获取坐标点 194 | * @returns {Array.} 195 | */ 196 | getPoints() { 197 | return this.points.slice(0); 198 | } 199 | 200 | /** 201 | * 获取点数量 202 | * @returns {Number} 203 | */ 204 | getPointCount() { 205 | return this.points.length; 206 | } 207 | 208 | /** 209 | * 更新当前坐标 210 | * @param point 211 | * @param index 212 | */ 213 | updatePoint(point, index) { 214 | if (index >= 0 && index < this.points.length) { 215 | this.points[index] = point; 216 | this.generate(); 217 | } 218 | } 219 | 220 | /** 221 | * 更新最后一个坐标 222 | * @param point 223 | */ 224 | updateLastPoint(point) { 225 | this.updatePoint(point, this.points.length - 1); 226 | } 227 | 228 | /** 229 | * 结束绘制 230 | */ 231 | finishDrawing() {} 232 | } 233 | 234 | export default Rectinclined; 235 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/Input/index.vue: -------------------------------------------------------------------------------- 1 | 63 | 216 | -------------------------------------------------------------------------------- /packages/ol-plot-vue/src/InputNumber/index.vue: -------------------------------------------------------------------------------- 1 | 54 | 236 | -------------------------------------------------------------------------------- /packages/ol-plot/src/utils/factory.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by FDD on 2017/5/1. 3 | * @desc 通过json获取样式 4 | */ 5 | import { Fill, Icon, RegularShape, Stroke, Style, Text, Circle } from 'ol/style'; 6 | import { Geometry } from 'ol/geom'; 7 | 8 | class StyleFactory { 9 | public style: Style; 10 | 11 | constructor(options: any) { 12 | const option = options && typeof options === 'object' ? options : {}; 13 | const style = new Style({}); 14 | if (option.geometry && option.geometry instanceof Geometry) { 15 | style.setGeometry(option.geometry); 16 | } 17 | if (option.zIndex && typeof option.zIndex === 'number') { 18 | style.setZIndex(option.zIndex); 19 | } 20 | if (option.fill && typeof option.fill === 'object') { 21 | style.setFill(this._getFill(option.fill)); 22 | } 23 | if (option.image && typeof option.image === 'object') { 24 | style.setImage(this._getImage(option.image)); 25 | } 26 | if (option.stroke && typeof option.stroke === 'object') { 27 | style.setStroke(this._getStroke(option.stroke)); 28 | } 29 | if (option.text && typeof option.text === 'object') { 30 | style.setText(this._getText(option.text)); 31 | } 32 | 33 | this.style = style; 34 | } 35 | 36 | /** 37 | * 获取规则样式图形 38 | * @param options 39 | * @returns {*} 40 | * @private 41 | */ 42 | _getRegularShape(options: any): RegularShape { 43 | return new RegularShape({ 44 | fill: this._getFill(options.fill) || undefined, 45 | points: typeof options.points === 'number' ? options.points : 1, 46 | radius: typeof options.radius === 'number' ? options.radius : undefined, 47 | radius1: typeof options.radius1 === 'number' ? options.radius1 : undefined, 48 | radius2: typeof options.radius2 === 'number' ? options.radius2 : undefined, 49 | angle: typeof options.angle === 'number' ? options.angle : 0, 50 | displacement: options.displacement ? options.displacement : [0, 0], 51 | scale: options.scale ? options.scale : 1, 52 | stroke: this._getStroke(options.stroke) || undefined, 53 | rotation: typeof options.rotation === 'number' ? options.rotation : 0, 54 | rotateWithView: typeof options.rotateWithView === 'boolean' ? options.rotateWithView : false, 55 | declutterMode: options.declutterMode ? options.declutterMode : undefined, 56 | }); 57 | } 58 | 59 | _getCircleShape(options: any): any { 60 | return new Circle({ 61 | fill: this._getFill(options.fill) || undefined, 62 | radius: typeof options.radius === 'number' ? options.radius : undefined, 63 | stroke: this._getStroke(options.stroke) || undefined, 64 | displacement: options.displacement ? options.displacement : [0, 0], 65 | scale: options.scale ? options.scale : undefined, 66 | rotation: typeof options.rotation === 'number' ? options.rotation : 0, 67 | rotateWithView: typeof options.rotateWithView === 'boolean' ? options.rotateWithView : false, 68 | declutterMode: options.declutterMode ? options.declutterMode : undefined, 69 | }); 70 | } 71 | 72 | /** 73 | * 获取图标样式 74 | * @param options 75 | * @returns {*} 76 | * @private 77 | */ 78 | _getImage(options): Icon | RegularShape { 79 | let image; 80 | // eslint-disable-next-line no-param-reassign 81 | options = options || {}; 82 | if (options.type === 'icon') { 83 | image = this._getIcon(options.image); 84 | } else if (options.type === 'circle') { 85 | image = this._getCircleShape(options.image); 86 | } else { 87 | image = this._getRegularShape(options.image); 88 | } 89 | return image; 90 | } 91 | 92 | /** 93 | * 获取icon 94 | * @param options 95 | * @returns {Icon} 96 | * @private 97 | */ 98 | _getIcon(options): Icon { 99 | // eslint-disable-next-line no-param-reassign 100 | options = options || {}; 101 | return new Icon({ 102 | anchor: options.imageAnchor ? options.imageAnchor : [0.5, 0.5], 103 | anchorXUnits: options.imageAnchorXUnits ? options.imageAnchorXUnits : 'fraction', 104 | anchorYUnits: options.imageAnchorYUnits ? options.imageAnchorYUnits : 'fraction', 105 | anchorOrigin: options.imageAnchorOrigin ? options.imageAnchorYUnits : 'top-left', 106 | color: options.imageColor ? options.imageColor : undefined, 107 | crossOrigin: options.crossOrigin ? options.crossOrigin : undefined, 108 | img: options.img ? options.img : undefined, 109 | offset: options.offset && Array.isArray(options.offset) && options.offset.length === 2 ? options.offset : [0, 0], 110 | offsetOrigin: options.offsetOrigin ? options.offsetOrigin : 'top-left', 111 | displacement: options.displacement ? options.displacement : [0, 0], 112 | scale: typeof options.scale === 'number' ? options.scale : 1, 113 | rotateWithView: typeof options.rotateWithView === 'boolean' ? options.rotateWithView : false, 114 | opacity: typeof options.imageOpacity === 'number' ? options.imageOpacity : 1, 115 | rotation: typeof options.imageRotation === 'number' ? options.imageRotation : 0, 116 | size: options.size && Array.isArray(options.size) && options.size.length === 2 ? options.size : undefined, 117 | imgSize: 118 | options.imgSize && Array.isArray(options.imgSize) && options.imgSize.length === 2 ? options.imgSize : undefined, 119 | src: options.imageSrc ? options.imageSrc : undefined, 120 | declutterMode: options.declutterMode ? options.declutterMode : undefined, 121 | }); 122 | } 123 | 124 | /** 125 | * 获取线条样式 126 | * @param options 127 | * @returns {Stroke} 128 | * @private 129 | */ 130 | _getStroke(options): Stroke { 131 | // eslint-disable-next-line no-param-reassign 132 | options = options || {}; 133 | return new Stroke({ 134 | color: options.strokeColor ? options.strokeColor : undefined, 135 | lineCap: options.strokeLineCap && typeof options.strokeLineCap === 'string' ? options.strokeLineCap : 'round', 136 | lineJoin: options.strokeLineJoin && typeof options.strokeLineJoin === 'string' ? options.strokeLineJoin : 'round', 137 | lineDash: options.strokeLineDash ? options.strokeLineDash : undefined, 138 | lineDashOffset: typeof options.strokeLineDashOffset === 'number' ? options.strokeLineDashOffset : '0', 139 | miterLimit: typeof options.strokeMiterLimit === 'number' ? options.strokeMiterLimit : 10, 140 | width: typeof options.strokeWidth === 'number' ? options.strokeWidth : undefined, 141 | }); 142 | } 143 | 144 | /** 145 | * 获取样式文本 146 | * @param options 147 | * @returns {Text} 148 | * @private 149 | */ 150 | _getText(options): Text { 151 | return new Text({ 152 | font: options.textFont && typeof options.textFont === 'string' ? options.textFont : '10px sans-serif', 153 | offsetX: typeof options.textOffsetX === 'number' ? options.textOffsetX : 0, 154 | offsetY: typeof options.textOffsetY === 'number' ? options.textOffsetY : 0, 155 | scale: typeof options.textScale === 'number' ? options.textScale : undefined, 156 | rotation: typeof options.textRotation === 'number' ? options.textRotation : 0, 157 | text: options.text && typeof options.text === 'string' ? options.text : undefined, 158 | textAlign: options.textAlign && typeof options.textAlign === 'string' ? options.textAlign : 'start', 159 | textBaseline: 160 | options.textBaseline && typeof options.textBaseline === 'string' ? options.textBaseline : 'alphabetic', 161 | rotateWithView: typeof options.rotateWithView === 'boolean' ? options.rotateWithView : false, 162 | fill: this._getFill(options.textFill), 163 | stroke: this._getStroke(options.textStroke), 164 | }); 165 | } 166 | 167 | /** 168 | * 获取填充颜色 169 | * @param options 170 | * @returns {Fill} 171 | * @private 172 | */ 173 | _getFill(options): Fill { 174 | // eslint-disable-next-line no-param-reassign 175 | options = options || {}; 176 | return new Fill({ 177 | color: options.fillColor ? options.fillColor : undefined, 178 | }); 179 | } 180 | } 181 | 182 | export default StyleFactory; 183 | --------------------------------------------------------------------------------