├── index.d.ts ├── export.js ├── .babelrc.json ├── .editorconfig ├── index.js ├── src ├── helper.js ├── AMapModel.js ├── index.js ├── AMapView.js └── AMapCoordSys.js ├── export.d.ts ├── .github └── workflows │ └── build.yml ├── LICENSE ├── types.d.ts ├── .gitignore ├── package.json ├── rollup.config.js ├── examples ├── heatmap_zh_CN.html ├── pie_zh_CN.html ├── lines_zh_CN.html ├── heatmap.html ├── pie.html ├── lines.html ├── scatter_zh_CN.html └── scatter.html ├── README.zh-CN.md ├── dist ├── echarts-extension-amap.min.js ├── echarts-extension-amap.esm.js ├── echarts-extension-amap.cjs.js ├── echarts-extension-amap.js └── echarts-extension-amap.min.js.map └── README.md /index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './types' 2 | -------------------------------------------------------------------------------- /export.js: -------------------------------------------------------------------------------- 1 | export * from './src/index' 2 | -------------------------------------------------------------------------------- /.babelrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/env" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * TODO use `echarts/core` rather than `echarts/lib/echarts` 3 | * to avoid self-registered `CanvasRenderer` and `DataSetComponent` in Apache ECharts 5 4 | * but it's not compatible with echarts v4. Leave it to 2.0. 5 | */ 6 | import * as echarts from 'echarts/lib/echarts' 7 | import { install } from './src/index' 8 | import { isNewEC } from './src/helper' 9 | 10 | isNewEC ? echarts.use(install) : install(echarts) 11 | 12 | export { name, version } from './src/index' 13 | -------------------------------------------------------------------------------- /src/helper.js: -------------------------------------------------------------------------------- 1 | import { version } from 'echarts/lib/echarts' 2 | 3 | export const ecVer = version.split('.') 4 | 5 | export const isNewEC = ecVer[0] > 4 6 | 7 | export const COMPONENT_TYPE = 'amap' 8 | 9 | /* global AMap */ 10 | 11 | // The version property is `AMap.v` in AMap 1.x, 12 | // but `AMap.version` may also exist (See #51) 13 | // In AMap 2.x, it's `AMap.version` (Not sure if `AMap.v` exists) 14 | // use function instead of constant to allow importing the plugin before AMap is loaded 15 | export const isAMap2X = () => !AMap.v && AMap.version && AMap.version.split('.')[0] >= 2 16 | 17 | export function v2Equal(a, b) { 18 | return a && b && a[0] === b[0] && a[1] === b[1] 19 | } 20 | 21 | let logMap = {} 22 | 23 | export function logWarn(tag, msg, once) { 24 | const log = `[ECharts][Extension][AMap]${tag ? ' ' + tag + ':' : ''} ${msg}` 25 | once && logMap[log] || console.warn(log) 26 | once && (logMap[log] = true) 27 | } 28 | 29 | export function clearLogMap() { 30 | logMap = {} 31 | } 32 | -------------------------------------------------------------------------------- /export.d.ts: -------------------------------------------------------------------------------- 1 | import { use } from 'echarts/core' 2 | import EChartsV4 from 'echarts/lib/echarts' 3 | 4 | type UnionToIntersection = 5 | (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never 6 | 7 | type LastOf = 8 | UnionToIntersection T : never> extends () => (infer R) ? R : never 9 | 10 | type Push = [...T, V] 11 | 12 | type TuplifyUnion, N = [T] extends [never] ? true : false> = 13 | true extends N ? [] : Push>, L> 14 | 15 | type EChartsExtensionInstallRegisters = Parameters[0]>[0]>[0] 16 | 17 | export type EChartsExtensionRegisters = EChartsExtensionInstallRegisters extends never 18 | ? typeof EChartsV4 19 | : EChartsExtensionInstallRegisters 20 | 21 | /** 22 | * To install AMap component 23 | * @param registers echarts registers. If using v4, it should be echarts namespace. 24 | */ 25 | export declare function install(registers: EChartsExtensionRegisters): void 26 | 27 | export * from './types' 28 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | pull_request: 7 | types: [opened, synchronize] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | node-version: [18.x] 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | 21 | - name: Use Node.js ${{ matrix.node-version }} 22 | uses: actions/setup-node@v3 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | registry-url: https://registry.npmjs.org/ 26 | 27 | - name: Cache node modules 28 | id: cache-dep 29 | uses: actions/cache@v3 30 | env: 31 | cache-name: cache-node-modules 32 | with: 33 | path: node_modules 34 | key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} 35 | 36 | - name: Install dependencies 37 | if: steps.cache-dep.outputs.cache-hit != 'true' 38 | run: npm ci 39 | 40 | - name: Build from source 41 | run: npm run build 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2024 Zhongxiang Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /types.d.ts: -------------------------------------------------------------------------------- 1 | declare const name = 'echarts-extension-amap' 2 | declare const version = '1.12.0' 3 | 4 | interface InnerAMapComponentOption { 5 | /** 6 | * The zIndex of echarts layer for AMap. 7 | * @default 2000 8 | * @deprecated deprecated since v1.9.0, use `echartsLayerInteractive` instead. 9 | */ 10 | echartsLayerZIndex?: number 11 | /** 12 | * Whether echarts layer is interactive. 13 | * @default true 14 | * @since v1.9.0 15 | */ 16 | echartsLayerInteractive?: Boolean 17 | /** 18 | * Whether to enable large mode 19 | * @default false 20 | * @since v1.9.0 21 | */ 22 | largeMode?: false 23 | /** 24 | * Whether echarts layer should be rendered when the map is moving. 25 | * if `false`, it will only be re-rendered after the map `moveend`. 26 | * It's better to set this option to false if data is large. 27 | * @default true 28 | */ 29 | renderOnMoving?: boolean 30 | /** 31 | * Whether to return map camera state in `amaproam` event 32 | * @default false 33 | * @since v1.10.0 34 | */ 35 | returnMapCameraState?: boolean 36 | } 37 | 38 | /** 39 | * Extended AMap component option 40 | */ 41 | interface AMapComponentOption { 42 | amap?: AMapOption extends never 43 | ? InnerAMapComponentOption 44 | : InnerAMapComponentOption & AMapOption 45 | } 46 | 47 | export { name, version, AMapComponentOption } 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # vuepress build output 66 | .vuepress/dist 67 | 68 | # Serverless directories 69 | .serverless 70 | 71 | # IDE 72 | .idea 73 | 74 | # Service worker 75 | sw.* 76 | 77 | # test 78 | test/ 79 | 80 | # tpl 81 | examples/*.tpl 82 | examples/*.version 83 | -------------------------------------------------------------------------------- /src/AMapModel.js: -------------------------------------------------------------------------------- 1 | import { ComponentModel } from 'echarts/lib/echarts' 2 | import { COMPONENT_TYPE, isNewEC, v2Equal } from './helper' 3 | 4 | const AMapModel = { 5 | type: COMPONENT_TYPE, 6 | 7 | setAMap(amap) { 8 | this.__amap = amap 9 | }, 10 | 11 | getAMap() { 12 | return this.__amap 13 | }, 14 | 15 | setEChartsLayer(layer) { 16 | this.__echartsLayer = layer 17 | }, 18 | 19 | getEChartsLayer() { 20 | return this.__echartsLayer 21 | }, 22 | 23 | setEChartsLayerVisibility(visible) { 24 | this.__echartsLayer.style.display = visible ? 'block' : 'none' 25 | }, 26 | 27 | // FIXME: NOT SUPPORT <= IE 10 28 | setEChartsLayerInteractive(interactive) { 29 | this.option.echartsLayerInteractive = !!interactive 30 | this.__echartsLayer.style.pointerEvents = interactive ? 'auto' : 'none' 31 | }, 32 | 33 | setCenterAndZoom(center, zoom) { 34 | this.option.center = center 35 | this.option.zoom = zoom 36 | }, 37 | 38 | centerOrZoomChanged(center, zoom) { 39 | const option = this.option 40 | return !(v2Equal(center, option.center) && zoom === option.zoom) 41 | }, 42 | 43 | defaultOption: { 44 | center: [116.397428, 39.90923], 45 | zoom: 5, 46 | isHotspot: false, 47 | resizeEnable: true, 48 | 49 | // extension specific options 50 | // echartsLayerZIndex: 2000, // DEPRECATED since v1.9.0 51 | echartsLayerInteractive: true, 52 | renderOnMoving: true, 53 | largeMode: false, 54 | // since v1.10.0 55 | returnMapCameraState: false 56 | } 57 | } 58 | 59 | export default isNewEC 60 | ? ComponentModel.extend(AMapModel) 61 | : AMapModel 62 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "echarts-extension-amap", 3 | "version": "1.12.0", 4 | "description": "An AMap(https://lbs.amap.com) extension for Apache ECharts (https://github.com/apache/echarts)", 5 | "main": "dist/echarts-extension-amap.min.js", 6 | "module": "dist/echarts-extension-amap.esm.js", 7 | "files": [ 8 | "dist", 9 | "src", 10 | "index.js", 11 | "index.d.ts", 12 | "export.js", 13 | "export.d.ts", 14 | "types.d.ts", 15 | "examples/*.html" 16 | ], 17 | "types": "types.d.ts", 18 | "scripts": { 19 | "dev": "rollup -wc --bundleConfigAsCjs --environment NODE_ENV:development", 20 | "build": "rollup -c --bundleConfigAsCjs --environment NODE_ENV:production", 21 | "postbuild": "node build/post-build.js", 22 | "release": "npm run build && npm run generate:example", 23 | "generate:example": "node build/generateExamples.js" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/plainheart/echarts-extension-amap.git" 28 | }, 29 | "keywords": [ 30 | "echarts", 31 | "amap", 32 | "autonavi", 33 | "echarts-extension", 34 | "data-visualization", 35 | "map", 36 | "gaode", 37 | "echarts-amap", 38 | "echarts4", 39 | "echarts5", 40 | "amap-v2" 41 | ], 42 | "author": "plainheart", 43 | "license": "MIT", 44 | "bugs": { 45 | "url": "https://github.com/plainheart/echarts-extension-amap/issues" 46 | }, 47 | "homepage": "https://github.com/plainheart/echarts-extension-amap#readme", 48 | "devDependencies": { 49 | "@babel/core": "^7.23.7", 50 | "@babel/preset-env": "^7.23.7", 51 | "@rollup/plugin-babel": "^6.0.4", 52 | "@rollup/plugin-commonjs": "^25.0.7", 53 | "@rollup/plugin-json": "^6.1.0", 54 | "@rollup/plugin-node-resolve": "^15.2.3", 55 | "@rollup/plugin-terser": "^0.4.4", 56 | "@types/echarts": "^4.9.22", 57 | "chalk": "^4.1.2", 58 | "echarts": "^5.4.3", 59 | "rollup": "^4.9.4" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * AMap component extension 3 | */ 4 | 5 | import AMapCoordSys from './AMapCoordSys' 6 | import AMapModel from './AMapModel' 7 | import AMapView from './AMapView' 8 | import { isNewEC, ecVer, COMPONENT_TYPE } from './helper' 9 | 10 | export { version, name } from '../package.json' 11 | 12 | /** 13 | * @typedef {import('../export').EChartsExtensionRegisters} EChartsExtensionRegisters 14 | */ 15 | 16 | /** 17 | * AMap extension installer 18 | * @param {EChartsExtensionRegisters} registers 19 | */ 20 | export function install(registers) { 21 | // add coordinate system support for pie series for ECharts < 5.4.0 22 | if (!isNewEC || (ecVer[0] == 5 && ecVer[1] < 4)) { 23 | registers.registerLayout(function(ecModel) { 24 | ecModel.eachSeriesByType('pie', function (seriesModel) { 25 | const coordSys = seriesModel.coordinateSystem 26 | const data = seriesModel.getData() 27 | const valueDim = data.mapDimension('value') 28 | if (coordSys && coordSys.type === COMPONENT_TYPE) { 29 | const center = seriesModel.get('center') 30 | const point = coordSys.dataToPoint(center) 31 | const cx = point[0] 32 | const cy = point[1] 33 | data.each(valueDim, function (value, idx) { 34 | const layout = data.getItemLayout(idx) 35 | layout.cx = cx 36 | layout.cy = cy 37 | }) 38 | } 39 | }) 40 | }) 41 | } 42 | // Model 43 | isNewEC 44 | ? registers.registerComponentModel(AMapModel) 45 | : registers.extendComponentModel(AMapModel) 46 | // View 47 | isNewEC 48 | ? registers.registerComponentView(AMapView) 49 | : registers.extendComponentView(AMapView) 50 | // Coordinate System 51 | registers.registerCoordinateSystem(COMPONENT_TYPE, AMapCoordSys) 52 | // Action 53 | registers.registerAction( 54 | { 55 | type: COMPONENT_TYPE + 'Roam', 56 | event: COMPONENT_TYPE + 'Roam', 57 | update: 'updateLayout' 58 | }, 59 | function(payload, ecModel) { 60 | ecModel.eachComponent(COMPONENT_TYPE, function(amapModel) { 61 | const amap = amapModel.getAMap() 62 | const center = amap.getCenter() 63 | amapModel.setCenterAndZoom([center.lng, center.lat], amap.getZoom()) 64 | }) 65 | } 66 | ) 67 | } 68 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import chalk from 'chalk' 3 | import json from '@rollup/plugin-json' 4 | import commonjs from '@rollup/plugin-commonjs' 5 | import terser from '@rollup/plugin-terser' 6 | import { nodeResolve } from '@rollup/plugin-node-resolve' 7 | import { babel } from '@rollup/plugin-babel' 8 | import { name, version } from './package.json' 9 | 10 | const resolve = p => path.resolve(__dirname, p) 11 | 12 | const outputConfigs = { 13 | esm: { 14 | file: resolve(`dist/${name}.esm.js`), 15 | format: 'es' 16 | }, 17 | cjs: { 18 | file: resolve(`dist/${name}.cjs.js`), 19 | format: 'cjs' 20 | }, 21 | umd: { 22 | file: resolve(`dist/${name}.js`), 23 | format: 'umd' 24 | } 25 | } 26 | 27 | const env = process.env.NODE_ENV 28 | const isProd = env === 'production' 29 | 30 | console.log(chalk.bgCyan(`🚩 Building ${version} for ${env}... `)) 31 | 32 | const packageFormats = isProd 33 | ? ['esm', 'cjs', 'umd'] 34 | : ['umd'] 35 | 36 | const packageConfigs = packageFormats.map( 37 | format => createConfig(format, outputConfigs[format]) 38 | ) 39 | 40 | if (isProd) { 41 | packageFormats.forEach(format => { 42 | if (format === 'umd') { 43 | packageConfigs.push(createMinifiedConfig(format)) 44 | } 45 | }) 46 | } 47 | 48 | function createConfig(format, output, specificPlugins = []) { 49 | output.externalLiveBindings = false 50 | 51 | const isUMDBuild = format === 'umd' 52 | 53 | if (isUMDBuild) { 54 | output.name = 'echarts.amap' 55 | output.sourcemap = isProd 56 | } 57 | 58 | output.interop = 'esModule' 59 | 60 | const external = ['echarts/lib/echarts'] 61 | output.globals = { 62 | // For UMD `global.echarts` 63 | [external[0]]: 'echarts' 64 | } 65 | 66 | output.validate = isProd 67 | output.banner = isProd && require('./build/header').getLicense() 68 | 69 | const plugins = [] 70 | 71 | if (isProd) { 72 | plugins.push( 73 | babel({ 74 | babelHelpers: 'bundled' 75 | }) 76 | ) 77 | } else { 78 | plugins.push({ 79 | outro() { 80 | return 'exports.bundleVersion = \'' + (+new Date()) + '\';' 81 | } 82 | }) 83 | } 84 | 85 | return { 86 | input: resolve('index.js'), 87 | external, 88 | plugins: [ 89 | json(), 90 | nodeResolve(), 91 | commonjs(), 92 | ...plugins, 93 | ...specificPlugins 94 | ], 95 | output, 96 | treeshake: { 97 | moduleSideEffects: false 98 | } 99 | } 100 | } 101 | 102 | function createMinifiedConfig(format) { 103 | return createConfig( 104 | format, 105 | { 106 | file: outputConfigs[format].file.replace(/\.js$/, '.min.js'), 107 | format: outputConfigs[format].format 108 | }, 109 | [ 110 | terser({ 111 | module: /^esm/.test(format), 112 | compress: { 113 | ecma: 2015, 114 | pure_getters: true, 115 | pure_funcs: ['console.log'] 116 | }, 117 | safari10: true, 118 | ie8: false 119 | }) 120 | ] 121 | ) 122 | } 123 | 124 | export default packageConfigs 125 | -------------------------------------------------------------------------------- /examples/heatmap_zh_CN.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Heatmap 热力图 | echarts-extension-amap 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 30 | 31 | 32 |
33 | 34 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /examples/pie_zh_CN.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Pie 饼图 | echarts-extension-amap 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 29 | 30 | 31 |
32 | 33 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /examples/lines_zh_CN.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Lines 路径图 | echarts-extension-amap 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 30 | 31 | 32 |
33 | 34 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /examples/heatmap.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Heatmap | echarts-extension-amap 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 30 | 31 | 32 |
33 | 34 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /examples/pie.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Pie | echarts-extension-amap 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 29 | 30 | 31 |
32 | 33 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /examples/lines.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Lines | echarts-extension-amap 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 30 | 31 | 32 |
33 | 34 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /src/AMapView.js: -------------------------------------------------------------------------------- 1 | import { ComponentView, getInstanceByDom, throttle } from 'echarts/lib/echarts' 2 | import { COMPONENT_TYPE, isNewEC, isAMap2X, clearLogMap } from './helper' 3 | 4 | let _isAMap2X 5 | 6 | const AMapView = { 7 | type: COMPONENT_TYPE, 8 | 9 | init() { 10 | this._isFirstRender = true 11 | 12 | _isAMap2X = isAMap2X() 13 | }, 14 | 15 | render(amapModel, ecModel, api) { 16 | let rendering = true 17 | 18 | const amap = amapModel.getAMap() 19 | const viewportRoot = api.getZr().painter.getViewportRoot() 20 | const offsetEl = amap.getContainer() 21 | const coordSys = amapModel.coordinateSystem 22 | 23 | const renderOnMoving = amapModel.get('renderOnMoving') 24 | const resizeEnable = amapModel.get('resizeEnable') 25 | const largeMode = amapModel.get('largeMode') 26 | const returnMapCameraState = amapModel.get('returnMapCameraState') 27 | 28 | const viewMode = amap.getViewMode_() 29 | const is3DMode = viewMode === '3D' 30 | 31 | let moveHandler = function(e) { 32 | if (rendering) { 33 | return 34 | } 35 | 36 | const offsetElStyle = offsetEl.style 37 | const mapOffset = [ 38 | -parseInt(offsetElStyle.left, 10) || 0, 39 | -parseInt(offsetElStyle.top, 10) || 0 40 | ] 41 | // only update style when map offset changed 42 | const viewportRootStyle = viewportRoot.style 43 | const offsetLeft = mapOffset[0] + 'px' 44 | const offsetTop = mapOffset[1] + 'px' 45 | if (viewportRootStyle.left !== offsetLeft) { 46 | viewportRootStyle.left = offsetLeft 47 | } 48 | if (viewportRootStyle.top !== offsetTop) { 49 | viewportRootStyle.top = offsetTop 50 | } 51 | 52 | coordSys.setMapOffset(amapModel.__mapOffset = mapOffset) 53 | 54 | const actionParams = { 55 | type: 'amapRoam', 56 | animation: { 57 | // compatible with ECharts 5.x 58 | // no delay for rendering but remain animation of elements 59 | duration: 0 60 | } 61 | } 62 | 63 | if (returnMapCameraState) { 64 | e = e || {} 65 | let center = e.center 66 | if (!center) { 67 | // normalize center LngLat to Array 68 | center = amap.getCenter() 69 | center = [center.lng, center.lat] 70 | } 71 | actionParams.camera = { 72 | viewMode, 73 | center, 74 | zoom: e.zoom || amap.getZoom(), 75 | rotation: e.rotation == null ? amap.getRotation() : e.rotation, 76 | pitch: e.pitch == null ? amap.getPitch() : e.pitch, 77 | scale: amap.getScale(), 78 | bounds: amap.getBounds() 79 | } 80 | } 81 | 82 | api.dispatchAction(actionParams) 83 | } 84 | 85 | amap.off('mapmove', this._moveHandler) 86 | amap.off('moveend', this._moveHandler) 87 | amap.off('viewchange', this._moveHandler) 88 | amap.off('camerachange', this._moveHandler) 89 | amap.off('zoom', this._moveHandler) 90 | 91 | if (this._resizeHandler) { 92 | amap.off('resize', this._resizeHandler) 93 | } 94 | if (this._moveStartHandler) { 95 | amap.off('movestart', this._moveStartHandler) 96 | } 97 | if (this._moveEndHandler) { 98 | amap.off('moveend', this._moveEndHandler) 99 | amap.off('zoomend', this._moveEndHandler) 100 | } 101 | 102 | amap.on( 103 | renderOnMoving 104 | ? (_isAMap2X 105 | ? 'viewchange' 106 | : is3DMode 107 | ? 'camerachange' 108 | : 'mapmove') 109 | : 'moveend', 110 | // FIXME: bad performance in 1.x in the cases with large data, use debounce? 111 | // moveHandler 112 | (!_isAMap2X && largeMode) ? (moveHandler = throttle(moveHandler, 20, true)) : moveHandler 113 | ) 114 | 115 | this._moveHandler = moveHandler 116 | 117 | if (renderOnMoving && !(_isAMap2X && is3DMode)) { 118 | // need to listen to zoom if 1.x & 2D mode 119 | // FIXME: unnecessary `mapmove` event triggered when zooming 120 | amap.on('zoom', moveHandler) 121 | } 122 | 123 | if (!renderOnMoving) { 124 | amap.on('movestart', this._moveStartHandler = function() { 125 | setTimeout(function() { 126 | amapModel.setEChartsLayerVisibility(false) 127 | }, 0) 128 | }) 129 | const moveEndHandler = this._moveEndHandler = function(e) { 130 | ;(!e || e.type !== 'moveend') && moveHandler(e) 131 | setTimeout(function() { 132 | amapModel.setEChartsLayerVisibility(true) 133 | }, _isAMap2X || !largeMode ? 0 : 20) 134 | } 135 | amap.on('moveend', moveEndHandler) 136 | amap.on('zoomend', moveEndHandler) 137 | if (this._isFirstRender && is3DMode) { 138 | // FIXME: not rewrite AMap instance method 139 | const nativeSetPitch = amap.setPitch 140 | const nativeSetRotation = amap.setRotation 141 | amap.setPitch = function() { 142 | nativeSetPitch.apply(this, arguments) 143 | moveEndHandler() 144 | } 145 | amap.setRotation = function() { 146 | nativeSetRotation.apply(this, arguments) 147 | moveEndHandler() 148 | } 149 | } 150 | } 151 | 152 | if (resizeEnable) { 153 | let resizeHandler = () => { 154 | clearTimeout(this._resizeTimeout) 155 | this._resizeTimeout = setTimeout(() => getInstanceByDom(api.getDom()).resize(), 0) 156 | } 157 | if (!_isAMap2X && largeMode) { 158 | resizeHandler = throttle(resizeHandler, 20, true) 159 | } 160 | amap.on('resize', this._resizeHandler = resizeHandler) 161 | } 162 | 163 | this._isFirstRender = rendering = false 164 | }, 165 | 166 | dispose() { 167 | clearTimeout(this._resizeTimeout) 168 | clearLogMap() 169 | const component = this.__model 170 | if (component) { 171 | component.getAMap().destroy() 172 | component.setAMap(null) 173 | component.setEChartsLayer(null) 174 | if (component.coordinateSystem) { 175 | component.coordinateSystem.setAMap(null) 176 | component.coordinateSystem = null 177 | } 178 | } 179 | delete this._moveHandler 180 | delete this._moveStartHandler 181 | delete this._moveEndHandler 182 | delete this._resizeHandler 183 | delete this._resizeTimeout 184 | } 185 | } 186 | 187 | export default isNewEC 188 | ? ComponentView.extend(AMapView) 189 | : AMapView 190 | -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- 1 | [![NPM version](https://img.shields.io/npm/v/echarts-extension-amap.svg?style=flat)](https://www.npmjs.org/package/echarts-extension-amap) 2 | [![Build Status](https://github.com/plainheart/echarts-extension-amap/actions/workflows/build.yml/badge.svg)](https://github.com/plainheart/echarts-extension-amap/actions/workflows/build.yml) 3 | [![NPM Downloads](https://img.shields.io/npm/dm/echarts-extension-amap.svg)](https://npmcharts.com/compare/echarts-extension-amap?minimal=true) 4 | [![jsDelivr Downloads](https://data.jsdelivr.com/v1/package/npm/echarts-extension-amap/badge?style=rounded)](https://www.jsdelivr.com/package/npm/echarts-extension-amap) 5 | [![License](https://img.shields.io/npm/l/echarts-extension-amap.svg)](https://github.com/plainheart/echarts-extension-amap/blob/master/LICENSE) 6 | 7 | ## Apache ECharts 高德地图扩展 8 | 9 | [README_EN](https://github.com/plainheart/echarts-extension-amap/blob/master/README.md) 10 | 11 | [在线示例](https://codepen.io/plainheart/pen/qBbdNYx) 12 | 13 | [Apache ECharts](https://echarts.apache.org/zh/index.html) 高德地图扩展,可以在高德地图上展现 [点图](https://echarts.apache.org/zh/option.html#series-scatter),[线图](https://echarts.apache.org/zh/option.html#series-lines),[热力图](https://echarts.apache.org/zh/option.html#series-heatmap),[饼图](https://echarts.apache.org/zh/option.html#series-pie) 等可视化。 14 | 15 | ### 示例 16 | 17 | Scatter 散点图: [examples/scatter.html](https://github.com/plainheart/echarts-extension-amap/blob/master/examples/scatter_zh_CN.html) 18 | 19 | ![Preview-Scatter](https://user-images.githubusercontent.com/26999792/53300484-e2979680-3882-11e9-8fb4-143c4ca4c416.png) 20 | 21 | Heatmap 热力图: [examples/heatmap.html](https://github.com/plainheart/echarts-extension-amap/blob/master/examples/heatmap_zh_CN.html) 22 | 23 | ![Preview-Heatmap](https://user-images.githubusercontent.com/26999792/101314208-fadb7880-3892-11eb-902a-8f6f41ffe0fc.png) 24 | 25 | Lines 线图: [examples/lines.html](https://github.com/plainheart/echarts-extension-amap/blob/master/examples/lines_zh_CN.html) 26 | 27 | ![Preview-Lines](https://user-images.githubusercontent.com/26999792/101313379-fca43c80-3890-11eb-9dea-46230dc432d5.gif) 28 | 29 | Pie 饼图: [examples/pie.html](https://github.com/plainheart/echarts-extension-amap/blob/master/examples/pie_zh_CN.html) (**自 v1.11.0 开始支持**) 30 | 31 | ![Preview-Pie](https://user-images.githubusercontent.com/26999792/193215980-cd6736f5-a63d-4085-8012-d519e9e78398.png) 32 | 33 | ### 安装 34 | 35 | ```shell 36 | npm install echarts-extension-amap --save 37 | ``` 38 | 39 | ### 引入 40 | 41 | 可以直接引入打包好的扩展文件和高德地图的 JavaScript API 42 | 43 | ```html 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ``` 52 | 53 | 如果 `webpack` 等工具打包,也可以通过 `require` 或者 `import` 引入 54 | 55 | ```js 56 | // 使用 require 57 | require('echarts'); 58 | require('echarts-extension-amap'); 59 | 60 | // 使用 import 61 | import * as echarts from 'echarts'; 62 | import 'echarts-extension-amap'; 63 | ``` 64 | 65 | > 如需动态引入高德地图 API 脚本,可以使用 [amap-jsapi-loader](https://www.npmjs.com/package/@amap/amap-jsapi-loader) 或自行借助 `Promise` 封装一个动态异步 script 加载器。 66 | 67 | **使用 CDN** 68 | 69 | [**jsDelivr**](https://www.jsdelivr.com/) 70 | 71 | 使用最新版 72 | 73 | [https://cdn.jsdelivr.net/npm/echarts-extension-amap/dist/echarts-extension-amap.min.js](https://cdn.jsdelivr.net/npm/echarts-extension-amap/dist/echarts-extension-amap.min.js) 74 | 75 | 使用指定版本 76 | 77 | [https://cdn.jsdelivr.net/npm/echarts-extension-amap@1.12.0/dist/echarts-extension-amap.min.js](https://cdn.jsdelivr.net/npm/echarts-extension-amap@1.12.0/dist/echarts-extension-amap.min.js) 78 | 79 | [**unpkg**](https://unpkg.com/) 80 | 81 | 使用最新版 82 | 83 | [https://unpkg.com/echarts-extension-amap/dist/echarts-extension-amap.min.js](https://unpkg.com/echarts-extension-amap/dist/echarts-extension-amap.min.js) 84 | 85 | 使用指定版本 86 | 87 | [https://unpkg.com/echarts-extension-amap@1.12.0/dist/echarts-extension-amap.min.js](https://unpkg.com/echarts-extension-amap@1.12.0/dist/echarts-extension-amap.min.js) 88 | 89 | 插件会自动注册相应的组件。 90 | 91 | **Apache ECharts 5 按需引入** 92 | 93 | Apache ECharts 从 v5.0.1 开始提供了[新的按需引入](https://echarts.apache.org/zh/tutorial.html#%E5%9C%A8%E6%89%93%E5%8C%85%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8%20ECharts)接口,因此也可以按需引入高德地图扩展组件。引入方法如下: 94 | 95 | ```ts 96 | // 按需引入 scatter、effectScatter 和 高德地图扩展 97 | import * as echarts from 'echarts/core'; 98 | import { 99 | ScatterChart, 100 | ScatterSeriesOption, 101 | EffectScatterChart, 102 | EffectScatterSeriesOption 103 | } from 'echarts/charts'; 104 | import { 105 | TooltipComponent, 106 | TitleComponentOption 107 | } from 'echarts/components'; 108 | import { CanvasRenderer } from 'echarts/renderers'; 109 | import { 110 | install as AMapComponent, 111 | AMapComponentOption 112 | } from 'echarts-extension-amap/export'; 113 | 114 | // 引入高德地图官方提供的 2.0 类型定义文件 115 | import '@amap/amap-jsapi-types'; 116 | 117 | // 组装所需的 option type 118 | type ECOption = echarts.ComposeOption< 119 | | ScatterSeriesOption 120 | | EffectScatterSeriesOption 121 | | TitleComponentOption 122 | // 合并高德地图的地图初始配置项 AMap.MapOptions 到 AMapComponentOption 123 | > & AMapComponentOption; 124 | 125 | // 注册渲染器、组件和图表 126 | echarts.use([ 127 | CanvasRenderer, 128 | TooltipComponent, 129 | AMapComponent, 130 | ScatterChart, 131 | EffectScatterChart 132 | ]); 133 | 134 | // 定义 ECharts option 135 | const option: ECOption = { 136 | // 高德地图组件 option 137 | amap: { 138 | // ... 139 | }, 140 | title: { 141 | // ... 142 | }, 143 | series: [ 144 | { 145 | type: 'scatter', 146 | // 指定坐标系为高德地图 147 | coordinateSystem: 'amap', 148 | // ... 149 | } 150 | ] 151 | // ... 152 | }; 153 | ``` 154 | 155 | ### 使用 156 | 157 | ```js 158 | option = { 159 | // 加载 amap 组件 160 | amap: { 161 | // 3D模式,无论你使用的是1.x版本还是2.x版本,都建议开启此项以获得更好的渲染体验 162 | viewMode: '3D', 163 | // 高德地图支持的初始化地图配置 164 | // 高德地图初始中心经纬度 165 | center: [108.39, 39.9], 166 | // 高德地图初始缩放级别 167 | zoom: 4, 168 | // 是否开启resize 169 | resizeEnable: true, 170 | // 自定义地图样式主题 171 | mapStyle: 'amap://styles/dark', 172 | // 移动过程中实时渲染 默认为true 如数据量较大 建议置为false 173 | renderOnMoving: true, 174 | // ECharts 图层的 zIndex 默认 2000 175 | // 从 v1.9.0 起 此配置项已被弃用 请使用 `echartsLayerInteractive` 代替 176 | echartsLayerZIndex: 2019, 177 | // 设置 ECharts 图层是否可交互 默认为 true 178 | // 设置为 false 可实现高德地图自身图层交互 179 | // 此配置项从 v1.9.0 起开始支持 180 | echartsLayerInteractive: true, 181 | // 是否启用大数据模式 默认为 false 182 | // 此配置项从 v1.9.0 起开始支持 183 | largeMode: false 184 | // 说明:如果想要添加卫星、路网等图层 185 | // 暂时先不要使用layers配置,因为存在Bug 186 | // 建议使用amap.add的方式,使用方式参见最下方代码 187 | }, 188 | series: [ 189 | { 190 | type: 'scatter', 191 | // 使用高德地图坐标系 192 | coordinateSystem: 'amap', 193 | // 数据格式跟在 geo 坐标系上一样,每一项都是 [经度,纬度,数值大小,其它维度...] 194 | data: [[120, 30, 8], [120.1, 30.2, 20]], 195 | encode: { 196 | value: 2 197 | } 198 | } 199 | ] 200 | }; 201 | 202 | // 获取 ECharts 高德地图组件 203 | var amapComponent = chart.getModel().getComponent('amap'); 204 | // 获取高德地图实例,使用高德地图自带的控件(需要在高德地图js API script标签手动引入) 205 | var amap = amapComponent.getAMap(); 206 | // 添加控件 207 | amap.addControl(new AMap.Scale()); 208 | amap.addControl(new AMap.ToolBar()); 209 | // 添加图层 210 | var satelliteLayer = new AMap.TileLayer.Satellite(); 211 | var roadNetLayer = new AMap.TileLayer.RoadNet(); 212 | amap.add([satelliteLayer, roadNetLayer]); 213 | // 添加一个 Marker 214 | amap.add(new AMap.Marker({ 215 | position: [115, 35] 216 | })); 217 | // 禁用 ECharts 图层交互,从而使高德地图图层可以点击交互 218 | amapComponent.setEChartsLayerInteractive(false); 219 | ``` 220 | -------------------------------------------------------------------------------- /dist/echarts-extension-amap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * echarts-extension-amap 3 | * @version 1.12.0 4 | * @author plainheart 5 | * 6 | * MIT License 7 | * 8 | * Copyright (c) 2019-2024 Zhongxiang Wang 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in all 18 | * copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | */ 29 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("echarts/lib/echarts")):"function"==typeof define&&define.amd?define(["exports","echarts"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).echarts=e.echarts||{},e.echarts.amap={}),e.echarts)}(this,(function(e,t){"use strict";var n=t.version.split("."),a=n[0]>4,o="amap";var i={};function r(e,t,n){var a="[ECharts][Extension][AMap]".concat(e?" "+e+":":""," ").concat(t);n&&i[a]||console.warn(a),n&&(i[a]=!0)}function s(e,n){return n=n||[0,0],t.util.map([0,1],(function(t){var a=n[t],o=e[t]/2,i=[],r=[];return i[t]=a-o,r[t]=a+o,i[1-t]=r[1-t]=n[1-t],Math.abs(this.dataToPoint(i)[t]-this.dataToPoint(r)[t])}),this)}var c=["echartsLayerZIndex","echartsLayerInteractive","renderOnMoving","largeMode","returnMapCameraState","layers"];function p(e,t){this._amap=e,this._api=t,this._mapOffset=[0,0]}var h=p.prototype;h.setZoom=function(e){this._zoom=e},h.setCenter=function(e){var t=new AMap.LngLat(e[0],e[1]);this._center=this._amap.lngLatToContainer(t)},h.setMapOffset=function(e){this._mapOffset=e},h.setAMap=function(e){this._amap=e},h.getAMap=function(){return this._amap},h.dataToPoint=function(e){var t=new AMap.LngLat(e[0],e[1]),n=this._amap.lngLatToContainer(t),a=this._mapOffset;return[n.x-a[0],n.y-a[1]]},h.pointToData=function(e){var t=this._mapOffset,n=this._amap.containerToLngLat(new AMap.Pixel(e[0]+t[0],e[1]+t[1]));return[n.lng,n.lat]},h.getViewRect=function(){var e=this._api;return new t.graphic.BoundingRect(0,0,e.getWidth(),e.getHeight())},h.getRoamTransform=function(){return t.matrix.create()},h.prepareCustoms=function(){var e=this.getViewRect();return{coordSys:{type:o,x:e.x,y:e.y,width:e.width,height:e.height},api:{coord:t.util.bind(this.dataToPoint,this),size:t.util.bind(s,this)}}},h.convertToPixel=function(e,t,n){return this.dataToPoint(n)},h.convertFromPixel=function(e,t,n){return this.pointToData(n)},p.create=function(e,n){var a;return e.eachComponent(o,(function(e){if("undefined"==typeof AMap)throw new Error("AMap api is not loaded");if(a)throw new Error("Only one amap component is allowed");var i=e.getAMap(),s=e.get("echartsLayerInteractive");if(!i){var h=n.getDom(),m=n.getZr().painter,l=m.getViewportRoot();l.className=o+"-ec-layer",l.style.visibility="hidden";var d="ec-extension-"+o,f=h.querySelector("."+d);f&&(l.style.left="0px",l.style.top="0px",h.removeChild(f)),(f=document.createElement("div")).className=d,f.style.cssText="position:absolute;top:0;left:0;bottom:0;right:0;",h.appendChild(f);var u=t.util.clone(e.get());"echartsLayerZIndex"in u&&r("DEPRECATED","the option `echartsLayerZIndex` has been removed since v1.9.0, use `echartsLayerInteractive` instead."),t.util.each(c,(function(e){delete u[e]})),(i=new AMap.Map(f,u)).on("complete",(function(){f.querySelector(".amap-maps").appendChild(l),l.style.visibility=""})),e.setAMap(i),e.setEChartsLayer(l),m.getViewportRootOffset=function(){return{offsetLeft:0,offsetTop:0}}}e.__echartsLayerInteractive!==s&&(e.setEChartsLayerInteractive(s),e.__echartsLayerInteractive=s);var v=e.get("center"),g=e.get("zoom");if(v&&g){var y=i.getCenter(),_=i.getZoom();e.centerOrZoomChanged([y.lng,y.lat],_)&&i.setZoomAndCenter(g,new AMap.LngLat(v[0],v[1]))}var L=e.__mapStyle,M=e.get("mapStyle");if(L!==M&&i.setMapStyle(e.__mapStyle=M),i.setLang){var C=e.__mapLang,A=e.get("lang");C!==A&&i.setLang(e.__mapLang=A)}else r("CAVEAT","The current map doesn't support `setLang` API!",!0);(a=new p(i,n)).setMapOffset(e.__mapOffset||[0,0]),a.setZoom(g),a.setCenter(v),e.coordinateSystem=a})),e.eachSeries((function(e){e.get("coordinateSystem")===o&&(e.coordinateSystem=a)})),a&&[a]},h.dimensions=p.dimensions=["lng","lat"],h.type=o;var m,l={type:o,setAMap:function(e){this.__amap=e},getAMap:function(){return this.__amap},setEChartsLayer:function(e){this.__echartsLayer=e},getEChartsLayer:function(){return this.__echartsLayer},setEChartsLayerVisibility:function(e){this.__echartsLayer.style.display=e?"block":"none"},setEChartsLayerInteractive:function(e){this.option.echartsLayerInteractive=!!e,this.__echartsLayer.style.pointerEvents=e?"auto":"none"},setCenterAndZoom:function(e,t){this.option.center=e,this.option.zoom=t},centerOrZoomChanged:function(e,t){var n,a,o=this.option;return a=o.center,!((n=e)&&a&&n[0]===a[0]&&n[1]===a[1]&&t===o.zoom)},defaultOption:{center:[116.397428,39.90923],zoom:5,isHotspot:!1,resizeEnable:!0,echartsLayerInteractive:!0,renderOnMoving:!0,largeMode:!1,returnMapCameraState:!1}},d=a?t.ComponentModel.extend(l):l,f={type:o,init:function(){this._isFirstRender=!0,m=!AMap.v&&AMap.version&&AMap.version.split(".")[0]>=2},render:function(e,n,a){var o=this,i=!0,r=e.getAMap(),s=a.getZr().painter.getViewportRoot(),c=r.getContainer(),p=e.coordinateSystem,h=e.get("renderOnMoving"),l=e.get("resizeEnable"),d=e.get("largeMode"),f=e.get("returnMapCameraState"),u=r.getViewMode_(),v="3D"===u,g=function(t){if(!i){var n=c.style,o=[-parseInt(n.left,10)||0,-parseInt(n.top,10)||0],h=s.style,m=o[0]+"px",l=o[1]+"px";h.left!==m&&(h.left=m),h.top!==l&&(h.top=l),p.setMapOffset(e.__mapOffset=o);var d={type:"amapRoam",animation:{duration:0}};if(f){var v=(t=t||{}).center;v||(v=[(v=r.getCenter()).lng,v.lat]),d.camera={viewMode:u,center:v,zoom:t.zoom||r.getZoom(),rotation:null==t.rotation?r.getRotation():t.rotation,pitch:null==t.pitch?r.getPitch():t.pitch,scale:r.getScale(),bounds:r.getBounds()}}a.dispatchAction(d)}};if(r.off("mapmove",this._moveHandler),r.off("moveend",this._moveHandler),r.off("viewchange",this._moveHandler),r.off("camerachange",this._moveHandler),r.off("zoom",this._moveHandler),this._resizeHandler&&r.off("resize",this._resizeHandler),this._moveStartHandler&&r.off("movestart",this._moveStartHandler),this._moveEndHandler&&(r.off("moveend",this._moveEndHandler),r.off("zoomend",this._moveEndHandler)),r.on(h?m?"viewchange":v?"camerachange":"mapmove":"moveend",!m&&d?g=t.throttle(g,20,!0):g),this._moveHandler=g,!h||m&&v||r.on("zoom",g),!h){r.on("movestart",this._moveStartHandler=function(){setTimeout((function(){e.setEChartsLayerVisibility(!1)}),0)});var y=this._moveEndHandler=function(t){(!t||"moveend"!==t.type)&&g(t),setTimeout((function(){e.setEChartsLayerVisibility(!0)}),m||!d?0:20)};if(r.on("moveend",y),r.on("zoomend",y),this._isFirstRender&&v){var _=r.setPitch,L=r.setRotation;r.setPitch=function(){_.apply(this,arguments),y()},r.setRotation=function(){L.apply(this,arguments),y()}}}if(l){var M=function(){clearTimeout(o._resizeTimeout),o._resizeTimeout=setTimeout((function(){return t.getInstanceByDom(a.getDom()).resize()}),0)};!m&&d&&(M=t.throttle(M,20,!0)),r.on("resize",this._resizeHandler=M)}this._isFirstRender=i=!1},dispose:function(){clearTimeout(this._resizeTimeout),i={};var e=this.__model;e&&(e.getAMap().destroy(),e.setAMap(null),e.setEChartsLayer(null),e.coordinateSystem&&(e.coordinateSystem.setAMap(null),e.coordinateSystem=null)),delete this._moveHandler,delete this._moveStartHandler,delete this._moveEndHandler,delete this._resizeHandler,delete this._resizeTimeout}},u=a?t.ComponentView.extend(f):f;function v(e){(!a||5==n[0]&&n[1]<4)&&e.registerLayout((function(e){e.eachSeriesByType("pie",(function(e){var t=e.coordinateSystem,n=e.getData(),a=n.mapDimension("value");if(t&&t.type===o){var i=e.get("center"),r=t.dataToPoint(i),s=r[0],c=r[1];n.each(a,(function(e,t){var a=n.getItemLayout(t);a.cx=s,a.cy=c}))}}))})),a?e.registerComponentModel(d):e.extendComponentModel(d),a?e.registerComponentView(u):e.extendComponentView(u),e.registerCoordinateSystem(o,p),e.registerAction({type:o+"Roam",event:o+"Roam",update:"updateLayout"},(function(e,t){t.eachComponent(o,(function(e){var t=e.getAMap(),n=t.getCenter();e.setCenterAndZoom([n.lng,n.lat],t.getZoom())}))}))}a?t.use(v):v(t),e.name="echarts-extension-amap",e.version="1.12.0"})); 30 | //# sourceMappingURL=echarts-extension-amap.min.js.map 31 | -------------------------------------------------------------------------------- /src/AMapCoordSys.js: -------------------------------------------------------------------------------- 1 | import { util as zrUtil, graphic, matrix } from 'echarts/lib/echarts' 2 | import { COMPONENT_TYPE, logWarn } from './helper' 3 | 4 | function dataToCoordSize(dataSize, dataItem) { 5 | dataItem = dataItem || [0, 0]; 6 | return zrUtil.map( 7 | [0, 1], 8 | function(dimIdx) { 9 | const val = dataItem[dimIdx] 10 | const halfSize = dataSize[dimIdx] / 2 11 | const p1 = [] 12 | const p2 = [] 13 | p1[dimIdx] = val - halfSize 14 | p2[dimIdx] = val + halfSize 15 | p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx] 16 | return Math.abs( 17 | this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx] 18 | ) 19 | }, 20 | this 21 | ) 22 | } 23 | 24 | // exclude private and unsupported options 25 | const excludedOptions = [ 26 | 'echartsLayerZIndex', // DEPRECATED since v1.9.0 27 | 'echartsLayerInteractive', 28 | 'renderOnMoving', 29 | 'largeMode', 30 | 'returnMapCameraState', 31 | 'layers' 32 | ] 33 | 34 | function AMapCoordSys(amap, api) { 35 | this._amap = amap 36 | this._api = api 37 | this._mapOffset = [0, 0] 38 | // this.dimensions = ['lng', 'lat'] 39 | } 40 | 41 | const AMapCoordSysProto = AMapCoordSys.prototype 42 | 43 | AMapCoordSysProto.setZoom = function(zoom) { 44 | this._zoom = zoom 45 | } 46 | 47 | AMapCoordSysProto.setCenter = function(center) { 48 | const lnglat = new AMap.LngLat(center[0], center[1]) 49 | this._center = this._amap.lngLatToContainer(lnglat) 50 | } 51 | 52 | AMapCoordSysProto.setMapOffset = function(mapOffset) { 53 | this._mapOffset = mapOffset 54 | } 55 | 56 | AMapCoordSysProto.setAMap = function(amap) { 57 | this._amap = amap 58 | } 59 | 60 | AMapCoordSysProto.getAMap = function() { 61 | return this._amap 62 | } 63 | 64 | AMapCoordSysProto.dataToPoint = function(data) { 65 | const lnglat = new AMap.LngLat(data[0], data[1]) 66 | const px = this._amap.lngLatToContainer(lnglat) 67 | const mapOffset = this._mapOffset 68 | return [px.x - mapOffset[0], px.y - mapOffset[1]] 69 | } 70 | 71 | AMapCoordSysProto.pointToData = function(pt) { 72 | const mapOffset = this._mapOffset 73 | const lnglat = this._amap.containerToLngLat( 74 | new AMap.Pixel( 75 | pt[0] + mapOffset[0], 76 | pt[1] + mapOffset[1] 77 | ) 78 | ) 79 | return [lnglat.lng, lnglat.lat] 80 | } 81 | 82 | AMapCoordSysProto.getViewRect = function() { 83 | const api = this._api 84 | return new graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()) 85 | } 86 | 87 | AMapCoordSysProto.getRoamTransform = function() { 88 | return matrix.create() 89 | } 90 | 91 | AMapCoordSysProto.prepareCustoms = function() { 92 | const rect = this.getViewRect() 93 | return { 94 | coordSys: { 95 | type: COMPONENT_TYPE, 96 | x: rect.x, 97 | y: rect.y, 98 | width: rect.width, 99 | height: rect.height 100 | }, 101 | api: { 102 | coord: zrUtil.bind(this.dataToPoint, this), 103 | size: zrUtil.bind(dataToCoordSize, this) 104 | } 105 | } 106 | } 107 | 108 | AMapCoordSysProto.convertToPixel = function(ecModel, finder, value) { 109 | // here we don't use finder as only one amap component is allowed 110 | return this.dataToPoint(value); 111 | } 112 | 113 | AMapCoordSysProto.convertFromPixel = function(ecModel, finder, value) { 114 | // here we don't use finder as only one amap component is allowed 115 | return this.pointToData(value); 116 | } 117 | 118 | // less useful 119 | // AMapCoordSysProto.containPoint = function(point) { 120 | // return this._amap.getBounds().contains(this.pointToData(point)); 121 | // } 122 | 123 | AMapCoordSys.create = function(ecModel, api) { 124 | let amapCoordSys 125 | ecModel.eachComponent(COMPONENT_TYPE, function(amapModel) { 126 | if (typeof AMap === 'undefined') { 127 | throw new Error('AMap api is not loaded') 128 | } 129 | if (amapCoordSys) { 130 | throw new Error('Only one amap component is allowed') 131 | } 132 | let amap = amapModel.getAMap() 133 | const echartsLayerInteractive = amapModel.get('echartsLayerInteractive') 134 | if (!amap) { 135 | const root = api.getDom() 136 | const painter = api.getZr().painter 137 | const viewportRoot = painter.getViewportRoot() 138 | viewportRoot.className = COMPONENT_TYPE + '-ec-layer' 139 | // PENDING not hidden? 140 | viewportRoot.style.visibility = 'hidden' 141 | const className = 'ec-extension-' + COMPONENT_TYPE 142 | // Not support IE8 143 | let amapRoot = root.querySelector('.' + className) 144 | if (amapRoot) { 145 | // Reset viewport left and top, which will be changed 146 | // in moving handler in AMapView 147 | viewportRoot.style.left = '0px' 148 | viewportRoot.style.top = '0px' 149 | root.removeChild(amapRoot) 150 | } 151 | amapRoot = document.createElement('div') 152 | amapRoot.className = className 153 | amapRoot.style.cssText = 'position:absolute;top:0;left:0;bottom:0;right:0;' 154 | root.appendChild(amapRoot) 155 | 156 | const options = zrUtil.clone(amapModel.get()) 157 | if ('echartsLayerZIndex' in options) { 158 | logWarn('DEPRECATED', 'the option `echartsLayerZIndex` has been removed since v1.9.0, use `echartsLayerInteractive` instead.') 159 | } 160 | // delete excluded options 161 | zrUtil.each(excludedOptions, function(key) { 162 | delete options[key] 163 | }) 164 | 165 | amap = new AMap.Map(amapRoot, options) 166 | 167 | // PENDING: should update the model option when the user call map.setXXX? 168 | 169 | // const nativeSetMapStyle = amap.setMapStyle 170 | // const nativeSetLang = amap.setLang 171 | 172 | // // PENDING 173 | // amap.setMapStyle = function () { 174 | // nativeSetMapStyle.apply(this, arguments) 175 | // amapModel.__mapStyle = amap.getMapStyle() 176 | // } 177 | 178 | // // PENDING 179 | // nativeSetLang && (amap.setLang = function() { 180 | // nativeSetLang.apply(this, arguments) 181 | // amapModel.__mapLang = amap.getLang() 182 | // }) 183 | 184 | // use `complete` callback to avoid NPE when first load amap 185 | amap.on('complete', function() { 186 | amapRoot.querySelector('.amap-maps').appendChild(viewportRoot) 187 | // PENDING 188 | viewportRoot.style.visibility = '' 189 | }) 190 | 191 | amapModel.setAMap(amap) 192 | amapModel.setEChartsLayer(viewportRoot) 193 | 194 | // Override 195 | painter.getViewportRootOffset = function() { 196 | return { offsetLeft: 0, offsetTop: 0 } 197 | } 198 | } 199 | 200 | const oldEChartsLayerInteractive = amapModel.__echartsLayerInteractive 201 | if (oldEChartsLayerInteractive !== echartsLayerInteractive) { 202 | amapModel.setEChartsLayerInteractive(echartsLayerInteractive) 203 | amapModel.__echartsLayerInteractive = echartsLayerInteractive 204 | } 205 | 206 | const center = amapModel.get('center') 207 | const zoom = amapModel.get('zoom') 208 | if (center && zoom) { 209 | const amapCenter = amap.getCenter() 210 | const amapZoom = amap.getZoom() 211 | const centerOrZoomChanged = amapModel.centerOrZoomChanged( 212 | [amapCenter.lng, amapCenter.lat], 213 | amapZoom 214 | ) 215 | if (centerOrZoomChanged) { 216 | amap.setZoomAndCenter(zoom, new AMap.LngLat(center[0], center[1])) 217 | } 218 | } 219 | 220 | // update map style(#13) 221 | const originalMapStyle = amapModel.__mapStyle 222 | const newMapStyle = amapModel.get('mapStyle') 223 | if (originalMapStyle !== newMapStyle) { 224 | amap.setMapStyle(amapModel.__mapStyle = newMapStyle) 225 | } 226 | 227 | // update map lang 228 | // PENDING: AMap 2.x does not support `setLang` yet 229 | if (amap.setLang) { 230 | const originalMapLang = amapModel.__mapLang 231 | const newMapLang = amapModel.get('lang') 232 | if (originalMapLang !== newMapLang) { 233 | amap.setLang(amapModel.__mapLang = newMapLang) 234 | } 235 | } 236 | else { 237 | logWarn('CAVEAT', 'The current map doesn\'t support `setLang` API!', true) 238 | } 239 | 240 | amapCoordSys = new AMapCoordSys(amap, api) 241 | amapCoordSys.setMapOffset(amapModel.__mapOffset || [0, 0]) 242 | amapCoordSys.setZoom(zoom) 243 | amapCoordSys.setCenter(center) 244 | 245 | amapModel.coordinateSystem = amapCoordSys 246 | }) 247 | 248 | ecModel.eachSeries(function(seriesModel) { 249 | if (seriesModel.get('coordinateSystem') === COMPONENT_TYPE) { 250 | // inject coordinate system 251 | seriesModel.coordinateSystem = amapCoordSys 252 | } 253 | }) 254 | 255 | // return created coordinate systems 256 | return amapCoordSys && [amapCoordSys] 257 | } 258 | 259 | AMapCoordSysProto.dimensions = AMapCoordSys.dimensions = ['lng', 'lat'] 260 | 261 | AMapCoordSysProto.type = COMPONENT_TYPE 262 | 263 | 264 | export default AMapCoordSys 265 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![NPM version](https://img.shields.io/npm/v/echarts-extension-amap.svg?style=flat)](https://www.npmjs.org/package/echarts-extension-amap) 2 | [![Build Status](https://github.com/plainheart/echarts-extension-amap/actions/workflows/build.yml/badge.svg)](https://github.com/plainheart/echarts-extension-amap/actions/workflows/build.yml) 3 | [![NPM Downloads](https://img.shields.io/npm/dm/echarts-extension-amap.svg)](https://npmcharts.com/compare/echarts-extension-amap?minimal=true) 4 | [![jsDelivr Downloads](https://data.jsdelivr.com/v1/package/npm/echarts-extension-amap/badge?style=rounded)](https://www.jsdelivr.com/package/npm/echarts-extension-amap) 5 | [![License](https://img.shields.io/npm/l/echarts-extension-amap.svg)](https://github.com/plainheart/echarts-extension-amap/blob/master/LICENSE) 6 | 7 | ## AMap extension for Apache ECharts 8 | 9 | [中文说明](https://github.com/plainheart/echarts-extension-amap/blob/master/README.zh-CN.md) 10 | 11 | [Online example on CodePen](https://codepen.io/plainheart/pen/qBbdNYx) 12 | 13 | This is an AMap extension for [Apache ECharts](https://echarts.apache.org/en/index.html) which is used to display visualizations such as [Scatter](https://echarts.apache.org/en/option.html#series-scatter), [Lines](https://echarts.apache.org/en/option.html#series-lines), [Heatmap](https://echarts.apache.org/en/option.html#series-heatmap), and [Pie](https://echarts.apache.org/en/option.html#series-pie). 14 | 15 | ### Examples 16 | 17 | Scatter: [examples/scatter.html](https://github.com/plainheart/echarts-extension-amap/blob/master/examples/scatter.html) 18 | 19 | ![Preview-Scatter](https://user-images.githubusercontent.com/26999792/53300484-e2979680-3882-11e9-8fb4-143c4ca4c416.png) 20 | 21 | Heatmap: [examples/heatmap.html](https://github.com/plainheart/echarts-extension-amap/blob/master/examples/heatmap.html) 22 | 23 | ![Preview-Heatmap](https://user-images.githubusercontent.com/26999792/101314208-fadb7880-3892-11eb-902a-8f6f41ffe0fc.png) 24 | 25 | Lines: [examples/lines.html](https://github.com/plainheart/echarts-extension-amap/blob/master/examples/lines.html) 26 | 27 | ![Preview-Lines](https://user-images.githubusercontent.com/26999792/101313379-fca43c80-3890-11eb-9dea-46230dc432d5.gif) 28 | 29 | Pie: [examples/pie.html](https://github.com/plainheart/echarts-extension-amap/blob/master/examples/pie.html) (**Since v1.11.0**) 30 | 31 | ![Preview-Pie](https://user-images.githubusercontent.com/26999792/193215980-cd6736f5-a63d-4085-8012-d519e9e78398.png) 32 | 33 | ### Installation 34 | 35 | ```shell 36 | npm install echarts-extension-amap --save 37 | ``` 38 | 39 | ### Import 40 | 41 | Import packaged distribution file `echarts-extension-amap.min.js` and add AMap API script and ECharts script. 42 | 43 | ```html 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | ``` 52 | 53 | You can also import this extension by `require` or `import` if you are using `webpack` or any other bundler. 54 | 55 | ```js 56 | // use require 57 | require('echarts'); 58 | require('echarts-extension-amap'); 59 | 60 | // use import 61 | import * as echarts from 'echarts'; 62 | import 'echarts-extension-amap'; 63 | ``` 64 | 65 | > If importing dynamically the API script is needed, it's suggested to use [amap-jsapi-loader](https://www.npmjs.com/package/@amap/amap-jsapi-loader) or wrap a dynamic and asynchronized script loader manually through `Promise`. 66 | 67 | **Use CDN** 68 | 69 | [**jsDelivr**](https://www.jsdelivr.com/) 70 | 71 | Use the latest version 72 | 73 | [https://cdn.jsdelivr.net/npm/echarts-extension-amap/dist/echarts-extension-amap.min.js](https://cdn.jsdelivr.net/npm/echarts-extension-amap/dist/echarts-extension-amap.min.js) 74 | 75 | Use a specific version 76 | 77 | [https://cdn.jsdelivr.net/npm/echarts-extension-amap@1.12.0/dist/echarts-extension-amap.min.js](https://cdn.jsdelivr.net/npm/echarts-extension-amap@1.12.0/dist/echarts-extension-amap.min.js) 78 | 79 | [**unpkg**](https://unpkg.com/) 80 | 81 | Use the latest version 82 | 83 | [https://unpkg.com/echarts-extension-amap/dist/echarts-extension-amap.min.js](https://unpkg.com/echarts-extension-amap/dist/echarts-extension-amap.min.js) 84 | 85 | Use a specific version 86 | 87 | [https://unpkg.com/echarts-extension-amap@1.12.0/dist/echarts-extension-amap.min.js](https://unpkg.com/echarts-extension-amap@1.12.0/dist/echarts-extension-amap.min.js) 88 | 89 | This extension will register itself as a component of `echarts` after it is imported. 90 | 91 | **Apache ECharts 5 import on demand** 92 | 93 | Apache ECharts has provided us the [new tree-shaking API](https://echarts.apache.org/en/tutorial.html#Use%20ECharts%20with%20bundler%20and%20NPM) since v5.0.1. This is how to use it in this extension: 94 | 95 | ```ts 96 | // import scatter, effectScatter and amap extension component on demand 97 | import * as echarts from 'echarts/core'; 98 | import { 99 | ScatterChart, 100 | ScatterSeriesOption, 101 | EffectScatterChart, 102 | EffectScatterSeriesOption 103 | } from 'echarts/charts'; 104 | import { 105 | TooltipComponent, 106 | TitleComponentOption 107 | } from 'echarts/components'; 108 | import { CanvasRenderer } from 'echarts/renderers'; 109 | import { 110 | install as AMapComponent, 111 | AMapComponentOption 112 | } from 'echarts-extension-amap/export'; 113 | 114 | // import the official type definition for AMap 2.0 115 | import '@amap/amap-jsapi-types'; 116 | 117 | // compose required options 118 | type ECOption = echarts.ComposeOption< 119 | | ScatterSeriesOption 120 | | EffectScatterSeriesOption 121 | | TitleComponentOption 122 | // unite AMapComponentOption with the initial options of AMap `AMap.MapOptions` 123 | > & AMapComponentOption; 124 | 125 | // register renderers, components and charts 126 | echarts.use([ 127 | CanvasRenderer, 128 | TooltipComponent, 129 | AMapComponent, 130 | ScatterChart, 131 | EffectScatterChart 132 | ]); 133 | 134 | // define ECharts option 135 | const option: ECOption = { 136 | // AMap extension option 137 | amap: { 138 | // ... 139 | }, 140 | title: { 141 | // ... 142 | }, 143 | series: [ 144 | { 145 | type: 'scatter', 146 | // Use AMap coordinate system 147 | coordinateSystem: 'amap', 148 | // ... 149 | } 150 | ] 151 | // ... 152 | }; 153 | ``` 154 | 155 | ### Usage 156 | 157 | ```js 158 | option = { 159 | // load amap component 160 | amap: { 161 | // enable 3D mode 162 | // Note that it's suggested to enable 3D mode to improve echarts rendering. 163 | viewMode: '3D', 164 | // initial options of AMap 165 | // See https://lbs.amap.com/api/javascript-api/reference/map#MapOption for details 166 | // initial map center [lng, lat] 167 | center: [108.39, 39.9], 168 | // initial map zoom 169 | zoom: 4, 170 | // whether the map and echarts automatically handles browser window resize to update itself. 171 | resizeEnable: true, 172 | // customized map style, see https://lbs.amap.com/dev/mapstyle/index for details 173 | mapStyle: 'amap://styles/dark', 174 | // whether echarts layer should be rendered when the map is moving. Default is true. 175 | // if false, it will only be re-rendered after the map `moveend`. 176 | // It's better to set this option to false if data is large. 177 | renderOnMoving: true, 178 | // the zIndex of echarts layer for AMap, default value is 2000. 179 | // deprecated since v1.9.0, use `echartsLayerInteractive` instead. 180 | echartsLayerZIndex: 2019, 181 | // whether echarts layer is interactive. Default value is true 182 | // supported since v1.9.0 183 | echartsLayerInteractive: true, 184 | // whether to enable large mode. Default value is false 185 | // supported since v1.9.0 186 | largeMode: false 187 | // Note: Please DO NOT use the initial option `layers` to add Satellite/RoadNet/Other layers now. 188 | // There are some bugs about it, we can use `amap.add` instead. 189 | // Refer to the codes at the bottom. 190 | 191 | // More initial options... 192 | }, 193 | series: [ 194 | { 195 | type: 'scatter', 196 | // use `amap` as the coordinate system 197 | coordinateSystem: 'amap', 198 | // data items [[lng, lat, value], [lng, lat, value], ...] 199 | data: [[120, 30, 8], [120.1, 30.2, 20]], 200 | encode: { 201 | // encode the third element of data item as the `value` dimension 202 | value: 2 203 | } 204 | } 205 | ] 206 | }; 207 | 208 | // Get AMap extension component 209 | var amapComponent = chart.getModel().getComponent('amap'); 210 | // Get the instance of AMap 211 | var amap = amapComponent.getAMap(); 212 | // Add some controls provided by AMap. 213 | amap.addControl(new AMap.Scale()); 214 | amap.addControl(new AMap.ToolBar()); 215 | // Add SatelliteLayer and RoadNetLayer to map 216 | var satelliteLayer = new AMap.TileLayer.Satellite(); 217 | var roadNetLayer = new AMap.TileLayer.RoadNet(); 218 | amap.add([satelliteLayer, roadNetLayer]); 219 | // Add a marker to map 220 | amap.add(new AMap.Marker({ 221 | position: [115, 35] 222 | })); 223 | // Make the overlay layer of AMap interactive 224 | amapComponent.setEChartsLayerInteractive(false); 225 | ``` 226 | -------------------------------------------------------------------------------- /examples/scatter_zh_CN.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Scatter 散点图 | echarts-extension-amap 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 29 | 30 | 31 |
32 | 33 | 548 | 549 | 550 | -------------------------------------------------------------------------------- /examples/scatter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Scatter | echarts-extension-amap 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 29 | 30 | 31 |
32 | 33 | 556 | 557 | 558 | -------------------------------------------------------------------------------- /dist/echarts-extension-amap.esm.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * echarts-extension-amap 3 | * @version 1.12.0 4 | * @author plainheart 5 | * 6 | * MIT License 7 | * 8 | * Copyright (c) 2019-2024 Zhongxiang Wang 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in all 18 | * copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | */ 29 | import * as echarts from 'echarts/lib/echarts'; 30 | import { version as version$1, graphic, matrix, util, ComponentModel, ComponentView, throttle, getInstanceByDom } from 'echarts/lib/echarts'; 31 | 32 | var ecVer = version$1.split('.'); 33 | var isNewEC = ecVer[0] > 4; 34 | var COMPONENT_TYPE = 'amap'; 35 | 36 | /* global AMap */ 37 | 38 | // The version property is `AMap.v` in AMap 1.x, 39 | // but `AMap.version` may also exist (See #51) 40 | // In AMap 2.x, it's `AMap.version` (Not sure if `AMap.v` exists) 41 | // use function instead of constant to allow importing the plugin before AMap is loaded 42 | var isAMap2X = function isAMap2X() { 43 | return !AMap.v && AMap.version && AMap.version.split('.')[0] >= 2; 44 | }; 45 | function v2Equal(a, b) { 46 | return a && b && a[0] === b[0] && a[1] === b[1]; 47 | } 48 | var logMap = {}; 49 | function logWarn(tag, msg, once) { 50 | var log = "[ECharts][Extension][AMap]".concat(tag ? ' ' + tag + ':' : '', " ").concat(msg); 51 | once && logMap[log] || console.warn(log); 52 | once && (logMap[log] = true); 53 | } 54 | function clearLogMap() { 55 | logMap = {}; 56 | } 57 | 58 | function dataToCoordSize(dataSize, dataItem) { 59 | dataItem = dataItem || [0, 0]; 60 | return util.map([0, 1], function (dimIdx) { 61 | var val = dataItem[dimIdx]; 62 | var halfSize = dataSize[dimIdx] / 2; 63 | var p1 = []; 64 | var p2 = []; 65 | p1[dimIdx] = val - halfSize; 66 | p2[dimIdx] = val + halfSize; 67 | p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]; 68 | return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]); 69 | }, this); 70 | } 71 | 72 | // exclude private and unsupported options 73 | var excludedOptions = ['echartsLayerZIndex', 74 | // DEPRECATED since v1.9.0 75 | 'echartsLayerInteractive', 'renderOnMoving', 'largeMode', 'returnMapCameraState', 'layers']; 76 | function AMapCoordSys(amap, api) { 77 | this._amap = amap; 78 | this._api = api; 79 | this._mapOffset = [0, 0]; 80 | // this.dimensions = ['lng', 'lat'] 81 | } 82 | var AMapCoordSysProto = AMapCoordSys.prototype; 83 | AMapCoordSysProto.setZoom = function (zoom) { 84 | this._zoom = zoom; 85 | }; 86 | AMapCoordSysProto.setCenter = function (center) { 87 | var lnglat = new AMap.LngLat(center[0], center[1]); 88 | this._center = this._amap.lngLatToContainer(lnglat); 89 | }; 90 | AMapCoordSysProto.setMapOffset = function (mapOffset) { 91 | this._mapOffset = mapOffset; 92 | }; 93 | AMapCoordSysProto.setAMap = function (amap) { 94 | this._amap = amap; 95 | }; 96 | AMapCoordSysProto.getAMap = function () { 97 | return this._amap; 98 | }; 99 | AMapCoordSysProto.dataToPoint = function (data) { 100 | var lnglat = new AMap.LngLat(data[0], data[1]); 101 | var px = this._amap.lngLatToContainer(lnglat); 102 | var mapOffset = this._mapOffset; 103 | return [px.x - mapOffset[0], px.y - mapOffset[1]]; 104 | }; 105 | AMapCoordSysProto.pointToData = function (pt) { 106 | var mapOffset = this._mapOffset; 107 | var lnglat = this._amap.containerToLngLat(new AMap.Pixel(pt[0] + mapOffset[0], pt[1] + mapOffset[1])); 108 | return [lnglat.lng, lnglat.lat]; 109 | }; 110 | AMapCoordSysProto.getViewRect = function () { 111 | var api = this._api; 112 | return new graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()); 113 | }; 114 | AMapCoordSysProto.getRoamTransform = function () { 115 | return matrix.create(); 116 | }; 117 | AMapCoordSysProto.prepareCustoms = function () { 118 | var rect = this.getViewRect(); 119 | return { 120 | coordSys: { 121 | type: COMPONENT_TYPE, 122 | x: rect.x, 123 | y: rect.y, 124 | width: rect.width, 125 | height: rect.height 126 | }, 127 | api: { 128 | coord: util.bind(this.dataToPoint, this), 129 | size: util.bind(dataToCoordSize, this) 130 | } 131 | }; 132 | }; 133 | AMapCoordSysProto.convertToPixel = function (ecModel, finder, value) { 134 | // here we don't use finder as only one amap component is allowed 135 | return this.dataToPoint(value); 136 | }; 137 | AMapCoordSysProto.convertFromPixel = function (ecModel, finder, value) { 138 | // here we don't use finder as only one amap component is allowed 139 | return this.pointToData(value); 140 | }; 141 | 142 | // less useful 143 | // AMapCoordSysProto.containPoint = function(point) { 144 | // return this._amap.getBounds().contains(this.pointToData(point)); 145 | // } 146 | 147 | AMapCoordSys.create = function (ecModel, api) { 148 | var amapCoordSys; 149 | ecModel.eachComponent(COMPONENT_TYPE, function (amapModel) { 150 | if (typeof AMap === 'undefined') { 151 | throw new Error('AMap api is not loaded'); 152 | } 153 | if (amapCoordSys) { 154 | throw new Error('Only one amap component is allowed'); 155 | } 156 | var amap = amapModel.getAMap(); 157 | var echartsLayerInteractive = amapModel.get('echartsLayerInteractive'); 158 | if (!amap) { 159 | var root = api.getDom(); 160 | var painter = api.getZr().painter; 161 | var viewportRoot = painter.getViewportRoot(); 162 | viewportRoot.className = COMPONENT_TYPE + '-ec-layer'; 163 | // PENDING not hidden? 164 | viewportRoot.style.visibility = 'hidden'; 165 | var className = 'ec-extension-' + COMPONENT_TYPE; 166 | // Not support IE8 167 | var amapRoot = root.querySelector('.' + className); 168 | if (amapRoot) { 169 | // Reset viewport left and top, which will be changed 170 | // in moving handler in AMapView 171 | viewportRoot.style.left = '0px'; 172 | viewportRoot.style.top = '0px'; 173 | root.removeChild(amapRoot); 174 | } 175 | amapRoot = document.createElement('div'); 176 | amapRoot.className = className; 177 | amapRoot.style.cssText = 'position:absolute;top:0;left:0;bottom:0;right:0;'; 178 | root.appendChild(amapRoot); 179 | var options = util.clone(amapModel.get()); 180 | if ('echartsLayerZIndex' in options) { 181 | logWarn('DEPRECATED', 'the option `echartsLayerZIndex` has been removed since v1.9.0, use `echartsLayerInteractive` instead.'); 182 | } 183 | // delete excluded options 184 | util.each(excludedOptions, function (key) { 185 | delete options[key]; 186 | }); 187 | amap = new AMap.Map(amapRoot, options); 188 | 189 | // PENDING: should update the model option when the user call map.setXXX? 190 | 191 | // const nativeSetMapStyle = amap.setMapStyle 192 | // const nativeSetLang = amap.setLang 193 | 194 | // // PENDING 195 | // amap.setMapStyle = function () { 196 | // nativeSetMapStyle.apply(this, arguments) 197 | // amapModel.__mapStyle = amap.getMapStyle() 198 | // } 199 | 200 | // // PENDING 201 | // nativeSetLang && (amap.setLang = function() { 202 | // nativeSetLang.apply(this, arguments) 203 | // amapModel.__mapLang = amap.getLang() 204 | // }) 205 | 206 | // use `complete` callback to avoid NPE when first load amap 207 | amap.on('complete', function () { 208 | amapRoot.querySelector('.amap-maps').appendChild(viewportRoot); 209 | // PENDING 210 | viewportRoot.style.visibility = ''; 211 | }); 212 | amapModel.setAMap(amap); 213 | amapModel.setEChartsLayer(viewportRoot); 214 | 215 | // Override 216 | painter.getViewportRootOffset = function () { 217 | return { 218 | offsetLeft: 0, 219 | offsetTop: 0 220 | }; 221 | }; 222 | } 223 | var oldEChartsLayerInteractive = amapModel.__echartsLayerInteractive; 224 | if (oldEChartsLayerInteractive !== echartsLayerInteractive) { 225 | amapModel.setEChartsLayerInteractive(echartsLayerInteractive); 226 | amapModel.__echartsLayerInteractive = echartsLayerInteractive; 227 | } 228 | var center = amapModel.get('center'); 229 | var zoom = amapModel.get('zoom'); 230 | if (center && zoom) { 231 | var amapCenter = amap.getCenter(); 232 | var amapZoom = amap.getZoom(); 233 | var centerOrZoomChanged = amapModel.centerOrZoomChanged([amapCenter.lng, amapCenter.lat], amapZoom); 234 | if (centerOrZoomChanged) { 235 | amap.setZoomAndCenter(zoom, new AMap.LngLat(center[0], center[1])); 236 | } 237 | } 238 | 239 | // update map style(#13) 240 | var originalMapStyle = amapModel.__mapStyle; 241 | var newMapStyle = amapModel.get('mapStyle'); 242 | if (originalMapStyle !== newMapStyle) { 243 | amap.setMapStyle(amapModel.__mapStyle = newMapStyle); 244 | } 245 | 246 | // update map lang 247 | // PENDING: AMap 2.x does not support `setLang` yet 248 | if (amap.setLang) { 249 | var originalMapLang = amapModel.__mapLang; 250 | var newMapLang = amapModel.get('lang'); 251 | if (originalMapLang !== newMapLang) { 252 | amap.setLang(amapModel.__mapLang = newMapLang); 253 | } 254 | } else { 255 | logWarn('CAVEAT', 'The current map doesn\'t support `setLang` API!', true); 256 | } 257 | amapCoordSys = new AMapCoordSys(amap, api); 258 | amapCoordSys.setMapOffset(amapModel.__mapOffset || [0, 0]); 259 | amapCoordSys.setZoom(zoom); 260 | amapCoordSys.setCenter(center); 261 | amapModel.coordinateSystem = amapCoordSys; 262 | }); 263 | ecModel.eachSeries(function (seriesModel) { 264 | if (seriesModel.get('coordinateSystem') === COMPONENT_TYPE) { 265 | // inject coordinate system 266 | seriesModel.coordinateSystem = amapCoordSys; 267 | } 268 | }); 269 | 270 | // return created coordinate systems 271 | return amapCoordSys && [amapCoordSys]; 272 | }; 273 | AMapCoordSysProto.dimensions = AMapCoordSys.dimensions = ['lng', 'lat']; 274 | AMapCoordSysProto.type = COMPONENT_TYPE; 275 | 276 | var AMapModel = { 277 | type: COMPONENT_TYPE, 278 | setAMap: function setAMap(amap) { 279 | this.__amap = amap; 280 | }, 281 | getAMap: function getAMap() { 282 | return this.__amap; 283 | }, 284 | setEChartsLayer: function setEChartsLayer(layer) { 285 | this.__echartsLayer = layer; 286 | }, 287 | getEChartsLayer: function getEChartsLayer() { 288 | return this.__echartsLayer; 289 | }, 290 | setEChartsLayerVisibility: function setEChartsLayerVisibility(visible) { 291 | this.__echartsLayer.style.display = visible ? 'block' : 'none'; 292 | }, 293 | // FIXME: NOT SUPPORT <= IE 10 294 | setEChartsLayerInteractive: function setEChartsLayerInteractive(interactive) { 295 | this.option.echartsLayerInteractive = !!interactive; 296 | this.__echartsLayer.style.pointerEvents = interactive ? 'auto' : 'none'; 297 | }, 298 | setCenterAndZoom: function setCenterAndZoom(center, zoom) { 299 | this.option.center = center; 300 | this.option.zoom = zoom; 301 | }, 302 | centerOrZoomChanged: function centerOrZoomChanged(center, zoom) { 303 | var option = this.option; 304 | return !(v2Equal(center, option.center) && zoom === option.zoom); 305 | }, 306 | defaultOption: { 307 | center: [116.397428, 39.90923], 308 | zoom: 5, 309 | isHotspot: false, 310 | resizeEnable: true, 311 | // extension specific options 312 | // echartsLayerZIndex: 2000, // DEPRECATED since v1.9.0 313 | echartsLayerInteractive: true, 314 | renderOnMoving: true, 315 | largeMode: false, 316 | // since v1.10.0 317 | returnMapCameraState: false 318 | } 319 | }; 320 | var AMapModel$1 = isNewEC ? ComponentModel.extend(AMapModel) : AMapModel; 321 | 322 | var _isAMap2X; 323 | var AMapView = { 324 | type: COMPONENT_TYPE, 325 | init: function init() { 326 | this._isFirstRender = true; 327 | _isAMap2X = isAMap2X(); 328 | }, 329 | render: function render(amapModel, ecModel, api) { 330 | var _this = this; 331 | var rendering = true; 332 | var amap = amapModel.getAMap(); 333 | var viewportRoot = api.getZr().painter.getViewportRoot(); 334 | var offsetEl = amap.getContainer(); 335 | var coordSys = amapModel.coordinateSystem; 336 | var renderOnMoving = amapModel.get('renderOnMoving'); 337 | var resizeEnable = amapModel.get('resizeEnable'); 338 | var largeMode = amapModel.get('largeMode'); 339 | var returnMapCameraState = amapModel.get('returnMapCameraState'); 340 | var viewMode = amap.getViewMode_(); 341 | var is3DMode = viewMode === '3D'; 342 | var moveHandler = function moveHandler(e) { 343 | if (rendering) { 344 | return; 345 | } 346 | var offsetElStyle = offsetEl.style; 347 | var mapOffset = [-parseInt(offsetElStyle.left, 10) || 0, -parseInt(offsetElStyle.top, 10) || 0]; 348 | // only update style when map offset changed 349 | var viewportRootStyle = viewportRoot.style; 350 | var offsetLeft = mapOffset[0] + 'px'; 351 | var offsetTop = mapOffset[1] + 'px'; 352 | if (viewportRootStyle.left !== offsetLeft) { 353 | viewportRootStyle.left = offsetLeft; 354 | } 355 | if (viewportRootStyle.top !== offsetTop) { 356 | viewportRootStyle.top = offsetTop; 357 | } 358 | coordSys.setMapOffset(amapModel.__mapOffset = mapOffset); 359 | var actionParams = { 360 | type: 'amapRoam', 361 | animation: { 362 | // compatible with ECharts 5.x 363 | // no delay for rendering but remain animation of elements 364 | duration: 0 365 | } 366 | }; 367 | if (returnMapCameraState) { 368 | e = e || {}; 369 | var center = e.center; 370 | if (!center) { 371 | // normalize center LngLat to Array 372 | center = amap.getCenter(); 373 | center = [center.lng, center.lat]; 374 | } 375 | actionParams.camera = { 376 | viewMode: viewMode, 377 | center: center, 378 | zoom: e.zoom || amap.getZoom(), 379 | rotation: e.rotation == null ? amap.getRotation() : e.rotation, 380 | pitch: e.pitch == null ? amap.getPitch() : e.pitch, 381 | scale: amap.getScale(), 382 | bounds: amap.getBounds() 383 | }; 384 | } 385 | api.dispatchAction(actionParams); 386 | }; 387 | amap.off('mapmove', this._moveHandler); 388 | amap.off('moveend', this._moveHandler); 389 | amap.off('viewchange', this._moveHandler); 390 | amap.off('camerachange', this._moveHandler); 391 | amap.off('zoom', this._moveHandler); 392 | if (this._resizeHandler) { 393 | amap.off('resize', this._resizeHandler); 394 | } 395 | if (this._moveStartHandler) { 396 | amap.off('movestart', this._moveStartHandler); 397 | } 398 | if (this._moveEndHandler) { 399 | amap.off('moveend', this._moveEndHandler); 400 | amap.off('zoomend', this._moveEndHandler); 401 | } 402 | amap.on(renderOnMoving ? _isAMap2X ? 'viewchange' : is3DMode ? 'camerachange' : 'mapmove' : 'moveend', 403 | // FIXME: bad performance in 1.x in the cases with large data, use debounce? 404 | // moveHandler 405 | !_isAMap2X && largeMode ? moveHandler = throttle(moveHandler, 20, true) : moveHandler); 406 | this._moveHandler = moveHandler; 407 | if (renderOnMoving && !(_isAMap2X && is3DMode)) { 408 | // need to listen to zoom if 1.x & 2D mode 409 | // FIXME: unnecessary `mapmove` event triggered when zooming 410 | amap.on('zoom', moveHandler); 411 | } 412 | if (!renderOnMoving) { 413 | amap.on('movestart', this._moveStartHandler = function () { 414 | setTimeout(function () { 415 | amapModel.setEChartsLayerVisibility(false); 416 | }, 0); 417 | }); 418 | var moveEndHandler = this._moveEndHandler = function (e) { 419 | (!e || e.type !== 'moveend') && moveHandler(e); 420 | setTimeout(function () { 421 | amapModel.setEChartsLayerVisibility(true); 422 | }, _isAMap2X || !largeMode ? 0 : 20); 423 | }; 424 | amap.on('moveend', moveEndHandler); 425 | amap.on('zoomend', moveEndHandler); 426 | if (this._isFirstRender && is3DMode) { 427 | // FIXME: not rewrite AMap instance method 428 | var nativeSetPitch = amap.setPitch; 429 | var nativeSetRotation = amap.setRotation; 430 | amap.setPitch = function () { 431 | nativeSetPitch.apply(this, arguments); 432 | moveEndHandler(); 433 | }; 434 | amap.setRotation = function () { 435 | nativeSetRotation.apply(this, arguments); 436 | moveEndHandler(); 437 | }; 438 | } 439 | } 440 | if (resizeEnable) { 441 | var resizeHandler = function resizeHandler() { 442 | clearTimeout(_this._resizeTimeout); 443 | _this._resizeTimeout = setTimeout(function () { 444 | return getInstanceByDom(api.getDom()).resize(); 445 | }, 0); 446 | }; 447 | if (!_isAMap2X && largeMode) { 448 | resizeHandler = throttle(resizeHandler, 20, true); 449 | } 450 | amap.on('resize', this._resizeHandler = resizeHandler); 451 | } 452 | this._isFirstRender = rendering = false; 453 | }, 454 | dispose: function dispose() { 455 | clearTimeout(this._resizeTimeout); 456 | clearLogMap(); 457 | var component = this.__model; 458 | if (component) { 459 | component.getAMap().destroy(); 460 | component.setAMap(null); 461 | component.setEChartsLayer(null); 462 | if (component.coordinateSystem) { 463 | component.coordinateSystem.setAMap(null); 464 | component.coordinateSystem = null; 465 | } 466 | } 467 | delete this._moveHandler; 468 | delete this._moveStartHandler; 469 | delete this._moveEndHandler; 470 | delete this._resizeHandler; 471 | delete this._resizeTimeout; 472 | } 473 | }; 474 | var AMapView$1 = isNewEC ? ComponentView.extend(AMapView) : AMapView; 475 | 476 | var name = "echarts-extension-amap"; 477 | var version = "1.12.0"; 478 | 479 | /** 480 | * AMap component extension 481 | */ 482 | 483 | 484 | /** 485 | * @typedef {import('../export').EChartsExtensionRegisters} EChartsExtensionRegisters 486 | */ 487 | 488 | /** 489 | * AMap extension installer 490 | * @param {EChartsExtensionRegisters} registers 491 | */ 492 | function install(registers) { 493 | // add coordinate system support for pie series for ECharts < 5.4.0 494 | if (!isNewEC || ecVer[0] == 5 && ecVer[1] < 4) { 495 | registers.registerLayout(function (ecModel) { 496 | ecModel.eachSeriesByType('pie', function (seriesModel) { 497 | var coordSys = seriesModel.coordinateSystem; 498 | var data = seriesModel.getData(); 499 | var valueDim = data.mapDimension('value'); 500 | if (coordSys && coordSys.type === COMPONENT_TYPE) { 501 | var center = seriesModel.get('center'); 502 | var point = coordSys.dataToPoint(center); 503 | var cx = point[0]; 504 | var cy = point[1]; 505 | data.each(valueDim, function (value, idx) { 506 | var layout = data.getItemLayout(idx); 507 | layout.cx = cx; 508 | layout.cy = cy; 509 | }); 510 | } 511 | }); 512 | }); 513 | } 514 | // Model 515 | isNewEC ? registers.registerComponentModel(AMapModel$1) : registers.extendComponentModel(AMapModel$1); 516 | // View 517 | isNewEC ? registers.registerComponentView(AMapView$1) : registers.extendComponentView(AMapView$1); 518 | // Coordinate System 519 | registers.registerCoordinateSystem(COMPONENT_TYPE, AMapCoordSys); 520 | // Action 521 | registers.registerAction({ 522 | type: COMPONENT_TYPE + 'Roam', 523 | event: COMPONENT_TYPE + 'Roam', 524 | update: 'updateLayout' 525 | }, function (payload, ecModel) { 526 | ecModel.eachComponent(COMPONENT_TYPE, function (amapModel) { 527 | var amap = amapModel.getAMap(); 528 | var center = amap.getCenter(); 529 | amapModel.setCenterAndZoom([center.lng, center.lat], amap.getZoom()); 530 | }); 531 | }); 532 | } 533 | 534 | /** 535 | * TODO use `echarts/core` rather than `echarts/lib/echarts` 536 | * to avoid self-registered `CanvasRenderer` and `DataSetComponent` in Apache ECharts 5 537 | * but it's not compatible with echarts v4. Leave it to 2.0. 538 | */ 539 | isNewEC ? echarts.use(install) : install(echarts); 540 | 541 | export { name, version }; 542 | -------------------------------------------------------------------------------- /dist/echarts-extension-amap.cjs.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * echarts-extension-amap 3 | * @version 1.12.0 4 | * @author plainheart 5 | * 6 | * MIT License 7 | * 8 | * Copyright (c) 2019-2024 Zhongxiang Wang 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in all 18 | * copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | */ 29 | 'use strict'; 30 | 31 | var echarts = require('echarts/lib/echarts'); 32 | 33 | var ecVer = echarts.version.split('.'); 34 | var isNewEC = ecVer[0] > 4; 35 | var COMPONENT_TYPE = 'amap'; 36 | 37 | /* global AMap */ 38 | 39 | // The version property is `AMap.v` in AMap 1.x, 40 | // but `AMap.version` may also exist (See #51) 41 | // In AMap 2.x, it's `AMap.version` (Not sure if `AMap.v` exists) 42 | // use function instead of constant to allow importing the plugin before AMap is loaded 43 | var isAMap2X = function isAMap2X() { 44 | return !AMap.v && AMap.version && AMap.version.split('.')[0] >= 2; 45 | }; 46 | function v2Equal(a, b) { 47 | return a && b && a[0] === b[0] && a[1] === b[1]; 48 | } 49 | var logMap = {}; 50 | function logWarn(tag, msg, once) { 51 | var log = "[ECharts][Extension][AMap]".concat(tag ? ' ' + tag + ':' : '', " ").concat(msg); 52 | once && logMap[log] || console.warn(log); 53 | once && (logMap[log] = true); 54 | } 55 | function clearLogMap() { 56 | logMap = {}; 57 | } 58 | 59 | function dataToCoordSize(dataSize, dataItem) { 60 | dataItem = dataItem || [0, 0]; 61 | return echarts.util.map([0, 1], function (dimIdx) { 62 | var val = dataItem[dimIdx]; 63 | var halfSize = dataSize[dimIdx] / 2; 64 | var p1 = []; 65 | var p2 = []; 66 | p1[dimIdx] = val - halfSize; 67 | p2[dimIdx] = val + halfSize; 68 | p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]; 69 | return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]); 70 | }, this); 71 | } 72 | 73 | // exclude private and unsupported options 74 | var excludedOptions = ['echartsLayerZIndex', 75 | // DEPRECATED since v1.9.0 76 | 'echartsLayerInteractive', 'renderOnMoving', 'largeMode', 'returnMapCameraState', 'layers']; 77 | function AMapCoordSys(amap, api) { 78 | this._amap = amap; 79 | this._api = api; 80 | this._mapOffset = [0, 0]; 81 | // this.dimensions = ['lng', 'lat'] 82 | } 83 | var AMapCoordSysProto = AMapCoordSys.prototype; 84 | AMapCoordSysProto.setZoom = function (zoom) { 85 | this._zoom = zoom; 86 | }; 87 | AMapCoordSysProto.setCenter = function (center) { 88 | var lnglat = new AMap.LngLat(center[0], center[1]); 89 | this._center = this._amap.lngLatToContainer(lnglat); 90 | }; 91 | AMapCoordSysProto.setMapOffset = function (mapOffset) { 92 | this._mapOffset = mapOffset; 93 | }; 94 | AMapCoordSysProto.setAMap = function (amap) { 95 | this._amap = amap; 96 | }; 97 | AMapCoordSysProto.getAMap = function () { 98 | return this._amap; 99 | }; 100 | AMapCoordSysProto.dataToPoint = function (data) { 101 | var lnglat = new AMap.LngLat(data[0], data[1]); 102 | var px = this._amap.lngLatToContainer(lnglat); 103 | var mapOffset = this._mapOffset; 104 | return [px.x - mapOffset[0], px.y - mapOffset[1]]; 105 | }; 106 | AMapCoordSysProto.pointToData = function (pt) { 107 | var mapOffset = this._mapOffset; 108 | var lnglat = this._amap.containerToLngLat(new AMap.Pixel(pt[0] + mapOffset[0], pt[1] + mapOffset[1])); 109 | return [lnglat.lng, lnglat.lat]; 110 | }; 111 | AMapCoordSysProto.getViewRect = function () { 112 | var api = this._api; 113 | return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()); 114 | }; 115 | AMapCoordSysProto.getRoamTransform = function () { 116 | return echarts.matrix.create(); 117 | }; 118 | AMapCoordSysProto.prepareCustoms = function () { 119 | var rect = this.getViewRect(); 120 | return { 121 | coordSys: { 122 | type: COMPONENT_TYPE, 123 | x: rect.x, 124 | y: rect.y, 125 | width: rect.width, 126 | height: rect.height 127 | }, 128 | api: { 129 | coord: echarts.util.bind(this.dataToPoint, this), 130 | size: echarts.util.bind(dataToCoordSize, this) 131 | } 132 | }; 133 | }; 134 | AMapCoordSysProto.convertToPixel = function (ecModel, finder, value) { 135 | // here we don't use finder as only one amap component is allowed 136 | return this.dataToPoint(value); 137 | }; 138 | AMapCoordSysProto.convertFromPixel = function (ecModel, finder, value) { 139 | // here we don't use finder as only one amap component is allowed 140 | return this.pointToData(value); 141 | }; 142 | 143 | // less useful 144 | // AMapCoordSysProto.containPoint = function(point) { 145 | // return this._amap.getBounds().contains(this.pointToData(point)); 146 | // } 147 | 148 | AMapCoordSys.create = function (ecModel, api) { 149 | var amapCoordSys; 150 | ecModel.eachComponent(COMPONENT_TYPE, function (amapModel) { 151 | if (typeof AMap === 'undefined') { 152 | throw new Error('AMap api is not loaded'); 153 | } 154 | if (amapCoordSys) { 155 | throw new Error('Only one amap component is allowed'); 156 | } 157 | var amap = amapModel.getAMap(); 158 | var echartsLayerInteractive = amapModel.get('echartsLayerInteractive'); 159 | if (!amap) { 160 | var root = api.getDom(); 161 | var painter = api.getZr().painter; 162 | var viewportRoot = painter.getViewportRoot(); 163 | viewportRoot.className = COMPONENT_TYPE + '-ec-layer'; 164 | // PENDING not hidden? 165 | viewportRoot.style.visibility = 'hidden'; 166 | var className = 'ec-extension-' + COMPONENT_TYPE; 167 | // Not support IE8 168 | var amapRoot = root.querySelector('.' + className); 169 | if (amapRoot) { 170 | // Reset viewport left and top, which will be changed 171 | // in moving handler in AMapView 172 | viewportRoot.style.left = '0px'; 173 | viewportRoot.style.top = '0px'; 174 | root.removeChild(amapRoot); 175 | } 176 | amapRoot = document.createElement('div'); 177 | amapRoot.className = className; 178 | amapRoot.style.cssText = 'position:absolute;top:0;left:0;bottom:0;right:0;'; 179 | root.appendChild(amapRoot); 180 | var options = echarts.util.clone(amapModel.get()); 181 | if ('echartsLayerZIndex' in options) { 182 | logWarn('DEPRECATED', 'the option `echartsLayerZIndex` has been removed since v1.9.0, use `echartsLayerInteractive` instead.'); 183 | } 184 | // delete excluded options 185 | echarts.util.each(excludedOptions, function (key) { 186 | delete options[key]; 187 | }); 188 | amap = new AMap.Map(amapRoot, options); 189 | 190 | // PENDING: should update the model option when the user call map.setXXX? 191 | 192 | // const nativeSetMapStyle = amap.setMapStyle 193 | // const nativeSetLang = amap.setLang 194 | 195 | // // PENDING 196 | // amap.setMapStyle = function () { 197 | // nativeSetMapStyle.apply(this, arguments) 198 | // amapModel.__mapStyle = amap.getMapStyle() 199 | // } 200 | 201 | // // PENDING 202 | // nativeSetLang && (amap.setLang = function() { 203 | // nativeSetLang.apply(this, arguments) 204 | // amapModel.__mapLang = amap.getLang() 205 | // }) 206 | 207 | // use `complete` callback to avoid NPE when first load amap 208 | amap.on('complete', function () { 209 | amapRoot.querySelector('.amap-maps').appendChild(viewportRoot); 210 | // PENDING 211 | viewportRoot.style.visibility = ''; 212 | }); 213 | amapModel.setAMap(amap); 214 | amapModel.setEChartsLayer(viewportRoot); 215 | 216 | // Override 217 | painter.getViewportRootOffset = function () { 218 | return { 219 | offsetLeft: 0, 220 | offsetTop: 0 221 | }; 222 | }; 223 | } 224 | var oldEChartsLayerInteractive = amapModel.__echartsLayerInteractive; 225 | if (oldEChartsLayerInteractive !== echartsLayerInteractive) { 226 | amapModel.setEChartsLayerInteractive(echartsLayerInteractive); 227 | amapModel.__echartsLayerInteractive = echartsLayerInteractive; 228 | } 229 | var center = amapModel.get('center'); 230 | var zoom = amapModel.get('zoom'); 231 | if (center && zoom) { 232 | var amapCenter = amap.getCenter(); 233 | var amapZoom = amap.getZoom(); 234 | var centerOrZoomChanged = amapModel.centerOrZoomChanged([amapCenter.lng, amapCenter.lat], amapZoom); 235 | if (centerOrZoomChanged) { 236 | amap.setZoomAndCenter(zoom, new AMap.LngLat(center[0], center[1])); 237 | } 238 | } 239 | 240 | // update map style(#13) 241 | var originalMapStyle = amapModel.__mapStyle; 242 | var newMapStyle = amapModel.get('mapStyle'); 243 | if (originalMapStyle !== newMapStyle) { 244 | amap.setMapStyle(amapModel.__mapStyle = newMapStyle); 245 | } 246 | 247 | // update map lang 248 | // PENDING: AMap 2.x does not support `setLang` yet 249 | if (amap.setLang) { 250 | var originalMapLang = amapModel.__mapLang; 251 | var newMapLang = amapModel.get('lang'); 252 | if (originalMapLang !== newMapLang) { 253 | amap.setLang(amapModel.__mapLang = newMapLang); 254 | } 255 | } else { 256 | logWarn('CAVEAT', 'The current map doesn\'t support `setLang` API!', true); 257 | } 258 | amapCoordSys = new AMapCoordSys(amap, api); 259 | amapCoordSys.setMapOffset(amapModel.__mapOffset || [0, 0]); 260 | amapCoordSys.setZoom(zoom); 261 | amapCoordSys.setCenter(center); 262 | amapModel.coordinateSystem = amapCoordSys; 263 | }); 264 | ecModel.eachSeries(function (seriesModel) { 265 | if (seriesModel.get('coordinateSystem') === COMPONENT_TYPE) { 266 | // inject coordinate system 267 | seriesModel.coordinateSystem = amapCoordSys; 268 | } 269 | }); 270 | 271 | // return created coordinate systems 272 | return amapCoordSys && [amapCoordSys]; 273 | }; 274 | AMapCoordSysProto.dimensions = AMapCoordSys.dimensions = ['lng', 'lat']; 275 | AMapCoordSysProto.type = COMPONENT_TYPE; 276 | 277 | var AMapModel = { 278 | type: COMPONENT_TYPE, 279 | setAMap: function setAMap(amap) { 280 | this.__amap = amap; 281 | }, 282 | getAMap: function getAMap() { 283 | return this.__amap; 284 | }, 285 | setEChartsLayer: function setEChartsLayer(layer) { 286 | this.__echartsLayer = layer; 287 | }, 288 | getEChartsLayer: function getEChartsLayer() { 289 | return this.__echartsLayer; 290 | }, 291 | setEChartsLayerVisibility: function setEChartsLayerVisibility(visible) { 292 | this.__echartsLayer.style.display = visible ? 'block' : 'none'; 293 | }, 294 | // FIXME: NOT SUPPORT <= IE 10 295 | setEChartsLayerInteractive: function setEChartsLayerInteractive(interactive) { 296 | this.option.echartsLayerInteractive = !!interactive; 297 | this.__echartsLayer.style.pointerEvents = interactive ? 'auto' : 'none'; 298 | }, 299 | setCenterAndZoom: function setCenterAndZoom(center, zoom) { 300 | this.option.center = center; 301 | this.option.zoom = zoom; 302 | }, 303 | centerOrZoomChanged: function centerOrZoomChanged(center, zoom) { 304 | var option = this.option; 305 | return !(v2Equal(center, option.center) && zoom === option.zoom); 306 | }, 307 | defaultOption: { 308 | center: [116.397428, 39.90923], 309 | zoom: 5, 310 | isHotspot: false, 311 | resizeEnable: true, 312 | // extension specific options 313 | // echartsLayerZIndex: 2000, // DEPRECATED since v1.9.0 314 | echartsLayerInteractive: true, 315 | renderOnMoving: true, 316 | largeMode: false, 317 | // since v1.10.0 318 | returnMapCameraState: false 319 | } 320 | }; 321 | var AMapModel$1 = isNewEC ? echarts.ComponentModel.extend(AMapModel) : AMapModel; 322 | 323 | var _isAMap2X; 324 | var AMapView = { 325 | type: COMPONENT_TYPE, 326 | init: function init() { 327 | this._isFirstRender = true; 328 | _isAMap2X = isAMap2X(); 329 | }, 330 | render: function render(amapModel, ecModel, api) { 331 | var _this = this; 332 | var rendering = true; 333 | var amap = amapModel.getAMap(); 334 | var viewportRoot = api.getZr().painter.getViewportRoot(); 335 | var offsetEl = amap.getContainer(); 336 | var coordSys = amapModel.coordinateSystem; 337 | var renderOnMoving = amapModel.get('renderOnMoving'); 338 | var resizeEnable = amapModel.get('resizeEnable'); 339 | var largeMode = amapModel.get('largeMode'); 340 | var returnMapCameraState = amapModel.get('returnMapCameraState'); 341 | var viewMode = amap.getViewMode_(); 342 | var is3DMode = viewMode === '3D'; 343 | var moveHandler = function moveHandler(e) { 344 | if (rendering) { 345 | return; 346 | } 347 | var offsetElStyle = offsetEl.style; 348 | var mapOffset = [-parseInt(offsetElStyle.left, 10) || 0, -parseInt(offsetElStyle.top, 10) || 0]; 349 | // only update style when map offset changed 350 | var viewportRootStyle = viewportRoot.style; 351 | var offsetLeft = mapOffset[0] + 'px'; 352 | var offsetTop = mapOffset[1] + 'px'; 353 | if (viewportRootStyle.left !== offsetLeft) { 354 | viewportRootStyle.left = offsetLeft; 355 | } 356 | if (viewportRootStyle.top !== offsetTop) { 357 | viewportRootStyle.top = offsetTop; 358 | } 359 | coordSys.setMapOffset(amapModel.__mapOffset = mapOffset); 360 | var actionParams = { 361 | type: 'amapRoam', 362 | animation: { 363 | // compatible with ECharts 5.x 364 | // no delay for rendering but remain animation of elements 365 | duration: 0 366 | } 367 | }; 368 | if (returnMapCameraState) { 369 | e = e || {}; 370 | var center = e.center; 371 | if (!center) { 372 | // normalize center LngLat to Array 373 | center = amap.getCenter(); 374 | center = [center.lng, center.lat]; 375 | } 376 | actionParams.camera = { 377 | viewMode: viewMode, 378 | center: center, 379 | zoom: e.zoom || amap.getZoom(), 380 | rotation: e.rotation == null ? amap.getRotation() : e.rotation, 381 | pitch: e.pitch == null ? amap.getPitch() : e.pitch, 382 | scale: amap.getScale(), 383 | bounds: amap.getBounds() 384 | }; 385 | } 386 | api.dispatchAction(actionParams); 387 | }; 388 | amap.off('mapmove', this._moveHandler); 389 | amap.off('moveend', this._moveHandler); 390 | amap.off('viewchange', this._moveHandler); 391 | amap.off('camerachange', this._moveHandler); 392 | amap.off('zoom', this._moveHandler); 393 | if (this._resizeHandler) { 394 | amap.off('resize', this._resizeHandler); 395 | } 396 | if (this._moveStartHandler) { 397 | amap.off('movestart', this._moveStartHandler); 398 | } 399 | if (this._moveEndHandler) { 400 | amap.off('moveend', this._moveEndHandler); 401 | amap.off('zoomend', this._moveEndHandler); 402 | } 403 | amap.on(renderOnMoving ? _isAMap2X ? 'viewchange' : is3DMode ? 'camerachange' : 'mapmove' : 'moveend', 404 | // FIXME: bad performance in 1.x in the cases with large data, use debounce? 405 | // moveHandler 406 | !_isAMap2X && largeMode ? moveHandler = echarts.throttle(moveHandler, 20, true) : moveHandler); 407 | this._moveHandler = moveHandler; 408 | if (renderOnMoving && !(_isAMap2X && is3DMode)) { 409 | // need to listen to zoom if 1.x & 2D mode 410 | // FIXME: unnecessary `mapmove` event triggered when zooming 411 | amap.on('zoom', moveHandler); 412 | } 413 | if (!renderOnMoving) { 414 | amap.on('movestart', this._moveStartHandler = function () { 415 | setTimeout(function () { 416 | amapModel.setEChartsLayerVisibility(false); 417 | }, 0); 418 | }); 419 | var moveEndHandler = this._moveEndHandler = function (e) { 420 | (!e || e.type !== 'moveend') && moveHandler(e); 421 | setTimeout(function () { 422 | amapModel.setEChartsLayerVisibility(true); 423 | }, _isAMap2X || !largeMode ? 0 : 20); 424 | }; 425 | amap.on('moveend', moveEndHandler); 426 | amap.on('zoomend', moveEndHandler); 427 | if (this._isFirstRender && is3DMode) { 428 | // FIXME: not rewrite AMap instance method 429 | var nativeSetPitch = amap.setPitch; 430 | var nativeSetRotation = amap.setRotation; 431 | amap.setPitch = function () { 432 | nativeSetPitch.apply(this, arguments); 433 | moveEndHandler(); 434 | }; 435 | amap.setRotation = function () { 436 | nativeSetRotation.apply(this, arguments); 437 | moveEndHandler(); 438 | }; 439 | } 440 | } 441 | if (resizeEnable) { 442 | var resizeHandler = function resizeHandler() { 443 | clearTimeout(_this._resizeTimeout); 444 | _this._resizeTimeout = setTimeout(function () { 445 | return echarts.getInstanceByDom(api.getDom()).resize(); 446 | }, 0); 447 | }; 448 | if (!_isAMap2X && largeMode) { 449 | resizeHandler = echarts.throttle(resizeHandler, 20, true); 450 | } 451 | amap.on('resize', this._resizeHandler = resizeHandler); 452 | } 453 | this._isFirstRender = rendering = false; 454 | }, 455 | dispose: function dispose() { 456 | clearTimeout(this._resizeTimeout); 457 | clearLogMap(); 458 | var component = this.__model; 459 | if (component) { 460 | component.getAMap().destroy(); 461 | component.setAMap(null); 462 | component.setEChartsLayer(null); 463 | if (component.coordinateSystem) { 464 | component.coordinateSystem.setAMap(null); 465 | component.coordinateSystem = null; 466 | } 467 | } 468 | delete this._moveHandler; 469 | delete this._moveStartHandler; 470 | delete this._moveEndHandler; 471 | delete this._resizeHandler; 472 | delete this._resizeTimeout; 473 | } 474 | }; 475 | var AMapView$1 = isNewEC ? echarts.ComponentView.extend(AMapView) : AMapView; 476 | 477 | var name = "echarts-extension-amap"; 478 | var version = "1.12.0"; 479 | 480 | /** 481 | * AMap component extension 482 | */ 483 | 484 | 485 | /** 486 | * @typedef {import('../export').EChartsExtensionRegisters} EChartsExtensionRegisters 487 | */ 488 | 489 | /** 490 | * AMap extension installer 491 | * @param {EChartsExtensionRegisters} registers 492 | */ 493 | function install(registers) { 494 | // add coordinate system support for pie series for ECharts < 5.4.0 495 | if (!isNewEC || ecVer[0] == 5 && ecVer[1] < 4) { 496 | registers.registerLayout(function (ecModel) { 497 | ecModel.eachSeriesByType('pie', function (seriesModel) { 498 | var coordSys = seriesModel.coordinateSystem; 499 | var data = seriesModel.getData(); 500 | var valueDim = data.mapDimension('value'); 501 | if (coordSys && coordSys.type === COMPONENT_TYPE) { 502 | var center = seriesModel.get('center'); 503 | var point = coordSys.dataToPoint(center); 504 | var cx = point[0]; 505 | var cy = point[1]; 506 | data.each(valueDim, function (value, idx) { 507 | var layout = data.getItemLayout(idx); 508 | layout.cx = cx; 509 | layout.cy = cy; 510 | }); 511 | } 512 | }); 513 | }); 514 | } 515 | // Model 516 | isNewEC ? registers.registerComponentModel(AMapModel$1) : registers.extendComponentModel(AMapModel$1); 517 | // View 518 | isNewEC ? registers.registerComponentView(AMapView$1) : registers.extendComponentView(AMapView$1); 519 | // Coordinate System 520 | registers.registerCoordinateSystem(COMPONENT_TYPE, AMapCoordSys); 521 | // Action 522 | registers.registerAction({ 523 | type: COMPONENT_TYPE + 'Roam', 524 | event: COMPONENT_TYPE + 'Roam', 525 | update: 'updateLayout' 526 | }, function (payload, ecModel) { 527 | ecModel.eachComponent(COMPONENT_TYPE, function (amapModel) { 528 | var amap = amapModel.getAMap(); 529 | var center = amap.getCenter(); 530 | amapModel.setCenterAndZoom([center.lng, center.lat], amap.getZoom()); 531 | }); 532 | }); 533 | } 534 | 535 | /** 536 | * TODO use `echarts/core` rather than `echarts/lib/echarts` 537 | * to avoid self-registered `CanvasRenderer` and `DataSetComponent` in Apache ECharts 5 538 | * but it's not compatible with echarts v4. Leave it to 2.0. 539 | */ 540 | isNewEC ? echarts.use(install) : install(echarts); 541 | 542 | exports.name = name; 543 | exports.version = version; 544 | -------------------------------------------------------------------------------- /dist/echarts-extension-amap.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * echarts-extension-amap 3 | * @version 1.12.0 4 | * @author plainheart 5 | * 6 | * MIT License 7 | * 8 | * Copyright (c) 2019-2024 Zhongxiang Wang 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in all 18 | * copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | */ 29 | (function (global, factory) { 30 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('echarts/lib/echarts')) : 31 | typeof define === 'function' && define.amd ? define(['exports', 'echarts'], factory) : 32 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.echarts = global.echarts || {}, global.echarts.amap = {}), global.echarts)); 33 | })(this, (function (exports, echarts) { 'use strict'; 34 | 35 | var ecVer = echarts.version.split('.'); 36 | var isNewEC = ecVer[0] > 4; 37 | var COMPONENT_TYPE = 'amap'; 38 | 39 | /* global AMap */ 40 | 41 | // The version property is `AMap.v` in AMap 1.x, 42 | // but `AMap.version` may also exist (See #51) 43 | // In AMap 2.x, it's `AMap.version` (Not sure if `AMap.v` exists) 44 | // use function instead of constant to allow importing the plugin before AMap is loaded 45 | var isAMap2X = function isAMap2X() { 46 | return !AMap.v && AMap.version && AMap.version.split('.')[0] >= 2; 47 | }; 48 | function v2Equal(a, b) { 49 | return a && b && a[0] === b[0] && a[1] === b[1]; 50 | } 51 | var logMap = {}; 52 | function logWarn(tag, msg, once) { 53 | var log = "[ECharts][Extension][AMap]".concat(tag ? ' ' + tag + ':' : '', " ").concat(msg); 54 | once && logMap[log] || console.warn(log); 55 | once && (logMap[log] = true); 56 | } 57 | function clearLogMap() { 58 | logMap = {}; 59 | } 60 | 61 | function dataToCoordSize(dataSize, dataItem) { 62 | dataItem = dataItem || [0, 0]; 63 | return echarts.util.map([0, 1], function (dimIdx) { 64 | var val = dataItem[dimIdx]; 65 | var halfSize = dataSize[dimIdx] / 2; 66 | var p1 = []; 67 | var p2 = []; 68 | p1[dimIdx] = val - halfSize; 69 | p2[dimIdx] = val + halfSize; 70 | p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]; 71 | return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]); 72 | }, this); 73 | } 74 | 75 | // exclude private and unsupported options 76 | var excludedOptions = ['echartsLayerZIndex', 77 | // DEPRECATED since v1.9.0 78 | 'echartsLayerInteractive', 'renderOnMoving', 'largeMode', 'returnMapCameraState', 'layers']; 79 | function AMapCoordSys(amap, api) { 80 | this._amap = amap; 81 | this._api = api; 82 | this._mapOffset = [0, 0]; 83 | // this.dimensions = ['lng', 'lat'] 84 | } 85 | var AMapCoordSysProto = AMapCoordSys.prototype; 86 | AMapCoordSysProto.setZoom = function (zoom) { 87 | this._zoom = zoom; 88 | }; 89 | AMapCoordSysProto.setCenter = function (center) { 90 | var lnglat = new AMap.LngLat(center[0], center[1]); 91 | this._center = this._amap.lngLatToContainer(lnglat); 92 | }; 93 | AMapCoordSysProto.setMapOffset = function (mapOffset) { 94 | this._mapOffset = mapOffset; 95 | }; 96 | AMapCoordSysProto.setAMap = function (amap) { 97 | this._amap = amap; 98 | }; 99 | AMapCoordSysProto.getAMap = function () { 100 | return this._amap; 101 | }; 102 | AMapCoordSysProto.dataToPoint = function (data) { 103 | var lnglat = new AMap.LngLat(data[0], data[1]); 104 | var px = this._amap.lngLatToContainer(lnglat); 105 | var mapOffset = this._mapOffset; 106 | return [px.x - mapOffset[0], px.y - mapOffset[1]]; 107 | }; 108 | AMapCoordSysProto.pointToData = function (pt) { 109 | var mapOffset = this._mapOffset; 110 | var lnglat = this._amap.containerToLngLat(new AMap.Pixel(pt[0] + mapOffset[0], pt[1] + mapOffset[1])); 111 | return [lnglat.lng, lnglat.lat]; 112 | }; 113 | AMapCoordSysProto.getViewRect = function () { 114 | var api = this._api; 115 | return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()); 116 | }; 117 | AMapCoordSysProto.getRoamTransform = function () { 118 | return echarts.matrix.create(); 119 | }; 120 | AMapCoordSysProto.prepareCustoms = function () { 121 | var rect = this.getViewRect(); 122 | return { 123 | coordSys: { 124 | type: COMPONENT_TYPE, 125 | x: rect.x, 126 | y: rect.y, 127 | width: rect.width, 128 | height: rect.height 129 | }, 130 | api: { 131 | coord: echarts.util.bind(this.dataToPoint, this), 132 | size: echarts.util.bind(dataToCoordSize, this) 133 | } 134 | }; 135 | }; 136 | AMapCoordSysProto.convertToPixel = function (ecModel, finder, value) { 137 | // here we don't use finder as only one amap component is allowed 138 | return this.dataToPoint(value); 139 | }; 140 | AMapCoordSysProto.convertFromPixel = function (ecModel, finder, value) { 141 | // here we don't use finder as only one amap component is allowed 142 | return this.pointToData(value); 143 | }; 144 | 145 | // less useful 146 | // AMapCoordSysProto.containPoint = function(point) { 147 | // return this._amap.getBounds().contains(this.pointToData(point)); 148 | // } 149 | 150 | AMapCoordSys.create = function (ecModel, api) { 151 | var amapCoordSys; 152 | ecModel.eachComponent(COMPONENT_TYPE, function (amapModel) { 153 | if (typeof AMap === 'undefined') { 154 | throw new Error('AMap api is not loaded'); 155 | } 156 | if (amapCoordSys) { 157 | throw new Error('Only one amap component is allowed'); 158 | } 159 | var amap = amapModel.getAMap(); 160 | var echartsLayerInteractive = amapModel.get('echartsLayerInteractive'); 161 | if (!amap) { 162 | var root = api.getDom(); 163 | var painter = api.getZr().painter; 164 | var viewportRoot = painter.getViewportRoot(); 165 | viewportRoot.className = COMPONENT_TYPE + '-ec-layer'; 166 | // PENDING not hidden? 167 | viewportRoot.style.visibility = 'hidden'; 168 | var className = 'ec-extension-' + COMPONENT_TYPE; 169 | // Not support IE8 170 | var amapRoot = root.querySelector('.' + className); 171 | if (amapRoot) { 172 | // Reset viewport left and top, which will be changed 173 | // in moving handler in AMapView 174 | viewportRoot.style.left = '0px'; 175 | viewportRoot.style.top = '0px'; 176 | root.removeChild(amapRoot); 177 | } 178 | amapRoot = document.createElement('div'); 179 | amapRoot.className = className; 180 | amapRoot.style.cssText = 'position:absolute;top:0;left:0;bottom:0;right:0;'; 181 | root.appendChild(amapRoot); 182 | var options = echarts.util.clone(amapModel.get()); 183 | if ('echartsLayerZIndex' in options) { 184 | logWarn('DEPRECATED', 'the option `echartsLayerZIndex` has been removed since v1.9.0, use `echartsLayerInteractive` instead.'); 185 | } 186 | // delete excluded options 187 | echarts.util.each(excludedOptions, function (key) { 188 | delete options[key]; 189 | }); 190 | amap = new AMap.Map(amapRoot, options); 191 | 192 | // PENDING: should update the model option when the user call map.setXXX? 193 | 194 | // const nativeSetMapStyle = amap.setMapStyle 195 | // const nativeSetLang = amap.setLang 196 | 197 | // // PENDING 198 | // amap.setMapStyle = function () { 199 | // nativeSetMapStyle.apply(this, arguments) 200 | // amapModel.__mapStyle = amap.getMapStyle() 201 | // } 202 | 203 | // // PENDING 204 | // nativeSetLang && (amap.setLang = function() { 205 | // nativeSetLang.apply(this, arguments) 206 | // amapModel.__mapLang = amap.getLang() 207 | // }) 208 | 209 | // use `complete` callback to avoid NPE when first load amap 210 | amap.on('complete', function () { 211 | amapRoot.querySelector('.amap-maps').appendChild(viewportRoot); 212 | // PENDING 213 | viewportRoot.style.visibility = ''; 214 | }); 215 | amapModel.setAMap(amap); 216 | amapModel.setEChartsLayer(viewportRoot); 217 | 218 | // Override 219 | painter.getViewportRootOffset = function () { 220 | return { 221 | offsetLeft: 0, 222 | offsetTop: 0 223 | }; 224 | }; 225 | } 226 | var oldEChartsLayerInteractive = amapModel.__echartsLayerInteractive; 227 | if (oldEChartsLayerInteractive !== echartsLayerInteractive) { 228 | amapModel.setEChartsLayerInteractive(echartsLayerInteractive); 229 | amapModel.__echartsLayerInteractive = echartsLayerInteractive; 230 | } 231 | var center = amapModel.get('center'); 232 | var zoom = amapModel.get('zoom'); 233 | if (center && zoom) { 234 | var amapCenter = amap.getCenter(); 235 | var amapZoom = amap.getZoom(); 236 | var centerOrZoomChanged = amapModel.centerOrZoomChanged([amapCenter.lng, amapCenter.lat], amapZoom); 237 | if (centerOrZoomChanged) { 238 | amap.setZoomAndCenter(zoom, new AMap.LngLat(center[0], center[1])); 239 | } 240 | } 241 | 242 | // update map style(#13) 243 | var originalMapStyle = amapModel.__mapStyle; 244 | var newMapStyle = amapModel.get('mapStyle'); 245 | if (originalMapStyle !== newMapStyle) { 246 | amap.setMapStyle(amapModel.__mapStyle = newMapStyle); 247 | } 248 | 249 | // update map lang 250 | // PENDING: AMap 2.x does not support `setLang` yet 251 | if (amap.setLang) { 252 | var originalMapLang = amapModel.__mapLang; 253 | var newMapLang = amapModel.get('lang'); 254 | if (originalMapLang !== newMapLang) { 255 | amap.setLang(amapModel.__mapLang = newMapLang); 256 | } 257 | } else { 258 | logWarn('CAVEAT', 'The current map doesn\'t support `setLang` API!', true); 259 | } 260 | amapCoordSys = new AMapCoordSys(amap, api); 261 | amapCoordSys.setMapOffset(amapModel.__mapOffset || [0, 0]); 262 | amapCoordSys.setZoom(zoom); 263 | amapCoordSys.setCenter(center); 264 | amapModel.coordinateSystem = amapCoordSys; 265 | }); 266 | ecModel.eachSeries(function (seriesModel) { 267 | if (seriesModel.get('coordinateSystem') === COMPONENT_TYPE) { 268 | // inject coordinate system 269 | seriesModel.coordinateSystem = amapCoordSys; 270 | } 271 | }); 272 | 273 | // return created coordinate systems 274 | return amapCoordSys && [amapCoordSys]; 275 | }; 276 | AMapCoordSysProto.dimensions = AMapCoordSys.dimensions = ['lng', 'lat']; 277 | AMapCoordSysProto.type = COMPONENT_TYPE; 278 | 279 | var AMapModel = { 280 | type: COMPONENT_TYPE, 281 | setAMap: function setAMap(amap) { 282 | this.__amap = amap; 283 | }, 284 | getAMap: function getAMap() { 285 | return this.__amap; 286 | }, 287 | setEChartsLayer: function setEChartsLayer(layer) { 288 | this.__echartsLayer = layer; 289 | }, 290 | getEChartsLayer: function getEChartsLayer() { 291 | return this.__echartsLayer; 292 | }, 293 | setEChartsLayerVisibility: function setEChartsLayerVisibility(visible) { 294 | this.__echartsLayer.style.display = visible ? 'block' : 'none'; 295 | }, 296 | // FIXME: NOT SUPPORT <= IE 10 297 | setEChartsLayerInteractive: function setEChartsLayerInteractive(interactive) { 298 | this.option.echartsLayerInteractive = !!interactive; 299 | this.__echartsLayer.style.pointerEvents = interactive ? 'auto' : 'none'; 300 | }, 301 | setCenterAndZoom: function setCenterAndZoom(center, zoom) { 302 | this.option.center = center; 303 | this.option.zoom = zoom; 304 | }, 305 | centerOrZoomChanged: function centerOrZoomChanged(center, zoom) { 306 | var option = this.option; 307 | return !(v2Equal(center, option.center) && zoom === option.zoom); 308 | }, 309 | defaultOption: { 310 | center: [116.397428, 39.90923], 311 | zoom: 5, 312 | isHotspot: false, 313 | resizeEnable: true, 314 | // extension specific options 315 | // echartsLayerZIndex: 2000, // DEPRECATED since v1.9.0 316 | echartsLayerInteractive: true, 317 | renderOnMoving: true, 318 | largeMode: false, 319 | // since v1.10.0 320 | returnMapCameraState: false 321 | } 322 | }; 323 | var AMapModel$1 = isNewEC ? echarts.ComponentModel.extend(AMapModel) : AMapModel; 324 | 325 | var _isAMap2X; 326 | var AMapView = { 327 | type: COMPONENT_TYPE, 328 | init: function init() { 329 | this._isFirstRender = true; 330 | _isAMap2X = isAMap2X(); 331 | }, 332 | render: function render(amapModel, ecModel, api) { 333 | var _this = this; 334 | var rendering = true; 335 | var amap = amapModel.getAMap(); 336 | var viewportRoot = api.getZr().painter.getViewportRoot(); 337 | var offsetEl = amap.getContainer(); 338 | var coordSys = amapModel.coordinateSystem; 339 | var renderOnMoving = amapModel.get('renderOnMoving'); 340 | var resizeEnable = amapModel.get('resizeEnable'); 341 | var largeMode = amapModel.get('largeMode'); 342 | var returnMapCameraState = amapModel.get('returnMapCameraState'); 343 | var viewMode = amap.getViewMode_(); 344 | var is3DMode = viewMode === '3D'; 345 | var moveHandler = function moveHandler(e) { 346 | if (rendering) { 347 | return; 348 | } 349 | var offsetElStyle = offsetEl.style; 350 | var mapOffset = [-parseInt(offsetElStyle.left, 10) || 0, -parseInt(offsetElStyle.top, 10) || 0]; 351 | // only update style when map offset changed 352 | var viewportRootStyle = viewportRoot.style; 353 | var offsetLeft = mapOffset[0] + 'px'; 354 | var offsetTop = mapOffset[1] + 'px'; 355 | if (viewportRootStyle.left !== offsetLeft) { 356 | viewportRootStyle.left = offsetLeft; 357 | } 358 | if (viewportRootStyle.top !== offsetTop) { 359 | viewportRootStyle.top = offsetTop; 360 | } 361 | coordSys.setMapOffset(amapModel.__mapOffset = mapOffset); 362 | var actionParams = { 363 | type: 'amapRoam', 364 | animation: { 365 | // compatible with ECharts 5.x 366 | // no delay for rendering but remain animation of elements 367 | duration: 0 368 | } 369 | }; 370 | if (returnMapCameraState) { 371 | e = e || {}; 372 | var center = e.center; 373 | if (!center) { 374 | // normalize center LngLat to Array 375 | center = amap.getCenter(); 376 | center = [center.lng, center.lat]; 377 | } 378 | actionParams.camera = { 379 | viewMode: viewMode, 380 | center: center, 381 | zoom: e.zoom || amap.getZoom(), 382 | rotation: e.rotation == null ? amap.getRotation() : e.rotation, 383 | pitch: e.pitch == null ? amap.getPitch() : e.pitch, 384 | scale: amap.getScale(), 385 | bounds: amap.getBounds() 386 | }; 387 | } 388 | api.dispatchAction(actionParams); 389 | }; 390 | amap.off('mapmove', this._moveHandler); 391 | amap.off('moveend', this._moveHandler); 392 | amap.off('viewchange', this._moveHandler); 393 | amap.off('camerachange', this._moveHandler); 394 | amap.off('zoom', this._moveHandler); 395 | if (this._resizeHandler) { 396 | amap.off('resize', this._resizeHandler); 397 | } 398 | if (this._moveStartHandler) { 399 | amap.off('movestart', this._moveStartHandler); 400 | } 401 | if (this._moveEndHandler) { 402 | amap.off('moveend', this._moveEndHandler); 403 | amap.off('zoomend', this._moveEndHandler); 404 | } 405 | amap.on(renderOnMoving ? _isAMap2X ? 'viewchange' : is3DMode ? 'camerachange' : 'mapmove' : 'moveend', 406 | // FIXME: bad performance in 1.x in the cases with large data, use debounce? 407 | // moveHandler 408 | !_isAMap2X && largeMode ? moveHandler = echarts.throttle(moveHandler, 20, true) : moveHandler); 409 | this._moveHandler = moveHandler; 410 | if (renderOnMoving && !(_isAMap2X && is3DMode)) { 411 | // need to listen to zoom if 1.x & 2D mode 412 | // FIXME: unnecessary `mapmove` event triggered when zooming 413 | amap.on('zoom', moveHandler); 414 | } 415 | if (!renderOnMoving) { 416 | amap.on('movestart', this._moveStartHandler = function () { 417 | setTimeout(function () { 418 | amapModel.setEChartsLayerVisibility(false); 419 | }, 0); 420 | }); 421 | var moveEndHandler = this._moveEndHandler = function (e) { 422 | (!e || e.type !== 'moveend') && moveHandler(e); 423 | setTimeout(function () { 424 | amapModel.setEChartsLayerVisibility(true); 425 | }, _isAMap2X || !largeMode ? 0 : 20); 426 | }; 427 | amap.on('moveend', moveEndHandler); 428 | amap.on('zoomend', moveEndHandler); 429 | if (this._isFirstRender && is3DMode) { 430 | // FIXME: not rewrite AMap instance method 431 | var nativeSetPitch = amap.setPitch; 432 | var nativeSetRotation = amap.setRotation; 433 | amap.setPitch = function () { 434 | nativeSetPitch.apply(this, arguments); 435 | moveEndHandler(); 436 | }; 437 | amap.setRotation = function () { 438 | nativeSetRotation.apply(this, arguments); 439 | moveEndHandler(); 440 | }; 441 | } 442 | } 443 | if (resizeEnable) { 444 | var resizeHandler = function resizeHandler() { 445 | clearTimeout(_this._resizeTimeout); 446 | _this._resizeTimeout = setTimeout(function () { 447 | return echarts.getInstanceByDom(api.getDom()).resize(); 448 | }, 0); 449 | }; 450 | if (!_isAMap2X && largeMode) { 451 | resizeHandler = echarts.throttle(resizeHandler, 20, true); 452 | } 453 | amap.on('resize', this._resizeHandler = resizeHandler); 454 | } 455 | this._isFirstRender = rendering = false; 456 | }, 457 | dispose: function dispose() { 458 | clearTimeout(this._resizeTimeout); 459 | clearLogMap(); 460 | var component = this.__model; 461 | if (component) { 462 | component.getAMap().destroy(); 463 | component.setAMap(null); 464 | component.setEChartsLayer(null); 465 | if (component.coordinateSystem) { 466 | component.coordinateSystem.setAMap(null); 467 | component.coordinateSystem = null; 468 | } 469 | } 470 | delete this._moveHandler; 471 | delete this._moveStartHandler; 472 | delete this._moveEndHandler; 473 | delete this._resizeHandler; 474 | delete this._resizeTimeout; 475 | } 476 | }; 477 | var AMapView$1 = isNewEC ? echarts.ComponentView.extend(AMapView) : AMapView; 478 | 479 | var name = "echarts-extension-amap"; 480 | var version = "1.12.0"; 481 | 482 | /** 483 | * AMap component extension 484 | */ 485 | 486 | 487 | /** 488 | * @typedef {import('../export').EChartsExtensionRegisters} EChartsExtensionRegisters 489 | */ 490 | 491 | /** 492 | * AMap extension installer 493 | * @param {EChartsExtensionRegisters} registers 494 | */ 495 | function install(registers) { 496 | // add coordinate system support for pie series for ECharts < 5.4.0 497 | if (!isNewEC || ecVer[0] == 5 && ecVer[1] < 4) { 498 | registers.registerLayout(function (ecModel) { 499 | ecModel.eachSeriesByType('pie', function (seriesModel) { 500 | var coordSys = seriesModel.coordinateSystem; 501 | var data = seriesModel.getData(); 502 | var valueDim = data.mapDimension('value'); 503 | if (coordSys && coordSys.type === COMPONENT_TYPE) { 504 | var center = seriesModel.get('center'); 505 | var point = coordSys.dataToPoint(center); 506 | var cx = point[0]; 507 | var cy = point[1]; 508 | data.each(valueDim, function (value, idx) { 509 | var layout = data.getItemLayout(idx); 510 | layout.cx = cx; 511 | layout.cy = cy; 512 | }); 513 | } 514 | }); 515 | }); 516 | } 517 | // Model 518 | isNewEC ? registers.registerComponentModel(AMapModel$1) : registers.extendComponentModel(AMapModel$1); 519 | // View 520 | isNewEC ? registers.registerComponentView(AMapView$1) : registers.extendComponentView(AMapView$1); 521 | // Coordinate System 522 | registers.registerCoordinateSystem(COMPONENT_TYPE, AMapCoordSys); 523 | // Action 524 | registers.registerAction({ 525 | type: COMPONENT_TYPE + 'Roam', 526 | event: COMPONENT_TYPE + 'Roam', 527 | update: 'updateLayout' 528 | }, function (payload, ecModel) { 529 | ecModel.eachComponent(COMPONENT_TYPE, function (amapModel) { 530 | var amap = amapModel.getAMap(); 531 | var center = amap.getCenter(); 532 | amapModel.setCenterAndZoom([center.lng, center.lat], amap.getZoom()); 533 | }); 534 | }); 535 | } 536 | 537 | /** 538 | * TODO use `echarts/core` rather than `echarts/lib/echarts` 539 | * to avoid self-registered `CanvasRenderer` and `DataSetComponent` in Apache ECharts 5 540 | * but it's not compatible with echarts v4. Leave it to 2.0. 541 | */ 542 | isNewEC ? echarts.use(install) : install(echarts); 543 | 544 | exports.name = name; 545 | exports.version = version; 546 | 547 | })); 548 | //# sourceMappingURL=echarts-extension-amap.js.map 549 | -------------------------------------------------------------------------------- /dist/echarts-extension-amap.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"echarts-extension-amap.min.js","sources":["../src/helper.js","../src/AMapCoordSys.js","../src/AMapModel.js","../src/AMapView.js","../src/index.js","../index.js"],"sourcesContent":["import { version } from 'echarts/lib/echarts'\n\nexport const ecVer = version.split('.')\n\nexport const isNewEC = ecVer[0] > 4\n\nexport const COMPONENT_TYPE = 'amap'\n\n/* global AMap */\n\n// The version property is `AMap.v` in AMap 1.x,\n// but `AMap.version` may also exist (See #51)\n// In AMap 2.x, it's `AMap.version` (Not sure if `AMap.v` exists)\n// use function instead of constant to allow importing the plugin before AMap is loaded\nexport const isAMap2X = () => !AMap.v && AMap.version && AMap.version.split('.')[0] >= 2\n\nexport function v2Equal(a, b) {\n return a && b && a[0] === b[0] && a[1] === b[1]\n}\n\nlet logMap = {}\n\nexport function logWarn(tag, msg, once) {\n const log = `[ECharts][Extension][AMap]${tag ? ' ' + tag + ':' : ''} ${msg}`\n once && logMap[log] || console.warn(log)\n once && (logMap[log] = true)\n}\n\nexport function clearLogMap() {\n logMap = {}\n}\n","import { util as zrUtil, graphic, matrix } from 'echarts/lib/echarts'\nimport { COMPONENT_TYPE, logWarn } from './helper'\n\nfunction dataToCoordSize(dataSize, dataItem) {\n dataItem = dataItem || [0, 0];\n return zrUtil.map(\n [0, 1],\n function(dimIdx) {\n const val = dataItem[dimIdx]\n const halfSize = dataSize[dimIdx] / 2\n const p1 = []\n const p2 = []\n p1[dimIdx] = val - halfSize\n p2[dimIdx] = val + halfSize\n p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]\n return Math.abs(\n this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]\n )\n },\n this\n )\n}\n\n// exclude private and unsupported options\nconst excludedOptions = [\n 'echartsLayerZIndex', // DEPRECATED since v1.9.0\n 'echartsLayerInteractive',\n 'renderOnMoving',\n 'largeMode',\n 'returnMapCameraState',\n 'layers'\n]\n\nfunction AMapCoordSys(amap, api) {\n this._amap = amap\n this._api = api\n this._mapOffset = [0, 0]\n // this.dimensions = ['lng', 'lat']\n}\n\nconst AMapCoordSysProto = AMapCoordSys.prototype\n\nAMapCoordSysProto.setZoom = function(zoom) {\n this._zoom = zoom\n}\n\nAMapCoordSysProto.setCenter = function(center) {\n const lnglat = new AMap.LngLat(center[0], center[1])\n this._center = this._amap.lngLatToContainer(lnglat)\n}\n\nAMapCoordSysProto.setMapOffset = function(mapOffset) {\n this._mapOffset = mapOffset\n}\n\nAMapCoordSysProto.setAMap = function(amap) {\n this._amap = amap\n}\n\nAMapCoordSysProto.getAMap = function() {\n return this._amap\n}\n\nAMapCoordSysProto.dataToPoint = function(data) {\n const lnglat = new AMap.LngLat(data[0], data[1])\n const px = this._amap.lngLatToContainer(lnglat)\n const mapOffset = this._mapOffset\n return [px.x - mapOffset[0], px.y - mapOffset[1]]\n}\n\nAMapCoordSysProto.pointToData = function(pt) {\n const mapOffset = this._mapOffset\n const lnglat = this._amap.containerToLngLat(\n new AMap.Pixel(\n pt[0] + mapOffset[0],\n pt[1] + mapOffset[1]\n )\n )\n return [lnglat.lng, lnglat.lat]\n}\n\nAMapCoordSysProto.getViewRect = function() {\n const api = this._api\n return new graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight())\n}\n\nAMapCoordSysProto.getRoamTransform = function() {\n return matrix.create()\n}\n\nAMapCoordSysProto.prepareCustoms = function() {\n const rect = this.getViewRect()\n return {\n coordSys: {\n type: COMPONENT_TYPE,\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height\n },\n api: {\n coord: zrUtil.bind(this.dataToPoint, this),\n size: zrUtil.bind(dataToCoordSize, this)\n }\n }\n}\n\nAMapCoordSysProto.convertToPixel = function(ecModel, finder, value) {\n // here we don't use finder as only one amap component is allowed\n return this.dataToPoint(value);\n}\n\nAMapCoordSysProto.convertFromPixel = function(ecModel, finder, value) {\n // here we don't use finder as only one amap component is allowed\n return this.pointToData(value);\n}\n\n// less useful\n// AMapCoordSysProto.containPoint = function(point) {\n// return this._amap.getBounds().contains(this.pointToData(point));\n// }\n\nAMapCoordSys.create = function(ecModel, api) {\n let amapCoordSys\n ecModel.eachComponent(COMPONENT_TYPE, function(amapModel) {\n if (typeof AMap === 'undefined') {\n throw new Error('AMap api is not loaded')\n }\n if (amapCoordSys) {\n throw new Error('Only one amap component is allowed')\n }\n let amap = amapModel.getAMap()\n const echartsLayerInteractive = amapModel.get('echartsLayerInteractive')\n if (!amap) {\n const root = api.getDom()\n const painter = api.getZr().painter\n const viewportRoot = painter.getViewportRoot()\n viewportRoot.className = COMPONENT_TYPE + '-ec-layer'\n // PENDING not hidden?\n viewportRoot.style.visibility = 'hidden'\n const className = 'ec-extension-' + COMPONENT_TYPE\n // Not support IE8\n let amapRoot = root.querySelector('.' + className)\n if (amapRoot) {\n // Reset viewport left and top, which will be changed\n // in moving handler in AMapView\n viewportRoot.style.left = '0px'\n viewportRoot.style.top = '0px'\n root.removeChild(amapRoot)\n }\n amapRoot = document.createElement('div')\n amapRoot.className = className\n amapRoot.style.cssText = 'position:absolute;top:0;left:0;bottom:0;right:0;'\n root.appendChild(amapRoot)\n\n const options = zrUtil.clone(amapModel.get())\n if ('echartsLayerZIndex' in options) {\n logWarn('DEPRECATED', 'the option `echartsLayerZIndex` has been removed since v1.9.0, use `echartsLayerInteractive` instead.')\n }\n // delete excluded options\n zrUtil.each(excludedOptions, function(key) {\n delete options[key]\n })\n\n amap = new AMap.Map(amapRoot, options)\n\n // PENDING: should update the model option when the user call map.setXXX?\n\n // const nativeSetMapStyle = amap.setMapStyle\n // const nativeSetLang = amap.setLang\n\n // // PENDING\n // amap.setMapStyle = function () {\n // nativeSetMapStyle.apply(this, arguments)\n // amapModel.__mapStyle = amap.getMapStyle()\n // }\n\n // // PENDING\n // nativeSetLang && (amap.setLang = function() {\n // nativeSetLang.apply(this, arguments)\n // amapModel.__mapLang = amap.getLang()\n // })\n\n // use `complete` callback to avoid NPE when first load amap\n amap.on('complete', function() {\n amapRoot.querySelector('.amap-maps').appendChild(viewportRoot)\n // PENDING\n viewportRoot.style.visibility = ''\n })\n\n amapModel.setAMap(amap)\n amapModel.setEChartsLayer(viewportRoot)\n\n // Override\n painter.getViewportRootOffset = function() {\n return { offsetLeft: 0, offsetTop: 0 }\n }\n }\n\n const oldEChartsLayerInteractive = amapModel.__echartsLayerInteractive\n if (oldEChartsLayerInteractive !== echartsLayerInteractive) {\n amapModel.setEChartsLayerInteractive(echartsLayerInteractive)\n amapModel.__echartsLayerInteractive = echartsLayerInteractive\n }\n\n const center = amapModel.get('center')\n const zoom = amapModel.get('zoom')\n if (center && zoom) {\n const amapCenter = amap.getCenter()\n const amapZoom = amap.getZoom()\n const centerOrZoomChanged = amapModel.centerOrZoomChanged(\n [amapCenter.lng, amapCenter.lat],\n amapZoom\n )\n if (centerOrZoomChanged) {\n amap.setZoomAndCenter(zoom, new AMap.LngLat(center[0], center[1]))\n }\n }\n\n // update map style(#13)\n const originalMapStyle = amapModel.__mapStyle\n const newMapStyle = amapModel.get('mapStyle')\n if (originalMapStyle !== newMapStyle) {\n amap.setMapStyle(amapModel.__mapStyle = newMapStyle)\n }\n\n // update map lang\n // PENDING: AMap 2.x does not support `setLang` yet\n if (amap.setLang) {\n const originalMapLang = amapModel.__mapLang\n const newMapLang = amapModel.get('lang')\n if (originalMapLang !== newMapLang) {\n amap.setLang(amapModel.__mapLang = newMapLang)\n }\n }\n else {\n logWarn('CAVEAT', 'The current map doesn\\'t support `setLang` API!', true)\n }\n\n amapCoordSys = new AMapCoordSys(amap, api)\n amapCoordSys.setMapOffset(amapModel.__mapOffset || [0, 0])\n amapCoordSys.setZoom(zoom)\n amapCoordSys.setCenter(center)\n\n amapModel.coordinateSystem = amapCoordSys\n })\n\n ecModel.eachSeries(function(seriesModel) {\n if (seriesModel.get('coordinateSystem') === COMPONENT_TYPE) {\n // inject coordinate system\n seriesModel.coordinateSystem = amapCoordSys\n }\n })\n\n // return created coordinate systems\n return amapCoordSys && [amapCoordSys]\n}\n\nAMapCoordSysProto.dimensions = AMapCoordSys.dimensions = ['lng', 'lat']\n\nAMapCoordSysProto.type = COMPONENT_TYPE\n\n\nexport default AMapCoordSys\n","import { ComponentModel } from 'echarts/lib/echarts'\nimport { COMPONENT_TYPE, isNewEC, v2Equal } from './helper'\n\nconst AMapModel = {\n type: COMPONENT_TYPE,\n\n setAMap(amap) {\n this.__amap = amap\n },\n\n getAMap() {\n return this.__amap\n },\n\n setEChartsLayer(layer) {\n this.__echartsLayer = layer\n },\n\n getEChartsLayer() {\n return this.__echartsLayer\n },\n\n setEChartsLayerVisibility(visible) {\n this.__echartsLayer.style.display = visible ? 'block' : 'none'\n },\n\n // FIXME: NOT SUPPORT <= IE 10\n setEChartsLayerInteractive(interactive) {\n this.option.echartsLayerInteractive = !!interactive\n this.__echartsLayer.style.pointerEvents = interactive ? 'auto' : 'none'\n },\n\n setCenterAndZoom(center, zoom) {\n this.option.center = center\n this.option.zoom = zoom\n },\n\n centerOrZoomChanged(center, zoom) {\n const option = this.option\n return !(v2Equal(center, option.center) && zoom === option.zoom)\n },\n\n defaultOption: {\n center: [116.397428, 39.90923],\n zoom: 5,\n isHotspot: false,\n resizeEnable: true,\n\n // extension specific options\n // echartsLayerZIndex: 2000, // DEPRECATED since v1.9.0\n echartsLayerInteractive: true,\n renderOnMoving: true,\n largeMode: false,\n // since v1.10.0\n returnMapCameraState: false\n }\n}\n\nexport default isNewEC\n ? ComponentModel.extend(AMapModel)\n : AMapModel\n","import { ComponentView, getInstanceByDom, throttle } from 'echarts/lib/echarts'\nimport { COMPONENT_TYPE, isNewEC, isAMap2X, clearLogMap } from './helper'\n\nlet _isAMap2X\n\nconst AMapView = {\n type: COMPONENT_TYPE,\n\n init() {\n this._isFirstRender = true\n\n _isAMap2X = isAMap2X()\n },\n\n render(amapModel, ecModel, api) {\n let rendering = true\n\n const amap = amapModel.getAMap()\n const viewportRoot = api.getZr().painter.getViewportRoot()\n const offsetEl = amap.getContainer()\n const coordSys = amapModel.coordinateSystem\n\n const renderOnMoving = amapModel.get('renderOnMoving')\n const resizeEnable = amapModel.get('resizeEnable')\n const largeMode = amapModel.get('largeMode')\n const returnMapCameraState = amapModel.get('returnMapCameraState')\n\n const viewMode = amap.getViewMode_()\n const is3DMode = viewMode === '3D'\n\n let moveHandler = function(e) {\n if (rendering) {\n return\n }\n\n const offsetElStyle = offsetEl.style\n const mapOffset = [\n -parseInt(offsetElStyle.left, 10) || 0,\n -parseInt(offsetElStyle.top, 10) || 0\n ]\n // only update style when map offset changed\n const viewportRootStyle = viewportRoot.style\n const offsetLeft = mapOffset[0] + 'px'\n const offsetTop = mapOffset[1] + 'px'\n if (viewportRootStyle.left !== offsetLeft) {\n viewportRootStyle.left = offsetLeft\n }\n if (viewportRootStyle.top !== offsetTop) {\n viewportRootStyle.top = offsetTop\n }\n\n coordSys.setMapOffset(amapModel.__mapOffset = mapOffset)\n\n const actionParams = {\n type: 'amapRoam',\n animation: {\n // compatible with ECharts 5.x\n // no delay for rendering but remain animation of elements\n duration: 0\n }\n }\n\n if (returnMapCameraState) {\n e = e || {}\n let center = e.center\n if (!center) {\n // normalize center LngLat to Array\n center = amap.getCenter()\n center = [center.lng, center.lat]\n }\n actionParams.camera = {\n viewMode,\n center,\n zoom: e.zoom || amap.getZoom(),\n rotation: e.rotation == null ? amap.getRotation() : e.rotation,\n pitch: e.pitch == null ? amap.getPitch() : e.pitch,\n scale: amap.getScale(),\n bounds: amap.getBounds()\n }\n }\n\n api.dispatchAction(actionParams)\n }\n\n amap.off('mapmove', this._moveHandler)\n amap.off('moveend', this._moveHandler)\n amap.off('viewchange', this._moveHandler)\n amap.off('camerachange', this._moveHandler)\n amap.off('zoom', this._moveHandler)\n\n if (this._resizeHandler) {\n amap.off('resize', this._resizeHandler)\n }\n if (this._moveStartHandler) {\n amap.off('movestart', this._moveStartHandler)\n }\n if (this._moveEndHandler) {\n amap.off('moveend', this._moveEndHandler)\n amap.off('zoomend', this._moveEndHandler)\n }\n\n amap.on(\n renderOnMoving\n ? (_isAMap2X\n ? 'viewchange'\n : is3DMode\n ? 'camerachange'\n : 'mapmove')\n : 'moveend',\n // FIXME: bad performance in 1.x in the cases with large data, use debounce?\n // moveHandler\n (!_isAMap2X && largeMode) ? (moveHandler = throttle(moveHandler, 20, true)) : moveHandler\n )\n\n this._moveHandler = moveHandler\n\n if (renderOnMoving && !(_isAMap2X && is3DMode)) {\n // need to listen to zoom if 1.x & 2D mode\n // FIXME: unnecessary `mapmove` event triggered when zooming\n amap.on('zoom', moveHandler)\n }\n\n if (!renderOnMoving) {\n amap.on('movestart', this._moveStartHandler = function() {\n setTimeout(function() {\n amapModel.setEChartsLayerVisibility(false)\n }, 0)\n })\n const moveEndHandler = this._moveEndHandler = function(e) {\n ;(!e || e.type !== 'moveend') && moveHandler(e)\n setTimeout(function() {\n amapModel.setEChartsLayerVisibility(true)\n }, _isAMap2X || !largeMode ? 0 : 20)\n }\n amap.on('moveend', moveEndHandler)\n amap.on('zoomend', moveEndHandler)\n if (this._isFirstRender && is3DMode) {\n // FIXME: not rewrite AMap instance method\n const nativeSetPitch = amap.setPitch\n const nativeSetRotation = amap.setRotation\n amap.setPitch = function() {\n nativeSetPitch.apply(this, arguments)\n moveEndHandler()\n }\n amap.setRotation = function() {\n nativeSetRotation.apply(this, arguments)\n moveEndHandler()\n }\n }\n }\n\n if (resizeEnable) {\n let resizeHandler = () => {\n clearTimeout(this._resizeTimeout)\n this._resizeTimeout = setTimeout(() => getInstanceByDom(api.getDom()).resize(), 0)\n }\n if (!_isAMap2X && largeMode) {\n resizeHandler = throttle(resizeHandler, 20, true)\n }\n amap.on('resize', this._resizeHandler = resizeHandler)\n }\n\n this._isFirstRender = rendering = false\n },\n\n dispose() {\n clearTimeout(this._resizeTimeout)\n clearLogMap()\n const component = this.__model\n if (component) {\n component.getAMap().destroy()\n component.setAMap(null)\n component.setEChartsLayer(null)\n if (component.coordinateSystem) {\n component.coordinateSystem.setAMap(null)\n component.coordinateSystem = null\n }\n }\n delete this._moveHandler\n delete this._moveStartHandler\n delete this._moveEndHandler\n delete this._resizeHandler\n delete this._resizeTimeout\n }\n}\n\nexport default isNewEC\n ? ComponentView.extend(AMapView)\n : AMapView\n","/**\n * AMap component extension\n */\n\nimport AMapCoordSys from './AMapCoordSys'\nimport AMapModel from './AMapModel'\nimport AMapView from './AMapView'\nimport { isNewEC, ecVer, COMPONENT_TYPE } from './helper'\n\nexport { version, name } from '../package.json'\n\n/**\n * @typedef {import('../export').EChartsExtensionRegisters} EChartsExtensionRegisters\n */\n\n/**\n * AMap extension installer\n * @param {EChartsExtensionRegisters} registers\n */\nexport function install(registers) {\n // add coordinate system support for pie series for ECharts < 5.4.0\n if (!isNewEC || (ecVer[0] == 5 && ecVer[1] < 4)) {\n registers.registerLayout(function(ecModel) {\n ecModel.eachSeriesByType('pie', function (seriesModel) {\n const coordSys = seriesModel.coordinateSystem\n const data = seriesModel.getData()\n const valueDim = data.mapDimension('value')\n if (coordSys && coordSys.type === COMPONENT_TYPE) {\n const center = seriesModel.get('center')\n const point = coordSys.dataToPoint(center)\n const cx = point[0]\n const cy = point[1]\n data.each(valueDim, function (value, idx) {\n const layout = data.getItemLayout(idx)\n layout.cx = cx\n layout.cy = cy\n })\n }\n })\n })\n }\n // Model\n isNewEC\n ? registers.registerComponentModel(AMapModel)\n : registers.extendComponentModel(AMapModel)\n // View\n isNewEC\n ? registers.registerComponentView(AMapView)\n : registers.extendComponentView(AMapView)\n // Coordinate System\n registers.registerCoordinateSystem(COMPONENT_TYPE, AMapCoordSys)\n // Action\n registers.registerAction(\n {\n type: COMPONENT_TYPE + 'Roam',\n event: COMPONENT_TYPE + 'Roam',\n update: 'updateLayout'\n },\n function(payload, ecModel) {\n ecModel.eachComponent(COMPONENT_TYPE, function(amapModel) {\n const amap = amapModel.getAMap()\n const center = amap.getCenter()\n amapModel.setCenterAndZoom([center.lng, center.lat], amap.getZoom())\n })\n }\n )\n}\n","/**\n * TODO use `echarts/core` rather than `echarts/lib/echarts`\n * to avoid self-registered `CanvasRenderer` and `DataSetComponent` in Apache ECharts 5\n * but it's not compatible with echarts v4. Leave it to 2.0.\n */\nimport * as echarts from 'echarts/lib/echarts'\nimport { install } from './src/index'\nimport { isNewEC } from './src/helper'\n\nisNewEC ? echarts.use(install) : install(echarts)\n\nexport { name, version } from './src/index'\n"],"names":["ecVer","version","split","isNewEC","COMPONENT_TYPE","logMap","logWarn","tag","msg","once","log","concat","console","warn","dataToCoordSize","dataSize","dataItem","zrUtil","map","dimIdx","val","halfSize","p1","p2","Math","abs","this","dataToPoint","excludedOptions","AMapCoordSys","amap","api","_amap","_api","_mapOffset","AMapCoordSysProto","prototype","setZoom","zoom","_zoom","setCenter","center","lnglat","AMap","LngLat","_center","lngLatToContainer","setMapOffset","mapOffset","setAMap","getAMap","data","px","x","y","pointToData","pt","containerToLngLat","Pixel","lng","lat","getViewRect","graphic","BoundingRect","getWidth","getHeight","getRoamTransform","matrix","create","prepareCustoms","rect","coordSys","type","width","height","coord","bind","size","util","convertToPixel","ecModel","finder","value","convertFromPixel","amapCoordSys","eachComponent","amapModel","Error","echartsLayerInteractive","get","root","getDom","painter","getZr","viewportRoot","getViewportRoot","className","style","visibility","amapRoot","querySelector","left","top","removeChild","document","createElement","cssText","appendChild","options","clone","each","key","Map","on","setEChartsLayer","getViewportRootOffset","offsetLeft","offsetTop","__echartsLayerInteractive","setEChartsLayerInteractive","amapCenter","getCenter","amapZoom","getZoom","centerOrZoomChanged","setZoomAndCenter","originalMapStyle","__mapStyle","newMapStyle","setMapStyle","setLang","originalMapLang","__mapLang","newMapLang","__mapOffset","coordinateSystem","eachSeries","seriesModel","dimensions","_isAMap2X","AMapModel","__amap","layer","__echartsLayer","getEChartsLayer","setEChartsLayerVisibility","visible","display","interactive","option","pointerEvents","setCenterAndZoom","a","b","defaultOption","isHotspot","resizeEnable","renderOnMoving","largeMode","returnMapCameraState","ComponentModel","extend","AMapView","init","_isFirstRender","v","render","_this","rendering","offsetEl","getContainer","viewMode","getViewMode_","is3DMode","moveHandler","e","offsetElStyle","parseInt","viewportRootStyle","actionParams","animation","duration","camera","rotation","getRotation","pitch","getPitch","scale","getScale","bounds","getBounds","dispatchAction","off","_moveHandler","_resizeHandler","_moveStartHandler","_moveEndHandler","throttle","setTimeout","moveEndHandler","nativeSetPitch","setPitch","nativeSetRotation","setRotation","apply","arguments","resizeHandler","clearTimeout","_resizeTimeout","getInstanceByDom","resize","dispose","component","__model","destroy","ComponentView","install","registers","registerLayout","eachSeriesByType","getData","valueDim","mapDimension","point","cx","cy","idx","layout","getItemLayout","registerComponentModel","extendComponentModel","registerComponentView","extendComponentView","registerCoordinateSystem","registerAction","event","update","payload","echarts","use"],"mappings":"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"} --------------------------------------------------------------------------------