├── .babelrc
├── .eslintrc
├── .github
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── LICENSE
├── README.md
├── package.json
├── src
├── components
│ ├── AutoComplete
│ │ └── index.js
│ ├── Base
│ │ ├── Bounds.js
│ │ ├── Common.js
│ │ ├── Events.js
│ │ ├── Path.js
│ │ ├── Point.js
│ │ ├── Size.js
│ │ └── index.js
│ ├── ContextMenu
│ │ ├── Item.js
│ │ └── index.js
│ ├── Control
│ │ ├── BaseControl.js
│ │ ├── CityList.js
│ │ ├── CopyrightControl.js
│ │ ├── Custom.js
│ │ ├── Geolocation.js
│ │ ├── MapType.js
│ │ ├── Navigation.js
│ │ ├── OverviewMap.js
│ │ ├── Panorama.js
│ │ └── Scale.js
│ ├── Copyright
│ │ └── index.js
│ ├── Layer
│ │ ├── TileLayer.js
│ │ └── TrafficLayer.js
│ ├── Library
│ │ ├── CurveLine
│ │ │ └── index.js
│ │ ├── DistanceTool
│ │ │ ├── Icon.js
│ │ │ └── index.js
│ │ └── HeatMap
│ │ │ └── index.js
│ ├── Map
│ │ ├── PlaceHolder.js
│ │ └── index.js
│ └── Overlay
│ │ ├── BaseOverlay.js
│ │ ├── Boundary.js
│ │ ├── Circle.js
│ │ ├── Custom.js
│ │ ├── Ground.js
│ │ ├── HTMLComponent.js
│ │ ├── HTMLStringComponent.js
│ │ ├── InfoWindow
│ │ ├── Content.js
│ │ ├── MaxContent.js
│ │ ├── Title.js
│ │ └── index.js
│ │ ├── Label
│ │ ├── Content.js
│ │ └── index.js
│ │ ├── Marker
│ │ ├── Icon.js
│ │ └── index.js
│ │ ├── PointCollection.js
│ │ ├── Polygon.js
│ │ ├── Polyline
│ │ ├── IconSequence.js
│ │ └── index.js
│ │ └── Symbol.js
├── core
│ ├── AutoComplete
│ │ └── index.js
│ ├── Control
│ │ ├── BaseControl.js
│ │ ├── CityList.js
│ │ ├── Copyright.js
│ │ ├── Custom.js
│ │ ├── Geolocation.js
│ │ ├── MapType.js
│ │ ├── Navigation.js
│ │ ├── OverviewMap.js
│ │ ├── Panorama.js
│ │ └── Scale.js
│ ├── Layer
│ │ ├── TileLayer.js
│ │ └── TrafficLayer.js
│ ├── Library
│ │ ├── CurveLine.js
│ │ ├── DistanceTool.js
│ │ └── HeatMap.js
│ ├── Map
│ │ └── index.js
│ ├── Overlay
│ │ ├── BaseOverlay.js
│ │ ├── Circle.js
│ │ ├── Custom.js
│ │ ├── GroundOverlay.js
│ │ ├── Icon.js
│ │ ├── IconSequence.js
│ │ ├── InfoWindow.js
│ │ ├── Label.js
│ │ ├── Marker.js
│ │ ├── PointCollection.js
│ │ ├── Polygon.js
│ │ ├── Polyline.js
│ │ └── Symbol.js
│ ├── constants
│ │ └── index.js
│ ├── index.js
│ ├── options
│ │ ├── autoComplete.js
│ │ ├── circle.js
│ │ ├── ground.js
│ │ ├── infoWindow.js
│ │ ├── label.js
│ │ ├── map.js
│ │ ├── marker.js
│ │ ├── polygon.js
│ │ ├── polyline.js
│ │ └── symbol.js
│ └── utils
│ │ ├── index.js
│ │ └── map.js
└── index.js
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | "stage-0"
6 | ],
7 | "plugins": [
8 | "transform-runtime",
9 | "transform-decorators-legacy",
10 | "babel-plugin-transform-regenerator"
11 | ]
12 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "parser": "babel-eslint",
4 | "env": {
5 | "browser": true
6 | },
7 | "rules": {
8 | "import/no-extraneous-dependencies": "off",
9 | "no-param-reassign": "off",
10 | "react/prop-types": "off",
11 | "no-underscore-dangle": "warn",
12 | "linebreak-style": "off",
13 | "global-require": "warn",
14 | "react/jsx-filename-extension": "off",
15 | "react/require-default-props": "off",
16 | "react/forbid-prop-types": "off",
17 | "react/destructuring-assignment": "off",
18 | "react/no-array-index-key": "off"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | **Do you want to request a *feature* or report a *bug*?**
2 |
3 | **What is the current behavior?**
4 |
5 | **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run. Paste the link to your CodeSandbox (https://codesandbox.io/s/jnnxrwq5y3) example below:**
6 |
7 | **What is the expected behavior?**
8 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | First of all, thank you for your contribution! :-)
2 |
3 | Please makes sure that these checkboxes are checked before submitting your PR, thank you!
4 |
5 | * [ ] Make sure that you propose PR to right branch: bugfix for `master`, feature for latest active branch `vx.x.x`.
6 | * [ ] Rebase before creating a PR to keep commit history clear.
7 | * [ ] Add some descriptions and refer relative issues for you PR.
8 |
9 | Extra checklist:
10 | if** *isNewFeature* **:**
11 |
12 | * [ ] Update API docs for the component.
13 | * [ ] Update/Add demo to demonstrate new feature.
14 | * [ ] Update TypeScript definition for the component.
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # dependencies
2 | /node_modules
3 |
4 | .DS_Store
5 | .env.local
6 | .env.development.local
7 | .env.test.local
8 | .env.production.local
9 |
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | /docs/.vuepress/dist
14 | .vscode
15 |
16 | lib
17 | dist
18 | package-lock.json
19 | /.idea
20 | /lib/
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 JserClub
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React BaiduMap
2 |
3 |
4 |
5 |
6 | 基于 React 的百度地图组件
7 |
8 | []()
9 | []()
10 |
11 | ## 文档
12 |
13 | 1.x文档地址:
14 |
15 | [http://jser.wang/bmap/](http://jser.wang/bmap/)
16 |
17 | 0.2.4文档地址:
18 |
19 | [https://bmap.jser-club.com](https://bmap.jser-club.com)
20 |
21 | ## 安装
22 |
23 | ```
24 | npm install rc-bmap
25 | ```
26 |
27 | 当前通过npm 或 yarn 直接安装为最新版,若想指定安装0.2.4版本时可通过:
28 | ```
29 | npm install rc-bmap@0.2.4
30 | ```
31 |
32 | ## 协议
33 |
34 | [MIT 许可证](https://opensource.org/licenses/MIT)
35 |
36 | ## 本地开发
37 |
38 | 与`demo`结合的最佳实践:
39 |
40 | 1. 将`demo`工程`clone`至本地。
41 | ``` bash
42 | git clone https://github.com/jser-club/rc-bmap-demo.git
43 | ```
44 | 2. 安装`demo`工程所需依赖。
45 | ``` bash
46 | cd 你刚clone的工程目录
47 | yarn install
48 | ```
49 | 3. 进入`rc-bmap`工程的目录,执行
50 | ``` bash
51 | yarn link
52 | ```
53 | 4. 进入`rc-bmap-dmeo`工程目录执行
54 | ``` bash
55 | yarn link rc-bmap
56 | ```
57 | 5. 修改完`rc-bmap`的源码后,在`rc-bmap`工程执行
58 | ``` bash
59 | yarn run build
60 | ```
61 | 如果在windows系统下
62 | ```bash
63 | yarn run build_win
64 | ```
65 | 6. 在`demo`重新点击按钮运行,即可看到最新修改后的效果
66 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rc-bmap",
3 | "version": "1.0.5",
4 | "main": "lib/index.js",
5 | "repository": {
6 | "type": "git",
7 | "url": "git+https://github.com/JserWang/rc-bmap.git"
8 | },
9 | "keywords": [
10 | "react",
11 | "baidu-map",
12 | "bmap",
13 | "rc-bmap",
14 | "baidu",
15 | "map"
16 | ],
17 | "files": [
18 | "src",
19 | "lib",
20 | "types"
21 | ],
22 | "license": "MIT",
23 | "homepage": "http://jser.wang/bmap",
24 | "dependencies": {
25 | "babel-plugin-transform-regenerator": "^6.26.0",
26 | "babel-plugin-transform-runtime": "^6.23.0",
27 | "lodash.isequal": "^4.5.0",
28 | "prop-types": "^15.6.2"
29 | },
30 | "scripts": {
31 | "build": "rm -rf lib && babel src -d lib",
32 | "build_win": "rimraf lib && babel src -d lib",
33 | "prepublish": "npm run build",
34 | "pub": "npm run prepublish && npm publish"
35 | },
36 | "devDependencies": {
37 | "@types/react": "^16.4.9",
38 | "babel-cli": "^6.26.0",
39 | "babel-core": "^6.26.3",
40 | "babel-eslint": "^8.2.6",
41 | "babel-loader": "^7.1.5",
42 | "babel-plugin-transform-decorators-legacy": "^1.3.5",
43 | "babel-preset-es2015": "^6.24.1",
44 | "babel-preset-react": "^6.24.1",
45 | "babel-preset-stage-0": "^6.24.1",
46 | "eslint": "^5.3.0",
47 | "eslint-config-airbnb": "^17.1.0",
48 | "eslint-plugin-import": "^2.14.0",
49 | "eslint-plugin-jsx-a11y": "^6.1.1",
50 | "eslint-plugin-react": "^7.11.0",
51 | "react": "^16.4.1",
52 | "react-dom": "^16.4.1"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/components/AutoComplete/index.js:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Util, AutoComplete as BAutoComplete } from '../../core';
4 |
5 | class AutoComplete extends PureComponent {
6 | instance = null;
7 |
8 | config = {}
9 |
10 | static childContextTypes = {
11 | centralizedUpdates: PropTypes.func,
12 | }
13 |
14 | getChildContext() {
15 | return {
16 | centralizedUpdates: this.centralizedUpdates,
17 | };
18 | }
19 |
20 | componentDidMount() {
21 | const { children, ...resetProps } = this.props;
22 | this.config = { ...this.config, ...resetProps };
23 | this.control = new BAutoComplete(this.config);
24 | this.instance = this.control.instance;
25 | }
26 |
27 | componentDidUpdate() {
28 | const { children, ...resetProps } = this.props;
29 | this.config = { ...this.config, ...resetProps };
30 | this.control.repaint(this.config);
31 | }
32 |
33 | componentWillUnmount() {
34 | this.control.destroy();
35 | }
36 |
37 | centralizedUpdates = ({ name, data }) => {
38 | const configName = Util.firstLowerCase(name);
39 | this.config[configName] = data;
40 | }
41 |
42 | render() {
43 | const { children } = this.props;
44 | return children || null;
45 | }
46 | }
47 |
48 | export default AutoComplete;
49 |
--------------------------------------------------------------------------------
/src/components/Base/Bounds.js:
--------------------------------------------------------------------------------
1 | import Common from './Common';
2 |
3 | export default class Bounds extends Common {
4 | static displayName = 'Bounds'
5 |
6 | getData = () => ({
7 | name: this.props.name || 'bounds',
8 | data: {
9 | sw: this.config.sw || this.props.sw,
10 | ne: this.config.ne || this.props.ne,
11 | },
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/src/components/Base/Common.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Util } from '../../core';
4 |
5 | class Common extends PureComponent {
6 | static contextTypes = {
7 | centralizedUpdates: PropTypes.func,
8 | }
9 |
10 | config = {}
11 |
12 | static displayName = 'CommonBaseComponent';
13 |
14 | static childContextTypes = {
15 | centralizedUpdates: PropTypes.func,
16 | }
17 |
18 | getChildContext() {
19 | return {
20 | centralizedUpdates: this.centralizedUpdates,
21 | };
22 | }
23 |
24 | componentDidMount() {
25 | const { context, getData } = this;
26 | const data = (getData && getData()) || {};
27 | context.centralizedUpdates(data);
28 | }
29 |
30 | componentDidUpdate() {
31 | const { context, getData } = this;
32 | const data = (getData && getData()) || {};
33 | context.centralizedUpdates(data);
34 | }
35 |
36 | componentWillUnmount() {
37 | const { context, getData } = this;
38 | const data = (getData && getData()) || {};
39 | data.data = null;
40 | context.centralizedUpdates(data);
41 | }
42 |
43 | centralizedUpdates = ({ name, data }) => {
44 | const configName = Util.firstLowerCase(name);
45 | this.config[configName] = data;
46 | }
47 |
48 | render() {
49 | const { children } = this.props;
50 | if (children) {
51 | return {children}
;
52 | }
53 | return null;
54 | }
55 | }
56 |
57 | export default Common;
58 |
--------------------------------------------------------------------------------
/src/components/Base/Events.js:
--------------------------------------------------------------------------------
1 | import Common from './Common';
2 |
3 | export default class Events extends Common {
4 | static displayName = 'Events'
5 |
6 | getData = () => ({
7 | name: 'events',
8 | data: this.props,
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/components/Base/Path.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | export default class Path extends PureComponent {
5 | static displayName = 'Path'
6 |
7 | static contextTypes = {
8 | centralizedUpdates: PropTypes.func,
9 | }
10 |
11 | items = []
12 |
13 | static childContextTypes = {
14 | addPoint: PropTypes.func,
15 | updatePoint: PropTypes.func,
16 | removePoint: PropTypes.func,
17 | }
18 |
19 | getChildContext() {
20 | return {
21 | addPoint: this.addPoint,
22 | updatePoint: this.updatePoint,
23 | removePoint: this.removePoint,
24 | };
25 | }
26 |
27 | componentDidMount() {
28 | const { context } = this;
29 | context.centralizedUpdates({
30 | name: this.props.name || 'path',
31 | data: [...this.items],
32 | });
33 | }
34 |
35 | componentDidUpdate() {
36 | const { context } = this;
37 | // filter undefined item
38 | context.centralizedUpdates({
39 | name: this.props.name || 'path',
40 | data: [...this.items.filter(i => i)],
41 | });
42 | }
43 |
44 | componentWillUnmount() {
45 | const { context } = this;
46 | context.centralizedUpdates({
47 | name: this.props.name || 'path',
48 | data: null,
49 | });
50 | }
51 |
52 | addPoint = (index, item) => {
53 | if (this.items[index]) {
54 | this.items.splice(index, 0, item);
55 | } else {
56 | this.items[index] = item;
57 | }
58 | }
59 |
60 | updatePoint = (index, item) => {
61 | this.items[index] = item;
62 | }
63 |
64 | removePoint = (index) => {
65 | // Fix sync call removePoint cause index confusion
66 | // https://github.com/jser-club/rc-bmap/issues/92
67 | this.items.splice(index, 1, undefined);
68 | }
69 |
70 | renderChildren = () => React.Children.map(this.props.children, (child, index) => {
71 | if (child) {
72 | return React.cloneElement(child, {
73 | index,
74 | });
75 | }
76 | return null;
77 | })
78 |
79 | render() {
80 | return (
81 |
82 | {this.renderChildren()}
83 |
84 | );
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/components/Base/Point.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import Common from './Common';
3 |
4 | export default class Point extends Common {
5 | static displayName = 'Point'
6 |
7 | static contextTypes = {
8 | centralizedUpdates: PropTypes.func,
9 | addPoint: PropTypes.func,
10 | updatePoint: PropTypes.func,
11 | removePoint: PropTypes.func,
12 | }
13 |
14 | componentDidMount() {
15 | const { context } = this;
16 | const {
17 | index, name = 'point', ...resetProps
18 | } = this.props;
19 | // 若存在addPoint,则证明在Path下,不进行统一数据变更逻辑
20 | if (context.addPoint) {
21 | context.addPoint(index, { ...resetProps });
22 | } else {
23 | this.centralizedUpdates(name, { ...resetProps });
24 | }
25 | }
26 |
27 | componentDidUpdate() {
28 | const { context } = this;
29 | const {
30 | index, name = 'point', ...resetProps
31 | } = this.props;
32 | if (context.updatePoint) {
33 | context.updatePoint(index, { ...resetProps });
34 | } else {
35 | this.centralizedUpdates(name, { ...resetProps });
36 | }
37 | }
38 |
39 | componentWillUnmount() {
40 | const { context } = this;
41 | const { index } = this.props;
42 | if (context.removePoint) {
43 | context.removePoint(index);
44 | }
45 | }
46 |
47 | centralizedUpdates = (name, item) => {
48 | this.context.centralizedUpdates({
49 | name,
50 | data: item,
51 | });
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/components/Base/Size.js:
--------------------------------------------------------------------------------
1 | import Common from './Common';
2 |
3 | export default class Size extends Common {
4 | static displayName = 'Size'
5 |
6 | getData = () => {
7 | const { width, height, name = 'size' } = this.props;
8 |
9 | const data = { width, height };
10 | return { name, data };
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/components/Base/index.js:
--------------------------------------------------------------------------------
1 | import Point from './Point';
2 | import Size from './Size';
3 | import Events from './Events';
4 | import Bounds from './Bounds';
5 | import Path from './Path';
6 |
7 | export default class Base {
8 | static Point = Point;
9 |
10 | static Size = Size;
11 |
12 | static Events = Events;
13 |
14 | static Bounds = Bounds;
15 |
16 | static Path = Path;
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/ContextMenu/Item.js:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Util, BMapUtil, Constants } from '../../core';
4 |
5 | const { CONTEXT_MENU_ICON } = Constants;
6 | // 内置ContextMenuIcon集合
7 | const builtInArray = [CONTEXT_MENU_ICON.ZOOM_IN, CONTEXT_MENU_ICON.ZOOM_OUT];
8 |
9 | /**
10 | * 处理icon
11 | * @param {*} iconUrl icon链接
12 | */
13 | const getIconUrl = (iconUrl) => {
14 | let icon = iconUrl;
15 | if (iconUrl && builtInArray.indexOf(iconUrl) > -1) {
16 | icon = global[iconUrl];
17 | }
18 | return icon;
19 | };
20 |
21 | export default class ContextMenuItem extends PureComponent {
22 | displayName = 'ContextMenuItem'
23 |
24 | instance = null
25 |
26 | static contextTypes = {
27 | addMenuItem: PropTypes.func,
28 | updateMenuItem: PropTypes.func,
29 | removeMenuItem: PropTypes.func,
30 | }
31 |
32 | componentDidMount() {
33 | const { context } = this;
34 | const { index } = this.props;
35 |
36 | this.instance = this.getInstance();
37 | context.addMenuItem(index, this.instance);
38 | }
39 |
40 | componentDidUpdate() {
41 | const { context } = this;
42 | const { index } = this.props;
43 | this.instance = this.getInstance();
44 | context.updateMenuItem(index, this.instance);
45 | }
46 |
47 | componentWillUnmount() {
48 | const { context } = this;
49 | const { index } = this.props;
50 | context.removeMenuItem(index);
51 | }
52 |
53 | /**
54 | * 根据 props 初始化MenuItem
55 | */
56 | getInstance = () => {
57 | const {
58 | disabled, separator, iconUrl,
59 | text, width, id, onClick,
60 | } = this.props;
61 | const menuItem = BMapUtil.BMenuItem(text, onClick, {
62 | id,
63 | width,
64 | iconUrl: getIconUrl(iconUrl),
65 | });
66 | menuItem.separator = separator;
67 | if (!Util.isNil(disabled) && disabled) {
68 | menuItem.disable();
69 | } else {
70 | menuItem.enable();
71 | }
72 | return menuItem;
73 | }
74 |
75 | render() {
76 | return null;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/components/ContextMenu/index.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Item from './Item';
4 | import { BMapUtil } from '../../core';
5 |
6 | export default class ContextMenu extends PureComponent {
7 | static Item = Item
8 |
9 | displayName = 'ContextMenu'
10 |
11 | static contextTypes = {
12 | centralizedUpdates: PropTypes.func,
13 | }
14 |
15 | // 子元素集合
16 | menuItems = [];
17 |
18 | // BContextMenu实例
19 | instance = null
20 |
21 | static childContextTypes = {
22 | addMenuItem: PropTypes.func,
23 | updateMenuItem: PropTypes.func,
24 | removeMenuItem: PropTypes.func,
25 | }
26 |
27 | getChildContext() {
28 | return {
29 | addMenuItem: this.addMenuItem,
30 | updateMenuItem: this.updateMenuItem,
31 | removeMenuItem: this.removeMenuItem,
32 | };
33 | }
34 |
35 | componentDidMount() {
36 | const { context } = this;
37 | this.repaint();
38 | context.centralizedUpdates({
39 | name: 'contextMenu',
40 | data: this.instance,
41 | });
42 | }
43 |
44 | componentDidUpdate() {
45 | const { context } = this;
46 | this.repaint();
47 | context.centralizedUpdates({
48 | name: 'contextMenu',
49 | data: this.instance,
50 | });
51 | }
52 |
53 | addMenuItem = (index, item) => {
54 | if (this.menuItems[index]) {
55 | this.menuItems.splice(index, 0, item);
56 | } else {
57 | this.menuItems[index] = item;
58 | }
59 | }
60 |
61 | updateMenuItem = (index, item) => {
62 | this.menuItems[index] = item;
63 | }
64 |
65 | removeMenuItem = (index) => {
66 | this.menuItems.splice(index, 1, undefined);
67 | }
68 |
69 | repaint = () => {
70 | this.instance = BMapUtil.BContextMenu([...this.menuItems.filter(i => i)]);
71 | }
72 |
73 | renderChildren = () => React.Children.map(this.props.children, (child, index) => {
74 | if (child) {
75 | // 这里将 index 传递给MenuItem,保证子元素的显示顺序
76 | return React.cloneElement(child, {
77 | index,
78 | });
79 | }
80 | return null;
81 | })
82 |
83 | render() {
84 | return (
85 |
86 | {this.renderChildren()}
87 |
88 | );
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/components/Control/BaseControl.js:
--------------------------------------------------------------------------------
1 |
2 | import { PureComponent } from 'react';
3 | import PropTypes from 'prop-types';
4 | import { Util } from '../../core';
5 |
6 | class BaseControl extends PureComponent {
7 | static contextTypes = {
8 | getMapInstance: PropTypes.func,
9 | }
10 |
11 | static childContextTypes = {
12 | centralizedUpdates: PropTypes.func,
13 | }
14 |
15 | control = null
16 |
17 | mapInstance = null
18 |
19 | config = {}
20 |
21 | getChildContext() {
22 | return {
23 | centralizedUpdates: this.centralizedUpdates,
24 | };
25 | }
26 |
27 | componentDidMount() {
28 | const { context, props } = this;
29 | const { children, ...resetProps } = props;
30 | this.config = { ...this.config, ...resetProps };
31 | this.mapInstance = context.getMapInstance();
32 | const control = this.getRealControl();
33 | this.control = control;
34 | this.instance = control.instance;
35 | }
36 |
37 | componentDidUpdate() {
38 | const { children, ...resetProps } = this.props;
39 | this.config = { ...this.config, ...resetProps };
40 | this.control.repaint(this.config);
41 | }
42 |
43 | componentWillUnmount() {
44 | this.control.destroy();
45 | }
46 |
47 | centralizedUpdates = ({ name, data }) => {
48 | const configName = Util.firstLowerCase(name);
49 | this.config[configName] = data;
50 | }
51 |
52 | render() {
53 | const { children } = this.props;
54 | return children || null;
55 | }
56 | }
57 |
58 | export default BaseControl;
59 |
--------------------------------------------------------------------------------
/src/components/Control/CityList.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { CityList as BCityList } from '../../core';
3 | import BaseControl from './BaseControl';
4 |
5 | class CityList extends BaseControl {
6 | getRealControl = () => new BCityList(this.config, this.mapInstance)
7 |
8 | render() {
9 | const { children } = this.props;
10 | if (children) {
11 | return {children}
;
12 | }
13 | return null;
14 | }
15 | }
16 |
17 | export default CityList;
18 |
--------------------------------------------------------------------------------
/src/components/Control/CopyrightControl.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Copyright as BCopyright } from '../../core';
4 | import BaseControl from './BaseControl';
5 |
6 | import Copyright from '../Copyright';
7 |
8 | class CopyrightControl extends BaseControl {
9 | static Copyright = Copyright;
10 |
11 | static childContextTypes = {
12 | addCopyright: PropTypes.func,
13 | updateCopyright: PropTypes.func,
14 | removeCopyright: PropTypes.func,
15 | }
16 |
17 | config = {
18 | copyrights: [],
19 | }
20 |
21 | getChildContext() {
22 | return {
23 | addCopyright: this.addCopyright,
24 | updateCopyright: this.updateCopyright,
25 | removeCopyright: this.removeCopyright,
26 | };
27 | }
28 |
29 | addCopyright = (index, item) => {
30 | if (this.config.copyrights[index]) {
31 | this.config.copyrights.splice(index, 0, item);
32 | } else {
33 | this.config.copyrights[index] = item;
34 | }
35 | }
36 |
37 | updateCopyright = (index, item) => {
38 | this.config.copyrights.splice(index, 1, item);
39 | }
40 |
41 | removeCopyright = (index) => {
42 | this.config.copyrights.splice(index, 1, undefined);
43 | }
44 |
45 | getRealControl = () => {
46 | this.config.copyrights = this.config.copyrights.filter(item => item);
47 | return new BCopyright(this.config, this.mapInstance)
48 | }
49 |
50 | renderChildren = () => React.Children.map(this.props.children, (child, index) => {
51 | if (child) {
52 | return React.cloneElement(child, {
53 | index,
54 | });
55 | }
56 | return null;
57 | })
58 |
59 | render() {
60 | return (
61 |
62 | {this.renderChildren()}
63 |
64 | );
65 | }
66 | }
67 |
68 | export default CopyrightControl;
69 |
--------------------------------------------------------------------------------
/src/components/Control/Custom.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { initCustomControl } from '../../core';
3 | import BaseControl from './BaseControl';
4 |
5 | const CustomHOC = WrappedComponent => class extends BaseControl {
6 | config = {}
7 |
8 | control = null
9 |
10 | componentDidMount() {
11 | const { context } = this;
12 | const { children, ...resetProps } = this.props;
13 | this.config = { ...this.config, ...resetProps };
14 | this.mapInstance = context.getMapInstance();
15 | this.control = initCustomControl(this.config, this.initialize, this.mapInstance);
16 | }
17 |
18 | getContainer = (ref) => {
19 | this.container = ref;
20 | }
21 |
22 | initialize = () => {
23 | const { container, mapInstance } = this;
24 | mapInstance.getContainer().appendChild(container);
25 | return container;
26 | }
27 |
28 | render() {
29 | const { context } = this;
30 | const { children } = this.props;
31 | return (
32 |
33 |
37 | { children }
38 |
39 | );
40 | }
41 | };
42 |
43 | export default CustomHOC;
44 |
--------------------------------------------------------------------------------
/src/components/Control/Geolocation.js:
--------------------------------------------------------------------------------
1 | import { Geolocation as BGeolocation } from '../../core';
2 | import BaseControl from './BaseControl';
3 |
4 | class Geolocation extends BaseControl {
5 | getRealControl = () => new BGeolocation(this.config, this.mapInstance)
6 | }
7 |
8 | export default Geolocation;
9 |
--------------------------------------------------------------------------------
/src/components/Control/MapType.js:
--------------------------------------------------------------------------------
1 | import { MapType as BMapType } from '../../core';
2 | import BaseControl from './BaseControl';
3 |
4 | class MapType extends BaseControl {
5 | getRealControl = () => new BMapType(this.config, this.mapInstance)
6 | }
7 |
8 | export default MapType;
9 |
--------------------------------------------------------------------------------
/src/components/Control/Navigation.js:
--------------------------------------------------------------------------------
1 | import { Navigation as BNavigation } from '../../core';
2 | import BaseControl from './BaseControl';
3 |
4 | class Navigation extends BaseControl {
5 | getRealControl = () => new BNavigation(this.config, this.mapInstance)
6 | }
7 |
8 | export default Navigation;
9 |
--------------------------------------------------------------------------------
/src/components/Control/OverviewMap.js:
--------------------------------------------------------------------------------
1 | import BaseControl from './BaseControl';
2 | import { OverviewMap as BOverviewMap } from '../../core';
3 |
4 | class OverviewMap extends BaseControl {
5 | getRealControl = () => new BOverviewMap(this.config, this.mapInstance)
6 | }
7 |
8 | export default OverviewMap;
9 |
--------------------------------------------------------------------------------
/src/components/Control/Panorama.js:
--------------------------------------------------------------------------------
1 | import { Panorama as BPanorama } from '../../core';
2 | import BaseControl from './BaseControl';
3 |
4 | class Panorama extends BaseControl {
5 | getRealControl = () => new BPanorama(this.config, this.mapInstance)
6 | }
7 |
8 | export default Panorama;
9 |
--------------------------------------------------------------------------------
/src/components/Control/Scale.js:
--------------------------------------------------------------------------------
1 | import BaseControl from './BaseControl';
2 | import { Scale as BScale } from '../../core';
3 |
4 | class Scale extends BaseControl {
5 | getRealControl = () => new BScale(this.config, this.mapInstance)
6 | }
7 |
8 | export default Scale;
9 |
--------------------------------------------------------------------------------
/src/components/Copyright/index.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | const containerStyle = {
5 | position: 'absolute',
6 | top: -10000,
7 | };
8 |
9 | export default class Copyright extends PureComponent {
10 | static contextTypes = {
11 | getMapInstance: PropTypes.func,
12 | addCopyright: PropTypes.func,
13 | updateCopyright: PropTypes.func,
14 | removeCopyright: PropTypes.func,
15 | }
16 |
17 | componentDidMount() {
18 | const { context } = this;
19 | const { index } = this.props;
20 | context.addCopyright(index, this.getCopyright());
21 | }
22 |
23 | componentDidUpdate() {
24 | const { context } = this;
25 | const { index } = this.props;
26 | context.updateCopyright(index, this.getCopyright());
27 | }
28 |
29 | componentWillUnmount() {
30 | const { context } = this;
31 | const { index } = this.props;
32 | context.removeCopyright(index);
33 | }
34 |
35 | getCopyright = () => {
36 | const { context } = this;
37 | const { index, bounds } = this.props;
38 | return {
39 | id: index,
40 | bounds: bounds || context.getMapInstance().getBounds(),
41 | content: this.container.innerHTML,
42 | };
43 | }
44 |
45 | getContainer = (ref) => {
46 | this.container = ref;
47 | }
48 |
49 | render() {
50 | const { children } = this.props;
51 | return (
52 |
53 | {children}
54 |
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/components/Layer/TileLayer.js:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { TileLayer as BTileLayer } from '../../core';
4 |
5 | class TileLayer extends PureComponent {
6 | static contextTypes = {
7 | getMapInstance: PropTypes.func,
8 | }
9 |
10 | componentDidMount() {
11 | const { context, props } = this;
12 | const { children, ...resetProps } = props;
13 | this.config = { ...this.config, ...resetProps };
14 | this.mapInstance = context.getMapInstance();
15 | const layer = new BTileLayer(this.config, this.mapInstance);
16 | this.layer = layer;
17 | this.instance = layer.instance;
18 | }
19 |
20 | componentDidUpdate() {
21 | const { children, ...resetProps } = this.props;
22 | this.config = { ...this.config, ...resetProps };
23 | this.layer.repaint({ ...this.config });
24 | }
25 |
26 | componentWillUnmount() {
27 | this.layer.destroy();
28 | }
29 |
30 | render() {
31 | const { children } = this.props;
32 | return children || null;
33 | }
34 | }
35 |
36 | export default TileLayer;
37 |
--------------------------------------------------------------------------------
/src/components/Layer/TrafficLayer.js:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { TrafficLayer as BTrafficLayer } from '../../core';
4 |
5 | class TrafficLayer extends PureComponent {
6 | static contextTypes = {
7 | getMapInstance: PropTypes.func,
8 | }
9 |
10 | componentDidMount() {
11 | const { context, props } = this;
12 | const { children, ...resetProps } = props;
13 | this.config = { ...this.config, ...resetProps };
14 | this.mapInstance = context.getMapInstance();
15 | const layer = new BTrafficLayer(this.config, this.mapInstance);
16 | this.layer = layer;
17 | this.instance = layer.instance;
18 | }
19 |
20 | componentDidUpdate() {
21 | const { children, ...resetProps } = this.props;
22 | this.config = { ...this.config, ...resetProps };
23 | this.layer.repaint({ ...this.config });
24 | }
25 |
26 | componentWillUnmount() {
27 | this.layer.destroy();
28 | }
29 |
30 | render() {
31 | const { children } = this.props;
32 | return children || null;
33 | }
34 | }
35 |
36 | export default TrafficLayer;
37 |
--------------------------------------------------------------------------------
/src/components/Library/CurveLine/index.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { CurveLine as BCurveLine, Util } from '../../../core';
4 |
5 | class CurveLine extends PureComponent {
6 | static contextTypes = {
7 | getMapInstance: PropTypes.func,
8 | }
9 |
10 | static childContextTypes = {
11 | centralizedUpdates: PropTypes.func,
12 | }
13 |
14 | config = {}
15 |
16 | getChildContext() {
17 | return {
18 | centralizedUpdates: this.centralizedUpdates,
19 | };
20 | }
21 |
22 | componentDidMount() {
23 | const map = this.context.getMapInstance();
24 |
25 | const { children, ...resetProps } = this.props;
26 | this.config = { ...this.config, ...resetProps };
27 |
28 | Util.syncScript('https://api.map.baidu.com/library/CurveLine/1.5/src/CurveLine.min.js')
29 | .then(() => {
30 | this.tool = new BCurveLine({ ...this.config }, map);
31 | if (this.props.getInstance) {
32 | this.props.getInstance(this.tool.instance);
33 | }
34 | });
35 | }
36 |
37 | componentDidUpdate() {
38 | if (this.tool) {
39 | const { children, ...resetProps } = this.props;
40 | this.config = { ...this.config, ...resetProps };
41 | this.tool.repaint(this.config);
42 | }
43 | }
44 |
45 |
46 | componentWillUnmount() {
47 | if (this.tool) {
48 | this.tool.destroy();
49 | }
50 | }
51 |
52 | centralizedUpdates = ({ name, data }) => {
53 | const configName = Util.firstLowerCase(name);
54 | this.config[configName] = data;
55 | }
56 |
57 | render() {
58 | const { children } = this.props;
59 | return (
60 |
61 | {children}
62 |
63 | );
64 | }
65 | }
66 |
67 | export default CurveLine;
68 |
--------------------------------------------------------------------------------
/src/components/Library/DistanceTool/Icon.js:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Icon as BIcon, Util } from '../../../core';
4 |
5 | export default class Icon extends PureComponent {
6 | config = {}
7 |
8 | static contextTypes = {
9 | centralizedUpdates: PropTypes.func,
10 | }
11 |
12 | static childContextTypes = {
13 | centralizedUpdates: PropTypes.func,
14 | }
15 |
16 | getChildContext() {
17 | return {
18 | centralizedUpdates: this.centralizedUpdates,
19 | };
20 | }
21 |
22 | componentDidMount() {
23 | const { context, props } = this;
24 | context.centralizedUpdates({
25 | name: props.name || 'secIcon',
26 | data: this.getIcon(),
27 | });
28 | }
29 |
30 | componentDidUpdate() {
31 | const { context, props } = this;
32 | context.centralizedUpdates({
33 | name: props.name || 'secIcon',
34 | data: this.getIcon(),
35 | });
36 | }
37 |
38 | centralizedUpdates = ({ name, data }) => {
39 | const configName = Util.firstLowerCase(name);
40 | this.config[configName] = data;
41 | }
42 |
43 | getIcon = () => {
44 | const { children, ...resetProps } = this.props;
45 | this.config = { ...this.config, ...resetProps };
46 |
47 | return new BIcon({ ...this.config });
48 | }
49 |
50 | render() {
51 | const { children } = this.props;
52 | return children || null;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/components/Library/DistanceTool/index.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Icon from './Icon';
4 | import { DistanceTool as BDistanceTool, Util } from '../../../core';
5 |
6 | class DistanceTool extends PureComponent {
7 | static Icon = Icon
8 |
9 | static contextTypes = {
10 | getMapInstance: PropTypes.func,
11 | }
12 |
13 | static childContextTypes = {
14 | centralizedUpdates: PropTypes.func,
15 | }
16 |
17 | config = {}
18 |
19 |
20 | getChildContext() {
21 | return {
22 | centralizedUpdates: this.centralizedUpdates,
23 | };
24 | }
25 |
26 | componentDidMount() {
27 | const map = this.context.getMapInstance();
28 |
29 | const { children, ...resetProps } = this.props;
30 | this.config = { ...this.config, ...resetProps };
31 |
32 | Util.syncScript('https://api.map.baidu.com/library/DistanceTool/1.2/src/DistanceTool_min.js')
33 | .then(() => {
34 | this.tool = new BDistanceTool({ ...this.config }, map);
35 | if (this.props.getInstance) {
36 | this.props.getInstance(this.tool.instance);
37 | }
38 | });
39 | }
40 |
41 | componentDidUpdate() {
42 | if (this.tool) {
43 | const { children, ...resetProps } = this.props;
44 | this.config = { ...this.config, ...resetProps };
45 | this.tool.init(this.config);
46 | }
47 | }
48 |
49 |
50 | componentWillUnmount() {
51 | if (this.tool) {
52 | this.tool.destroy();
53 | }
54 | }
55 |
56 | centralizedUpdates = ({ name, data }) => {
57 | const configName = Util.firstLowerCase(name);
58 | this.config[configName] = data;
59 | }
60 |
61 | render() {
62 | const { children } = this.props;
63 | return (
64 |
65 | {children}
66 |
67 | );
68 | }
69 | }
70 |
71 | export default DistanceTool;
72 |
--------------------------------------------------------------------------------
/src/components/Library/HeatMap/index.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { HeatMap as BHeatMap, Util } from '../../../core';
4 |
5 | class HeatMap extends PureComponent {
6 | static contextTypes = {
7 | getMapInstance: PropTypes.func,
8 | }
9 |
10 | static childContextTypes = {
11 | centralizedUpdates: PropTypes.func,
12 | }
13 |
14 | config = {}
15 |
16 | getChildContext() {
17 | return {
18 | centralizedUpdates: this.centralizedUpdates,
19 | };
20 | }
21 |
22 | componentDidMount() {
23 | const map = this.context.getMapInstance();
24 |
25 | const { children, ...resetProps } = this.props;
26 | this.config = { ...this.config, ...resetProps };
27 |
28 | Util.syncScript('https://api.map.baidu.com/library/Heatmap/2.0/src/Heatmap_min.js')
29 | .then(() => {
30 | this.tool = new BHeatMap({ ...this.config }, map);
31 | if (this.props.getInstance) {
32 | this.props.getInstance(this.tool.instance);
33 | }
34 | });
35 | }
36 |
37 | componentDidUpdate() {
38 | if (this.tool) {
39 | const { children, ...resetProps } = this.props;
40 | this.config = { ...this.config, ...resetProps };
41 | this.tool.repaint(this.config);
42 | }
43 | }
44 |
45 |
46 | componentWillUnmount() {
47 | if (this.tool) {
48 | this.tool.destroy();
49 | }
50 | }
51 |
52 | centralizedUpdates = ({ name, data }) => {
53 | const configName = Util.firstLowerCase(name);
54 | this.config[configName] = data;
55 | }
56 |
57 | render() {
58 | const { children } = this.props;
59 | return (
60 |
61 | {children}
62 |
63 | );
64 | }
65 | }
66 |
67 | export default HeatMap;
68 |
--------------------------------------------------------------------------------
/src/components/Map/PlaceHolder.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 |
3 | const style = {
4 | height: '100%',
5 | width: '100%',
6 | display: 'flex',
7 | justifyContent: 'center',
8 | alignItems: 'center',
9 | };
10 |
11 | export default class PlaceHolder extends PureComponent {
12 | static displayName= 'PlaceHolder'
13 |
14 | render() {
15 | const { children } = this.props;
16 | return children || 地图加载中...
;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/Map/index.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import initMap, { Util } from '../../core';
4 | import ContextMenu from '../ContextMenu';
5 | import PlaceHolder from './PlaceHolder';
6 |
7 | const fillStyle = {
8 | width: '100%',
9 | height: '100%',
10 | };
11 |
12 | export default class Map extends PureComponent {
13 | static PlaceHolder = PlaceHolder;
14 |
15 | static ContextMenu = ContextMenu;
16 |
17 | static childContextTypes = {
18 | getMapInstance: PropTypes.func,
19 | centralizedUpdates: PropTypes.func,
20 | }
21 |
22 | config = {}
23 |
24 | // 仅用作config的组件
25 | configComponent = ['Point', 'PlaceHolder']
26 |
27 | getChildContext() {
28 | return {
29 | getMapInstance: this.getMapInstance,
30 | centralizedUpdates: this.centralizedUpdates,
31 | };
32 | }
33 |
34 | componentDidMount() {
35 | const { children, ...resetProps } = this.props;
36 | this.config = { ...this.config, ...resetProps };
37 | this.createMapInstance(this.config);
38 | }
39 |
40 | componentDidUpdate() {
41 | const { children, ...resetProps } = this.props;
42 | this.config = { ...this.config, ...resetProps };
43 | if (this.map) {
44 | this.map.repaint(this.config);
45 | }
46 | }
47 |
48 | /**
49 | * 内部子组件属性更新触发方法
50 | */
51 | centralizedUpdates = ({ name, data }) => {
52 | const configName = Util.firstLowerCase(name);
53 | this.config[configName] = data;
54 | }
55 |
56 | /**
57 | * 初始化地图实例
58 | */
59 | createMapInstance = async (config) => {
60 | const { mounted, name } = this.props;
61 | this.map = await initMap(this.mapContainer, config);
62 | const mapInstance = this.map.instance;
63 | if (name) {
64 | global[`${name}`] = mapInstance;
65 | }
66 | this.forceUpdate(() => {
67 | if (mounted) {
68 | mounted(mapInstance);
69 | }
70 | });
71 | }
72 |
73 | /**
74 | * 获得地图容器ref
75 | */
76 | getMapContainer = (ref) => {
77 | this.mapContainer = ref;
78 | }
79 |
80 | /**
81 | * 获得地图实例
82 | */
83 | getMapInstance = () => this.map && this.map.instance
84 |
85 | renderChildren = () => {
86 | const { children } = this.props;
87 | return React.Children.map(children, (child) => {
88 | if (this.map || (child && this.configComponent.indexOf(child.type.displayName) > -1)) {
89 | return child;
90 | }
91 | return null;
92 | });
93 | }
94 |
95 | render() {
96 | return (
97 |
98 | { this.renderChildren() }
99 |
100 | );
101 | }
102 | }
103 |
104 |
105 | Map.propTypes = {
106 | //
107 | ak: PropTypes.string,
108 | // 地图实例别名
109 | // 设置后可通过window[name]进行获取
110 | name: PropTypes.string,
111 | // 当前缩放等级
112 | zoom: PropTypes.number,
113 | // 当前百度地图版本, 2 or 3
114 | version: PropTypes.number,
115 | // 最小缩放等级
116 | minZoom: PropTypes.number,
117 | // 最大缩放等级
118 | maxZoom: PropTypes.number,
119 | // 设置地图默认的鼠标指针样式
120 | defaultCursor: PropTypes.string,
121 | // 设置拖拽地图时的鼠标指针样式
122 | draggingCursor: PropTypes.string,
123 | // 设置地图样式,样式包括地图底图颜色和地图要素是否展示两部分
124 | mapStyle: PropTypes.object,
125 | // 设置地图个性化样式V2版本,仅支持现代浏览器(支持Canvas)
126 | mapStyleV2: PropTypes.object,
127 | // 设置地图类型
128 | mapType: PropTypes.string,
129 | // 地图初始化完成回调函数
130 | mounted: PropTypes.func,
131 | // 是否启用使用高分辨率地图
132 | highResolution: PropTypes.bool,
133 | // 自动适应地图容器变化
134 | autoResize: PropTypes.bool,
135 | // 地图可点
136 | mapClick: PropTypes.bool,
137 | // 拖拽
138 | dragging: PropTypes.bool,
139 | // 滚轮缩放
140 | scrollWheelZoom: PropTypes.bool,
141 | // 双击放大
142 | doubleClickZoom: PropTypes.bool,
143 | // 键盘操作
144 | keyboard: PropTypes.bool,
145 | // 惯性拖拽
146 | inertialDragging: PropTypes.bool,
147 | // 连续缩放
148 | continuousZoom: PropTypes.bool,
149 | // 双指操作
150 | pinchToZoom: PropTypes.bool,
151 | };
152 |
--------------------------------------------------------------------------------
/src/components/Overlay/BaseOverlay.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Util } from '../../core';
4 |
5 | class BaseOverlay extends PureComponent {
6 | static contextTypes = {
7 | getMapInstance: PropTypes.func,
8 | }
9 |
10 | static childContextTypes = {
11 | centralizedUpdates: PropTypes.func,
12 | }
13 |
14 | overlay = null
15 |
16 | mapInstance = null
17 |
18 | config = {}
19 |
20 | getChildContext() {
21 | return {
22 | centralizedUpdates: this.centralizedUpdates,
23 | };
24 | }
25 |
26 | componentDidMount() {
27 | const { context, props } = this;
28 | const { children, ...resetProps } = props;
29 | this.config = { ...this.config, ...resetProps };
30 | this.mapInstance = context.getMapInstance();
31 | const overlay = this.getRealOverlay();
32 | this.overlay = overlay;
33 | this.instance = overlay.instance;
34 | }
35 |
36 | componentDidUpdate() {
37 | const { children, ...resetProps } = this.props;
38 | this.config = { ...this.config, ...resetProps };
39 | this.overlay.repaint({ ...this.config });
40 | // fix: when the custom overlay change the point, overlay need redraw
41 | if (this.draw) {
42 | this.draw();
43 | }
44 | }
45 |
46 | componentWillUnmount() {
47 | this.overlay.destroy();
48 | }
49 |
50 | centralizedUpdates = ({ name, data }) => {
51 | const configName = Util.firstLowerCase(name);
52 | this.config[configName] = data;
53 | }
54 |
55 | render() {
56 | const { children } = this.props;
57 | if (children) {
58 | return {children}
;
59 | }
60 | return null;
61 | }
62 | }
63 |
64 | export default BaseOverlay;
65 |
--------------------------------------------------------------------------------
/src/components/Overlay/Boundary.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Polygon from './Polygon';
4 | import Base from '../Base';
5 | import { Util } from '../../core';
6 |
7 | const { Point, Path } = Base;
8 |
9 | class Boundary extends PureComponent {
10 | static contextTypes = {
11 | getMapInstance: PropTypes.func,
12 | }
13 |
14 | state = {
15 | name: '',
16 | area: [],
17 | }
18 |
19 | componentDidMount() {
20 | const { name } = this.props;
21 | this.getPoints(name);
22 | }
23 |
24 | componentDidUpdate() {
25 | const { name } = this.props;
26 | if (name !== this.state.name) {
27 | this.getPoints(name);
28 | }
29 | }
30 |
31 | getPoints = (name) => {
32 | Util.getBoundary(name).then(({ points, area }) => {
33 | this.processAutoViewport(points);
34 | this.setState({
35 | name,
36 | area,
37 | });
38 | });
39 | }
40 |
41 | processAutoViewport(points = []) {
42 | const { context, props } = this;
43 | const { autoViewport } = props;
44 | if (autoViewport) {
45 | context.getMapInstance().setViewport(points);
46 | }
47 | }
48 |
49 | render() {
50 | const { area, name } = this.state;
51 | const { children, ...resetProps } = this.props;
52 | return (
53 | area.length > 0 ? (
54 |
55 | {
56 | area.map((points, index) => (
57 |
61 |
62 | {
63 | points.map((item, idx) => (
64 |
65 | ))
66 | }
67 |
68 | { children }
69 |
70 | ))
71 | }
72 |
73 | ) : null
74 | );
75 | }
76 | }
77 |
78 | export default Boundary;
79 |
--------------------------------------------------------------------------------
/src/components/Overlay/Circle.js:
--------------------------------------------------------------------------------
1 | import BaseOverlay from './BaseOverlay';
2 | import { Circle as BCircle } from '../../core';
3 |
4 | class Circle extends BaseOverlay {
5 | getRealOverlay = () => new BCircle(this.config, this.mapInstance)
6 | }
7 |
8 | export default Circle;
9 |
--------------------------------------------------------------------------------
/src/components/Overlay/Custom.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { initCustomOverlay, Util, Constants } from '../../core';
3 | import BaseOverlay from './BaseOverlay';
4 |
5 | const { MAP_PANES } = Constants;
6 |
7 | // fix: #106 the custom overlay's container position should be absolute
8 | const containerStyle = {
9 | position: 'absolute',
10 | };
11 |
12 | const CustomHOC = WrappedComponent => class extends BaseOverlay {
13 | config = {}
14 |
15 | overlay = null
16 |
17 | componentDidMount() {
18 | const { context } = this;
19 | const { children, ...resetProps } = this.props;
20 | this.config = { ...this.config, ...resetProps };
21 | this.mapInstance = context.getMapInstance();
22 | this.overlay = initCustomOverlay(this.config, this.initialize, this.draw, this.mapInstance);
23 | }
24 |
25 | getContainer = (ref) => {
26 | this.container = ref;
27 | }
28 |
29 | initialize = () => {
30 | const { container, mapInstance } = this;
31 | mapInstance.getPanes()[MAP_PANES.MARKER].appendChild(container);
32 | return container;
33 | }
34 |
35 | draw = () => {
36 | const { container, mapInstance } = this;
37 | const { point, offset = { width: 0, height: 0 } } = this.config;
38 | const bdPoint = Util.convert2BPoint({ ...point });
39 | // 当地图scroll时,container的高度为0 宽度为0,导致计算出现错误,所以存储上次有效宽高
40 | this.lastWidth = container.offsetWidth > 0 ? container.offsetWidth : this.lastWidth;
41 | this.lastHeight = container.offsetHeight > 0 ? container.offsetHeight : this.lastHeight;
42 |
43 | const position = mapInstance.pointToOverlayPixel(bdPoint);
44 | container.style.left = `${position.x - this.lastWidth / 2 + offset.width / 2}px`;
45 | container.style.top = `${position.y - this.lastHeight / 2 + offset.height / 2}px`;
46 | }
47 |
48 | render() {
49 | const { context } = this;
50 | const { children } = this.props;
51 | return (
52 |
53 |
54 |
58 | { children }
59 |
60 |
61 | );
62 | }
63 | };
64 |
65 | export default CustomHOC;
66 |
--------------------------------------------------------------------------------
/src/components/Overlay/Ground.js:
--------------------------------------------------------------------------------
1 | import { GroundOverlay as BGroundOverlay } from '../../core';
2 | import BaseOverlay from './BaseOverlay';
3 |
4 | class Ground extends BaseOverlay {
5 | getRealOverlay = () => new BGroundOverlay(this.config, this.mapInstance)
6 | }
7 |
8 | export default Ground;
9 |
--------------------------------------------------------------------------------
/src/components/Overlay/HTMLComponent.js:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import ReactDOM from 'react-dom';
3 | import PropTypes from 'prop-types';
4 |
5 | class HTMLComponent extends PureComponent {
6 | static contextTypes = {
7 | centralizedUpdates: PropTypes.func,
8 | }
9 |
10 | static displayName = 'HTMLComponent';
11 |
12 | constructor(props) {
13 | super(props);
14 | this.div = document.createElement('div');
15 | }
16 |
17 | componentDidMount() {
18 | const { context } = this;
19 | ReactDOM.render(this.props.children, this.div);
20 | context.centralizedUpdates({
21 | name: this.name,
22 | data: this.div,
23 | });
24 | }
25 |
26 | componentDidUpdate() {
27 | const { context } = this;
28 | ReactDOM.render(this.props.children, this.div);
29 | context.centralizedUpdates({
30 | name: this.name,
31 | data: this.div,
32 | });
33 | }
34 |
35 | componentWillUnmount() {
36 | const { context } = this;
37 | context.centralizedUpdates({
38 | name: this.name,
39 | data: null,
40 | });
41 | }
42 |
43 | render() {
44 | return null;
45 | }
46 | }
47 |
48 | export default HTMLComponent;
49 |
--------------------------------------------------------------------------------
/src/components/Overlay/HTMLStringComponent.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | const containerStyle = {
5 | position: 'absolute',
6 | top: -10000,
7 | };
8 |
9 | class HTMLStringComponent extends PureComponent {
10 | static contextTypes = {
11 | centralizedUpdates: PropTypes.func,
12 | }
13 |
14 | static displayName = 'HTMLComponent';
15 |
16 | componentDidMount() {
17 | const { context } = this;
18 | this.instance = this.content.innerHTML;
19 | context.centralizedUpdates({
20 | name: this.name,
21 | data: this.content.innerHTML,
22 | });
23 | }
24 |
25 | componentDidUpdate() {
26 | const { context } = this;
27 | context.centralizedUpdates({
28 | name: this.name,
29 | data: this.content.innerHTML,
30 | });
31 | }
32 |
33 | componentWillUnmount() {
34 | const { context } = this;
35 | context.centralizedUpdates({
36 | name: this.name,
37 | data: null,
38 | });
39 | }
40 |
41 | getContent = (ref) => {
42 | this.content = ref;
43 | }
44 |
45 | render() {
46 | const { children } = this.props;
47 | return (
48 |
49 | { children || null }
50 |
51 | );
52 | }
53 | }
54 |
55 | export default HTMLStringComponent;
--------------------------------------------------------------------------------
/src/components/Overlay/InfoWindow/Content.js:
--------------------------------------------------------------------------------
1 | import HTMLComponent from '../HTMLComponent';
2 |
3 | class Content extends HTMLComponent {
4 | name = 'content';
5 | }
6 |
7 | export default Content;
8 |
--------------------------------------------------------------------------------
/src/components/Overlay/InfoWindow/MaxContent.js:
--------------------------------------------------------------------------------
1 | import HTMLComponent from '../HTMLComponent';
2 |
3 | class MaxContent extends HTMLComponent {
4 | name = 'maxContent';
5 | }
6 |
7 | export default MaxContent;
8 |
--------------------------------------------------------------------------------
/src/components/Overlay/InfoWindow/Title.js:
--------------------------------------------------------------------------------
1 | import HTMLComponent from '../HTMLComponent';
2 |
3 | class Title extends HTMLComponent {
4 | name = 'title';
5 | }
6 |
7 | export default Title;
8 |
--------------------------------------------------------------------------------
/src/components/Overlay/InfoWindow/index.js:
--------------------------------------------------------------------------------
1 | import BaseOverlay from '../BaseOverlay';
2 | import { InfoWindow as BInfoWindow } from '../../../core';
3 | import Content from './Content';
4 | import Title from './Title';
5 | import MaxContent from './MaxContent';
6 |
7 | class InfoWindow extends BaseOverlay {
8 | static Content = Content;
9 |
10 | static Title = Title;
11 |
12 | static MaxContent = MaxContent;
13 |
14 | getRealOverlay = () => new BInfoWindow(this.config, this.mapInstance);
15 | }
16 |
17 | export default InfoWindow;
18 |
--------------------------------------------------------------------------------
/src/components/Overlay/Label/Content.js:
--------------------------------------------------------------------------------
1 | import HTMLStringComponent from '../HTMLStringComponent';
2 |
3 | class Content extends HTMLStringComponent {
4 | name = 'content'
5 | }
6 |
7 | export default Content;
8 |
--------------------------------------------------------------------------------
/src/components/Overlay/Label/index.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import BaseOverlay from '../BaseOverlay';
3 | import { Label as BLabel } from '../../../core';
4 | import Content from './Content';
5 |
6 | class Label extends BaseOverlay {
7 | static Content = Content;
8 |
9 | static contextTypes = {
10 | getMapInstance: PropTypes.func,
11 | centralizedUpdates: PropTypes.func,
12 | }
13 |
14 | componentDidMount() {
15 | const { context, props } = this;
16 | const { children, ...resetProps } = props;
17 | this.config = { ...this.config, ...resetProps };
18 | this.mapInstance = context.getMapInstance();
19 | const overlay = this.getRealOverlay();
20 | this.overlay = overlay;
21 | this.instance = overlay.instance;
22 |
23 | context.centralizedUpdates({
24 | name: 'label',
25 | data: this.instance,
26 | });
27 | }
28 |
29 | componentDidUpdate() {
30 | const { context } = this;
31 | const { children, ...resetProps } = this.props;
32 | this.config = { ...this.config, ...resetProps };
33 | this.overlay.repaint({ ...this.config });
34 |
35 | context.centralizedUpdates({
36 | name: 'label',
37 | data: this.overlay.instance,
38 | });
39 | }
40 |
41 | getRealOverlay = () => new BLabel(this.config, this.mapInstance)
42 | }
43 |
44 | export default Label;
45 |
--------------------------------------------------------------------------------
/src/components/Overlay/Marker/Icon.js:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Icon as BIcon, Util } from '../../../core';
4 |
5 | export default class Icon extends PureComponent {
6 | config = {}
7 |
8 | static contextTypes = {
9 | centralizedUpdates: PropTypes.func,
10 | }
11 |
12 | static childContextTypes = {
13 | centralizedUpdates: PropTypes.func,
14 | }
15 |
16 | getChildContext() {
17 | return {
18 | centralizedUpdates: this.centralizedUpdates,
19 | };
20 | }
21 |
22 | componentDidMount() {
23 | const { context } = this;
24 | context.centralizedUpdates({
25 | name: 'icon',
26 | data: this.getIcon(),
27 | });
28 | }
29 |
30 | componentDidUpdate() {
31 | const { context } = this;
32 | context.centralizedUpdates({
33 | name: 'icon',
34 | data: this.getIcon(),
35 | });
36 | }
37 |
38 | centralizedUpdates = ({ name, data }) => {
39 | const configName = Util.firstLowerCase(name);
40 | this.config[configName] = data;
41 | }
42 |
43 | getIcon = () => {
44 | const { children, ...resetProps } = this.props;
45 | this.config = { ...this.config, ...resetProps };
46 |
47 | return new BIcon({ ...this.config });
48 | }
49 |
50 | render() {
51 | const { children } = this.props;
52 | return children || null;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/components/Overlay/Marker/index.js:
--------------------------------------------------------------------------------
1 | import BaseOverlay from '../BaseOverlay';
2 | import ContextMenu from '../../ContextMenu';
3 | import Icon from './Icon';
4 | import Symbol from '../Symbol';
5 | import { Marker as BMarker } from '../../../core';
6 |
7 | class Marker extends BaseOverlay {
8 | static ContextMenu = ContextMenu;
9 |
10 | static Icon = Icon;
11 |
12 | static Symbol = Symbol;
13 |
14 | getRealOverlay = () => {
15 | // symbol 覆盖 icon 属性
16 | if (this.config.symbol) {
17 | this.config.icon = this.config.symbol;
18 | }
19 | return new BMarker(this.config, this.mapInstance);
20 | }
21 | }
22 |
23 | export default Marker;
24 |
--------------------------------------------------------------------------------
/src/components/Overlay/PointCollection.js:
--------------------------------------------------------------------------------
1 | import BaseOverlay from './BaseOverlay';
2 | import { PointCollection as BPointCollection } from '../../core';
3 |
4 | class PointCollection extends BaseOverlay {
5 | getRealOverlay = () => new BPointCollection(this.config, this.mapInstance)
6 | }
7 |
8 | export default PointCollection;
9 |
--------------------------------------------------------------------------------
/src/components/Overlay/Polygon.js:
--------------------------------------------------------------------------------
1 | import BaseOverlay from './BaseOverlay';
2 | import { Polygon as BPolygon } from '../../core';
3 |
4 | class Polygon extends BaseOverlay {
5 | getRealOverlay = () => new BPolygon(this.config, this.mapInstance);
6 | }
7 |
8 | export default Polygon;
9 |
--------------------------------------------------------------------------------
/src/components/Overlay/Polyline/IconSequence.js:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Symbol from '../Symbol';
4 | import { IconSequence as BIconSequence, Util } from '../../../core';
5 |
6 | export default class IconSequence extends PureComponent {
7 | static Symbol = Symbol;
8 |
9 | config = {};
10 |
11 | static contextTypes = {
12 | centralizedUpdates: PropTypes.func,
13 | }
14 |
15 | static childContextTypes = {
16 | centralizedUpdates: PropTypes.func,
17 | }
18 |
19 | getChildContext() {
20 | return {
21 | centralizedUpdates: this.centralizedUpdates,
22 | };
23 | }
24 |
25 | componentDidMount() {
26 | const { context } = this;
27 | context.centralizedUpdates({
28 | name: 'icons',
29 | data: [this.iconSequence()],
30 | });
31 | }
32 |
33 | componentDidUpdate() {
34 | const { context } = this;
35 | context.centralizedUpdates({
36 | name: 'icons',
37 | data: [this.iconSequence()],
38 | });
39 | }
40 |
41 | centralizedUpdates = ({ name, data }) => {
42 | const configName = Util.firstLowerCase(name);
43 | this.config[configName] = data;
44 | }
45 |
46 | iconSequence = () => {
47 | const { children, ...resetProps } = this.props;
48 | this.config = { ...this.config, ...resetProps };
49 | return new BIconSequence({ ...this.config });
50 | }
51 |
52 | render() {
53 | const { children } = this.props;
54 | return children || null;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/components/Overlay/Polyline/index.js:
--------------------------------------------------------------------------------
1 | import IconSequence from './IconSequence';
2 | import BaseOverlay from '../BaseOverlay';
3 | import { Polyline as BPolyline } from '../../../core';
4 |
5 | class Polyline extends BaseOverlay {
6 | static IconSequence = IconSequence;
7 |
8 | getRealOverlay = () => new BPolyline(this.config, this.mapInstance);
9 | }
10 |
11 | export default Polyline;
12 |
--------------------------------------------------------------------------------
/src/components/Overlay/Symbol.js:
--------------------------------------------------------------------------------
1 | import { PureComponent } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Symbol as BSymbol, Util } from '../../core';
4 |
5 | export default class Symbol extends PureComponent {
6 | config = {}
7 |
8 | static contextTypes = {
9 | centralizedUpdates: PropTypes.func,
10 | }
11 |
12 | static childContextTypes = {
13 | centralizedUpdates: PropTypes.func,
14 | }
15 |
16 | getChildContext() {
17 | return {
18 | centralizedUpdates: this.centralizedUpdates,
19 | };
20 | }
21 |
22 | componentDidMount() {
23 | const { context } = this;
24 | context.centralizedUpdates({
25 | name: 'symbol',
26 | data: this.getIcon(),
27 | });
28 | }
29 |
30 | componentDidUpdate() {
31 | const { context } = this;
32 | context.centralizedUpdates({
33 | name: 'symbol',
34 | data: this.getIcon(),
35 | });
36 | }
37 |
38 | centralizedUpdates = ({ name, data }) => {
39 | const configName = Util.firstLowerCase(name);
40 | this.config[configName] = data;
41 | }
42 |
43 | getIcon = () => {
44 | const { children, ...resetProps } = this.props;
45 | this.config = { ...this.config, ...resetProps };
46 |
47 | return new BSymbol({ ...this.config });
48 | }
49 |
50 | render() {
51 | const { children } = this.props;
52 | return children || null;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/core/AutoComplete/index.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 | import OPTIONS from '../options/autoComplete';
4 |
5 | const getAutocompleteOptions = (config, map) => ({
6 | location: config.location || map,
7 | types: config.types,
8 | onSearchComplete: config.onSearchComplete,
9 | input: config.input,
10 | });
11 |
12 | class AutoComplete {
13 | config = {}
14 |
15 | outOfRangeOpts = ['input', 'onSearchComplete']
16 |
17 | hasOutOfRangeOpts = (opts = []) => opts.some(item => this.outOfRangeOpts.indexOf(item) > -1)
18 |
19 | constructor(config = {}, map) {
20 | this.config = { ...config };
21 | this.init(config, map);
22 | }
23 |
24 | init = (config, map) => {
25 | this.checkInputExist();
26 | const options = getAutocompleteOptions(config, map);
27 | this.instance = BMapUtil.BAutocomplete(options);
28 | this.processOptions(config);
29 | this.processEvents(config.events);
30 | }
31 |
32 | checkInputExist = () => {
33 | if (!document.querySelector(`#${this.config.input}`)) {
34 | throw Error(`[Input] ${this.config.input} is not exist when init autocomplete.`);
35 | }
36 | }
37 |
38 | repaint = (config) => {
39 | const diffConfig = Util.compareConfig(this.config, config) || {};
40 | if (this.hasOutOfRangeOpts(Object.keys(diffConfig))) {
41 | this.destroy();
42 | this.init({ ...this.config, ...diffConfig });
43 | } else {
44 | this.processOptions(diffConfig);
45 | }
46 | this.config = { ...this.config, ...diffConfig };
47 | this.processEvents(this.config.events);
48 | }
49 |
50 | destroy = () => {
51 | this.instance.dispose();
52 | }
53 |
54 | processEvents = (events) => {
55 | Util.unbindEvents(this.instance);
56 | Util.bindEvents(this.instance, events);
57 | }
58 |
59 | processOptions(config) {
60 | if (config.value) {
61 | config.inputValue = config.value;
62 | }
63 | Util.processSetOptions(this.instance, OPTIONS.SET, config);
64 | }
65 | }
66 |
67 | export default AutoComplete;
68 |
--------------------------------------------------------------------------------
/src/core/Control/BaseControl.js:
--------------------------------------------------------------------------------
1 | /*
2 | * 基础控件类
3 | * 用于统一处理重绘、销毁逻辑
4 | */
5 |
6 | import Util from '../utils';
7 |
8 | class BaseControl {
9 | instance = null;
10 |
11 | constructor(config, map) {
12 | this.map = map;
13 | this.repaint(config);
14 | }
15 |
16 | /**
17 | * 重绘
18 | */
19 | repaint = (config) => {
20 | this.destroy();
21 | config = { ...config, ...Util.convertControlOptions(config) };
22 | this.init(config);
23 | Util.processControlVisible(this.instance, config.visible);
24 | }
25 |
26 | /**
27 | * 销毁
28 | */
29 | destroy = () => {
30 | if (this.instance) {
31 | this.map.removeControl(this.instance);
32 | this.instance = null;
33 | }
34 | }
35 | }
36 |
37 | export default BaseControl;
38 |
--------------------------------------------------------------------------------
/src/core/Control/CityList.js:
--------------------------------------------------------------------------------
1 | import BMapUtil from '../utils/map';
2 | import BaseControl from './BaseControl';
3 |
4 | const processEvents = (config) => {
5 | const events = config.events || {};
6 | const keys = Object.keys(events);
7 |
8 | keys.forEach((key) => {
9 | config[key] = events[key];
10 | });
11 | };
12 |
13 | class CityList extends BaseControl {
14 | init(config = {}) {
15 | processEvents(config);
16 | this.instance = BMapUtil.BCityListControl(config);
17 | this.map.addControl(this.instance);
18 | }
19 | }
20 |
21 | export default CityList;
22 |
--------------------------------------------------------------------------------
/src/core/Control/Copyright.js:
--------------------------------------------------------------------------------
1 | import BMapUtil from '../utils/map';
2 | import BaseControl from './BaseControl';
3 |
4 | class Copyright extends BaseControl {
5 | init(config = {}) {
6 | const { copyrights = [] } = config;
7 | this.instance = BMapUtil.BCopyrightControl(config);
8 | copyrights.forEach((item) => {
9 | this.instance.addCopyright(item);
10 | });
11 | this.map.addControl(this.instance);
12 | }
13 | }
14 |
15 | export default Copyright;
16 |
--------------------------------------------------------------------------------
/src/core/Control/Custom.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 |
4 | class CustomControl {
5 | constructor(config, map) {
6 | this.map = map;
7 | config = { ...config, ...Util.convertControlOptions(config) };
8 | this.config = { ...config };
9 | this.defaultAnchor = config.anchor;
10 | this.defaultOffset = config.offset;
11 | }
12 |
13 | config = {}
14 |
15 | processOptions = ({ anchor, offset, visible }) => {
16 | if (anchor) {
17 | this.setAnchor(anchor);
18 | }
19 | if (offset) {
20 | this.setOffset(offset);
21 | }
22 | if (!Util.isNil(visible)) {
23 | if (!visible) {
24 | this.hide();
25 | } else {
26 | this.show();
27 | }
28 | }
29 | }
30 |
31 | repaint = (config) => {
32 | config = { ...config, ...Util.convertControlOptions(config) };
33 | const diffConfig = Util.compareConfig(this.config, config);
34 | this.processOptions(diffConfig);
35 | this.config = { ...this.config, ...diffConfig };
36 | }
37 |
38 | destroy = () => {
39 | this.map.removeControl(this);
40 | }
41 | }
42 |
43 | // 异步加载时,BMap对象不存在,所以提供获得类方法,确保调用时BMap对象存在。
44 | const initCustomControl = (config, initialize, mapInstance) => {
45 | CustomControl.prototype = BMapUtil.BControl();
46 | CustomControl.prototype.initialize = initialize;
47 |
48 | const control = new CustomControl(config, mapInstance);
49 | mapInstance.addControl(control);
50 | Util.processControlVisible(control, config.visible);
51 | return control;
52 | };
53 |
54 | export default initCustomControl;
55 |
--------------------------------------------------------------------------------
/src/core/Control/Geolocation.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 | import BaseControl from './BaseControl';
4 |
5 | class Geolocation extends BaseControl {
6 | init(config = {}) {
7 | config.locationIcon = config.icon;
8 | delete config.icon;
9 | this.instance = BMapUtil.BGeolocationControl(config);
10 | this.map.addControl(this.instance);
11 |
12 | Util.bindEvents(this.instance, config.events);
13 | }
14 | }
15 |
16 | export default Geolocation;
17 |
--------------------------------------------------------------------------------
/src/core/Control/MapType.js:
--------------------------------------------------------------------------------
1 | import BMapUtil from '../utils/map';
2 | import BaseControl from './BaseControl';
3 |
4 | const getTypes = types => types && types.map(item => global[item] || item);
5 |
6 | const getMapTypeOptions = config => ({
7 | anchor: config.anchor,
8 | offset: config.offset,
9 | type: global[config.type] || config.type,
10 | mapTypes: getTypes(config.mapTypes),
11 | });
12 |
13 | class MapType extends BaseControl {
14 | init(config = {}) {
15 | const options = getMapTypeOptions(config);
16 | this.instance = BMapUtil.BMapTypeControl(options);
17 | this.map.addControl(this.instance);
18 | }
19 | }
20 |
21 | export default MapType;
22 |
--------------------------------------------------------------------------------
/src/core/Control/Navigation.js:
--------------------------------------------------------------------------------
1 | import BMapUtil from '../utils/map';
2 | import BaseControl from './BaseControl';
3 |
4 | const getNavigationControlOptions = config => ({
5 | anchor: config.anchor,
6 | offset: config.offset,
7 | type: global[config.type] || config.type,
8 | showZoomInfo: config.showZoomInfo,
9 | });
10 |
11 | class Navigation extends BaseControl {
12 | init(config = {}) {
13 | const options = getNavigationControlOptions(config);
14 | this.instance = BMapUtil.BNavigationControl(options);
15 | this.map.addControl(this.instance);
16 | }
17 | }
18 |
19 | export default Navigation;
20 |
--------------------------------------------------------------------------------
/src/core/Control/OverviewMap.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 | import BaseControl from './BaseControl';
4 |
5 | const getOverviewMapControlOptions = config => ({
6 | anchor: config.anchor,
7 | offset: config.offset,
8 | size: config.size && BMapUtil.BSize({ ...config.size }),
9 | isOpen: config.isOpen,
10 | });
11 |
12 | class OverviewMap extends BaseControl {
13 | init(config = {}) {
14 | const options = getOverviewMapControlOptions(config);
15 | this.instance = BMapUtil.BOverviewMapControl(options);
16 | this.map.addControl(this.instance);
17 | Util.bindEvents(this.instance, config.events);
18 | }
19 | }
20 |
21 | export default OverviewMap;
22 |
--------------------------------------------------------------------------------
/src/core/Control/Panorama.js:
--------------------------------------------------------------------------------
1 | import BMapUtil from '../utils/map';
2 | import BaseControl from './BaseControl';
3 |
4 | class Panorama extends BaseControl {
5 | init(config = {}) {
6 | this.instance = BMapUtil.BPanoramaControl(config);
7 | this.map.addControl(this.instance);
8 | }
9 | }
10 |
11 | export default Panorama;
12 |
--------------------------------------------------------------------------------
/src/core/Control/Scale.js:
--------------------------------------------------------------------------------
1 | import BMapUtil from '../utils/map';
2 | import BaseControl from './BaseControl';
3 |
4 | const processUnit = (unit, instance) => {
5 | if (unit) {
6 | unit = global[unit] || unit;
7 | instance.setUnit(unit);
8 | }
9 | };
10 |
11 | class Scale extends BaseControl {
12 | init(config = {}) {
13 | this.instance = BMapUtil.BScaleControl(config);
14 | processUnit(config.unit, this.instance);
15 | this.map.addControl(this.instance);
16 | }
17 | }
18 |
19 | export default Scale;
20 |
--------------------------------------------------------------------------------
/src/core/Layer/TileLayer.js:
--------------------------------------------------------------------------------
1 | import BMapUtil from '../utils/map';
2 |
3 | const getTileLayerOptions = config => ({
4 | transparentPng: config.transparentPng,
5 | tileUrlTemplate: config.tileUrlTemplate,
6 | zIndex: config.zIndex,
7 | });
8 |
9 | class TileLayer {
10 | constructor(config, map) {
11 | this.map = map;
12 | this.init(config);
13 | }
14 |
15 | init(config = {}) {
16 | const options = getTileLayerOptions(config);
17 | this.instance = BMapUtil.BTileLayer(options);
18 | if (config.getTilesUrl) {
19 | this.instance.getTilesUrl = config.getTilesUrl;
20 | }
21 | this.map.addTileLayer(this.instance);
22 | }
23 |
24 | repaint = (config = {}) => {
25 | this.destroy();
26 | this.init(config);
27 | }
28 |
29 | destroy = () => {
30 | if (this.instance) {
31 | this.map.removeTileLayer(this.instance);
32 | }
33 | }
34 | }
35 |
36 | export default TileLayer;
37 |
--------------------------------------------------------------------------------
/src/core/Layer/TrafficLayer.js:
--------------------------------------------------------------------------------
1 | import BMapUtil from '../utils/map';
2 |
3 | class TrafficLayer {
4 | constructor(config, map) {
5 | this.map = map;
6 | this.init(config);
7 | }
8 |
9 | init(config = {}) {
10 | const now = new Date();
11 | if (!config.weekday) {
12 | config.weekday = now.getDay();
13 | }
14 |
15 | if (!config.hour) {
16 | config.hour = now.getHours();
17 | }
18 |
19 | this.instance = BMapUtil.BTrafficLayer({
20 | predictDate: {
21 | weekday: config.weekday,
22 | hour: config.hour,
23 | },
24 | });
25 |
26 | this.map.addTileLayer(this.instance);
27 | }
28 |
29 | repaint = (config = {}) => {
30 | this.destroy();
31 | this.init(config);
32 | }
33 |
34 | destroy = () => {
35 | if (this.instance) {
36 | this.map.removeTileLayer(this.instance);
37 | }
38 | }
39 | }
40 |
41 | export default TrafficLayer;
42 |
--------------------------------------------------------------------------------
/src/core/Library/CurveLine.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 |
3 | const getCurveLineOptions = config => ({
4 | strokeColor: config.strokeColor,
5 | strokeWeight: config.strokeWeight,
6 | strokeOpacity: config.strokeOpacity,
7 | strokeStyle: config.strokeStyle,
8 | });
9 |
10 | class CurveLine {
11 | constructor(config, map) {
12 | this.map = map;
13 | this.init(config);
14 | }
15 |
16 | init(config = {}) {
17 | const options = getCurveLineOptions(config);
18 | const points = this.processPoints(config.path);
19 | this.instance = new global.BMapLib.CurveLine(points, options);
20 | this.map.addOverlay(this.instance);
21 | this.processEditing(config.editing);
22 | }
23 |
24 | repaint = (config) => {
25 | if (this.instance) {
26 | this.instance.disableEditing();
27 | this.destroy();
28 | this.init(config);
29 | }
30 | }
31 |
32 | processPoints = points => points.map(point => Util.convert2BPoint(point))
33 |
34 | processEditing = (editing) => {
35 | if (editing) {
36 | this.instance.enableEditing();
37 | } else {
38 | this.instance.disableEditing();
39 | }
40 | }
41 |
42 | destroy = () => {
43 | if (this.instance) {
44 | this.map.removeOverlay(this.instance);
45 | }
46 | }
47 | }
48 |
49 | export default CurveLine;
50 |
--------------------------------------------------------------------------------
/src/core/Library/DistanceTool.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 |
3 | const getDistanceToolOptions = config => ({
4 | followText: config.followText || '单击确定地点,双击结束',
5 | unit: config.unit,
6 | lineColor: config.lineColor || 'red',
7 | lineStroke: config.lineStroke || 2,
8 | opacity: config.opacity,
9 | cursor: config.cursor,
10 | lineStyle: config.lineStyle,
11 | secIcon: config.secIcon,
12 | closeIcon: config.closeIcon,
13 | });
14 |
15 | class DistanceTool {
16 | constructor(config, map) {
17 | this.map = map;
18 | this.init(config);
19 | }
20 |
21 | init(config = {}) {
22 | const options = getDistanceToolOptions(config);
23 | this.instance = new global.BMapLib.DistanceTool(this.map, options);
24 | this.processEvents(config.events);
25 | }
26 |
27 | processEvents = (events) => {
28 | Util.unbindEvents(this.instance);
29 | Util.bindEvents(this.instance, events);
30 | }
31 |
32 | destroy = () => {
33 | if (this.instance) {
34 | this.instance.close();
35 | }
36 | }
37 | }
38 |
39 | export default DistanceTool;
40 |
--------------------------------------------------------------------------------
/src/core/Library/HeatMap.js:
--------------------------------------------------------------------------------
1 | const getHeatMapOptions = config => ({
2 | radius: config.radius,
3 | visible: config.visible,
4 | gradient: config.gradient,
5 | opacity: config.opacity,
6 | });
7 |
8 | class HeatMap {
9 | constructor(config, map) {
10 | this.map = map;
11 | this.init(config);
12 | }
13 |
14 | init(config = {}) {
15 | const options = getHeatMapOptions(config);
16 | this.instance = new global.BMapLib.HeatmapOverlay(options);
17 | this.map.addOverlay(this.instance);
18 | this.setData(config);
19 | }
20 |
21 | repaint = (config) => {
22 | if (this.instance) {
23 | const options = getHeatMapOptions(config);
24 | this.instance.setOptions(options);
25 | this.setData(config);
26 | }
27 | }
28 |
29 | setData = (config) => {
30 | if (config.data) {
31 | this.instance.setDataSet({
32 | max: config.max,
33 | data: config.data,
34 | });
35 | }
36 | }
37 |
38 | destroy = () => {
39 | if (this.instance) {
40 | this.map.removeOverlay(this.instance);
41 | }
42 | }
43 | }
44 |
45 | export default HeatMap;
46 |
--------------------------------------------------------------------------------
/src/core/Map/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * 百度地图核心类
3 | *
4 | */
5 |
6 | import Util from '../utils';
7 | import BMapUtil from '../utils/map';
8 |
9 | import OPTIONS from '../options/map';
10 |
11 | /**
12 | * 地图初始化配置项所需属性
13 | */
14 | const getMapOptions = config => ({
15 | minZoom: config.minZoom,
16 | maxZoom: config.maxZoom,
17 | mapType: config.mapType && global[config.mapType],
18 | enableHighResolution: config.highResolution,
19 | enableAutoResize: config.autoResize,
20 | enableMapClick: config.mapClick,
21 | });
22 |
23 | /**
24 | * 处理地图显示中心点
25 | */
26 | const processCenter = (center) => {
27 | if (!Util.isNil(center) && !Util.isString(center)) {
28 | center = Util.convert2BPoint(center, 'center');
29 | }
30 |
31 | return center;
32 | };
33 |
34 | class Map {
35 | config = {}
36 |
37 | instance = null
38 |
39 | requiredProperty = ['zoom', 'center']
40 |
41 | constructor(container, config) {
42 | const mapOptions = getMapOptions(config);
43 | this.instance = BMapUtil.BMap(container, mapOptions);
44 | this.config.center = processCenter(config.center);
45 | if (!config.zoom) {
46 | throw Error('Missing the required property `zoom`');
47 | }
48 | this.instance.centerAndZoom(this.config.center, config.zoom);
49 | }
50 |
51 | /**
52 | * 设置右键菜单
53 | */
54 | processContextMenu = (contextMenu) => {
55 | if (this.contextMenu) {
56 | this.instance.removeContextMenu(this.contextMenu);
57 | }
58 | this.contextMenu = contextMenu;
59 | if (contextMenu) {
60 | this.instance.addContextMenu(contextMenu);
61 | }
62 | }
63 |
64 | /**
65 | * 设置地图类型
66 | */
67 | setMapType = (mapType) => {
68 | if (mapType && global[mapType]) {
69 | this.instance.setMapType(global[mapType]);
70 | }
71 | }
72 |
73 | /**
74 | * 处理地图相关事件
75 | * 绑定之前先统一解绑
76 | */
77 | processEvents = (events) => {
78 | Util.unbindEvents(this.instance);
79 | Util.bindEvents(this.instance, events);
80 | }
81 |
82 | /**
83 | * 处理可以通过 setXXX 以及 enable、disableXXX 的方法
84 | */
85 | processOptions = (config) => {
86 | Util.processSetOptions(this.instance, OPTIONS.SET, config);
87 | Util.processBooleanOptions(this.instance, OPTIONS.BOOLEAN, config);
88 | }
89 |
90 | /**
91 | * 重绘
92 | */
93 | repaint = (config) => {
94 | // 先进行一步转换,因为this.config.center为转换后的值,防止diff出现 bad case
95 | if (config.center) {
96 | config.center = processCenter(config.center);
97 | }
98 | const diffConfig = Util.compareConfig(this.config, config);
99 |
100 | this.processContextMenu(diffConfig.contextMenu);
101 | this.setMapType(diffConfig.mapType);
102 | this.processOptions(diffConfig);
103 | this.config = {
104 | ...this.config,
105 | ...diffConfig,
106 | };
107 | this.processEvents(this.config.events);
108 | }
109 | }
110 |
111 | export default Map;
112 |
--------------------------------------------------------------------------------
/src/core/Overlay/BaseOverlay.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 |
3 | class BaseOverlay {
4 | config = {}
5 |
6 | outOfRangeOpts = []
7 |
8 | constructor(config, map) {
9 | this.map = map;
10 | this.config = { ...config };
11 | this.init(config);
12 | this.processEvents(config.events);
13 | }
14 |
15 | hasOutOfRangeOpts = (opts = []) => opts.some(item => this.outOfRangeOpts.indexOf(item) > -1)
16 |
17 | processEvents = (events) => {
18 | Util.unbindEvents(this.instance);
19 | Util.bindEvents(this.instance, events);
20 | }
21 |
22 | repaint = (config) => {
23 | const diffConfig = Util.compareConfig(this.config, config) || {};
24 |
25 | if (this.hasOutOfRangeOpts(Object.keys(diffConfig))) {
26 | this.destroy();
27 | this.init({ ...this.config, ...diffConfig });
28 | } else {
29 | this.processOptions(diffConfig);
30 | }
31 | this.config = { ...this.config, ...diffConfig };
32 | this.processEvents(this.config.events);
33 | }
34 |
35 | destroy = () => {
36 | this.map.removeOverlay(this.instance);
37 | }
38 | }
39 |
40 | export default BaseOverlay;
41 |
--------------------------------------------------------------------------------
/src/core/Overlay/Circle.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 | import OPTIONS from '../options/circle';
4 | import BaseOverlay from './BaseOverlay';
5 |
6 | const getCircleOptions = config => ({
7 | strokeColor: config.strokeColor,
8 | fillColor: config.fillColor,
9 | strokeWeight: config.strokeWeight,
10 | strokeOpacity: config.strokeOpacity,
11 | fillOpacity: config.fillOpacity,
12 | strokeStyle: config.strokeStyle,
13 | enableMassClear: config.massClear,
14 | enableClicking: config.clicking,
15 | });
16 |
17 | class Circle extends BaseOverlay {
18 | outOfRangeOpts = ['clicking']
19 |
20 | init(config = {}) {
21 | const options = getCircleOptions(config);
22 | const center = Util.convert2BPoint(config.center);
23 | this.instance = BMapUtil.BCircle(center, config.radius, options);
24 | this.map.addOverlay(this.instance);
25 | this.processOptions(config);
26 | }
27 |
28 | processOptions(config) {
29 | if (config.center) {
30 | config.center = Util.convert2BPoint(config.center);
31 | }
32 | Util.processSetOptions(this.instance, OPTIONS.SET, config);
33 | Util.processBooleanOptions(this.instance, OPTIONS.BOOLEAN, config);
34 | }
35 | }
36 |
37 | export default Circle;
38 |
--------------------------------------------------------------------------------
/src/core/Overlay/Custom.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 |
4 | class CustomOverlay {
5 | constructor(config, map) {
6 | this.config = { ...config };
7 | this.map = map;
8 | this.processOptions(config);
9 | }
10 |
11 | config = {}
12 |
13 | processOptions = ({ visible }) => {
14 | if (!Util.isNil(visible)) {
15 | if (!visible) {
16 | this.hide();
17 | } else {
18 | this.show();
19 | }
20 | }
21 | }
22 |
23 | repaint = (config) => {
24 | const diffConfig = Util.compareConfig(this.config, config);
25 | this.processOptions(diffConfig);
26 | this.config = { ...this.config, ...diffConfig };
27 | }
28 |
29 | destroy = () => {
30 | this.map.removeOverlay(this);
31 | }
32 | }
33 |
34 | // 异步加载时,BMap对象不存在,所以提供获得类方法,确保调用时BMap对象存在。
35 | const initCustomOverlay = (config, initialize, draw, mapInstance) => {
36 | CustomOverlay.prototype = BMapUtil.BOverlay();
37 | CustomOverlay.prototype.initialize = initialize;
38 | CustomOverlay.prototype.draw = draw;
39 |
40 | const overlay = new CustomOverlay(config, mapInstance);
41 | mapInstance.addOverlay(overlay);
42 |
43 | return overlay;
44 | };
45 |
46 | export default initCustomOverlay;
47 |
--------------------------------------------------------------------------------
/src/core/Overlay/GroundOverlay.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 | import OPTIONS from '../options/ground';
4 | import BaseOverlay from './BaseOverlay';
5 |
6 | const getGroundOverlayOptions = config => ({
7 | opacity: config.opacity,
8 | imageURL: config.imageURL,
9 | displayOnMaxLevel: config.displayOnMaxLevel,
10 | displayOnMinLevel: config.displayOnMinLevel,
11 | });
12 |
13 | class GroundOverlay extends BaseOverlay {
14 | init(config = {}) {
15 | const bounds = Util.convert2BBounds(config.bounds);
16 | const options = getGroundOverlayOptions(config);
17 | this.instance = BMapUtil.BGroundOverlay(bounds, options);
18 | this.map.addOverlay(this.instance);
19 | this.processOptions(config);
20 | }
21 |
22 | processOptions(config) {
23 | if (config.bounds) {
24 | config.bounds = Util.convert2BBounds(config.bounds);
25 | }
26 | Util.processSetOptions(this.instance, OPTIONS.SET, config);
27 | }
28 | }
29 |
30 | export default GroundOverlay;
31 |
--------------------------------------------------------------------------------
/src/core/Overlay/Icon.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 |
4 | const getIconOptions = config => ({
5 | anchor: config.anchor,
6 | imageOffset: config.imageOffset,
7 | imageSize: config.imageSize,
8 | infoWindowAnchor: config.infoWindowAnchor,
9 | printImageUrl: config.printImageUrl,
10 | });
11 |
12 | const processConfig = (config) => {
13 | const {
14 | size, imageOffset, imageSize, infoWindowAnchor,
15 | } = config;
16 | const result = { ...config };
17 |
18 | if (size) {
19 | result.size = Util.convert2BSize(size);
20 | }
21 |
22 | if (imageOffset) {
23 | result.imageOffset = Util.convert2BSize(imageOffset);
24 | }
25 |
26 | if (imageSize) {
27 | result.imageSize = Util.convert2BSize(imageSize);
28 | }
29 |
30 | if (infoWindowAnchor) {
31 | result.infoWindowAnchor = Util.convert2BSize(infoWindowAnchor);
32 | }
33 | return result;
34 | };
35 |
36 | class Icon {
37 | constructor(config = {}) {
38 | const result = processConfig(config);
39 | const options = getIconOptions(result);
40 | const icon = BMapUtil.BIcon(result.imageUrl, result.size, options);
41 | return icon;
42 | }
43 | }
44 |
45 | export default Icon;
46 |
--------------------------------------------------------------------------------
/src/core/Overlay/IconSequence.js:
--------------------------------------------------------------------------------
1 | import BMapUtil from '../utils/map';
2 |
3 | class IconSequence {
4 | constructor(config = {}) {
5 | const {
6 | symbol, offset, repeat, fixedRotation,
7 | } = config;
8 | const icon = BMapUtil.BIconSequence(symbol, offset, repeat, fixedRotation);
9 | return icon;
10 | }
11 | }
12 |
13 | export default IconSequence;
14 |
--------------------------------------------------------------------------------
/src/core/Overlay/InfoWindow.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 |
4 | import OPTIONS from '../options/infoWindow';
5 | import BaseOverlay from './BaseOverlay';
6 |
7 | const getInfoWindowOptions = config => ({
8 | width: config.width,
9 | height: config.height,
10 | maxWidth: config.maxWidth,
11 | offset: config.offset,
12 | title: config.title,
13 | enableAutoPan: config.autoPan,
14 | enableCloseOnClick: config.closeOnClick,
15 | enableMessage: config.displayMessage,
16 | message: config.message,
17 | });
18 |
19 | class InfoWindow extends BaseOverlay {
20 | outOfRangeOpts = ['maxWidth', 'offset', 'displayMessage', 'message', 'point']
21 |
22 | init(config = {}) {
23 | const options = getInfoWindowOptions(config);
24 | const point = Util.convert2BPoint(config.point);
25 | this.instance = BMapUtil.BInfoWindow(config.content, options);
26 | this.processVisible(config.visible, point);
27 | }
28 |
29 | processOptions(config) {
30 | const point = config.point || this.config.point;
31 | config.point = Util.convert2BPoint(point);
32 |
33 | Util.processSetOptions(this.instance, OPTIONS.SET, config);
34 | Util.processBooleanOptions(this.instance, OPTIONS.BOOLEAN, config);
35 | this.processVisible(config.visible, config.point);
36 | }
37 |
38 | processVisible(visible = true, point) {
39 | if (this.instance.isOpen() && !visible) {
40 | this.map.closeInfoWindow();
41 | } else if (!this.instance.isOpen() && visible) {
42 | this.map.openInfoWindow(this.instance, point);
43 | }
44 | }
45 | }
46 |
47 | export default InfoWindow;
48 |
--------------------------------------------------------------------------------
/src/core/Overlay/Label.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 | import OPTIONS from '../options/label';
4 | import BaseOverlay from './BaseOverlay';
5 |
6 | const getLabelOptions = config => ({
7 | offset: config.offset,
8 | position: config.position,
9 | enableMassClear: config.massClear,
10 | });
11 |
12 | class Label extends BaseOverlay {
13 | outOfRangeOpts = []
14 |
15 | init(config = {}) {
16 | if (config.position) {
17 | config.position = Util.convert2BPoint(config.position);
18 | }
19 | if (config.offset) {
20 | config.offset = Util.convert2BSize(config.offset);
21 | }
22 | const options = getLabelOptions(config);
23 | this.instance = BMapUtil.BLabel(config.content, options);
24 | this.map.addOverlay(this.instance);
25 | this.processOptions(config);
26 | }
27 |
28 | processOptions(config) {
29 | if (config.position) {
30 | config.position = Util.convert2BPoint(config.position);
31 | }
32 | Util.processSetOptions(this.instance, OPTIONS.SET, config);
33 | Util.processBooleanOptions(this.instance, OPTIONS.BOOLEAN, config);
34 | }
35 | }
36 |
37 | export default Label;
38 |
--------------------------------------------------------------------------------
/src/core/Overlay/Marker.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 | import OPTIONS from '../options/marker';
4 | import BaseOverlay from './BaseOverlay';
5 |
6 | const getMarkerOptions = config => ({
7 | offset: config.offset,
8 | icon: config.icon,
9 | enableMassClear: config.massClear,
10 | enableClicking: config.clicking,
11 | raiseOnDrag: config.raiseOnDrag,
12 | draggingCursor: config.draggingCursor,
13 | rotation: config.rotation,
14 | shadow: config.shadow,
15 | title: config.title,
16 | });
17 |
18 | class Marker extends BaseOverlay {
19 | outOfRangeOpts = ['clicking', 'raiseOnDrag', 'draggingCursor', 'shadow']
20 |
21 | init(config = {}) {
22 | const options = getMarkerOptions(config);
23 | const point = Util.convert2BPoint(config.point);
24 | this.instance = BMapUtil.BMarker(point, options);
25 | this.map.addOverlay(this.instance);
26 | this.processOptions(config);
27 | this.setContextMenu(config.contextMenu);
28 | }
29 |
30 | processOptions(config) {
31 | const { animation } = config;
32 | if (animation) {
33 | config.animation = global[animation] || animation;
34 | }
35 |
36 | if (config.point) {
37 | config.position = Util.convert2BPoint(config.point);
38 | } else {
39 | delete config.position;
40 | }
41 |
42 | Util.processSetOptions(this.instance, OPTIONS.SET, config);
43 | Util.processBooleanOptions(this.instance, OPTIONS.BOOLEAN, config);
44 |
45 | if (config.contextMenu) {
46 | this.setContextMenu(config.contextMenu);
47 | }
48 | }
49 |
50 | setContextMenu(contextMenu) {
51 | if (this.contextMenu) {
52 | this.instance.removeContextMenu(this.contextMenu);
53 | }
54 | this.contextMenu = contextMenu;
55 | if (contextMenu) {
56 | this.instance.addContextMenu(contextMenu);
57 | }
58 | }
59 | }
60 |
61 | export default Marker;
62 |
--------------------------------------------------------------------------------
/src/core/Overlay/PointCollection.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 |
4 | import BaseOverlay from './BaseOverlay';
5 |
6 | const getPointCollectionOptions = config => ({
7 | shape: config.shape ? global[config.shape] : null,
8 | size: config.size ? global[config.size] : null,
9 | color: config.color,
10 | });
11 |
12 | const processPoints = (points = []) => points.map(item => Util.convert2BPoint(item));
13 |
14 | class PointCollection extends BaseOverlay {
15 | init(config = {}) {
16 | const options = getPointCollectionOptions(config);
17 | const points = processPoints(config.path);
18 | this.instance = BMapUtil.BPointCollection(points, options);
19 | this.map.addOverlay(this.instance);
20 | }
21 |
22 | processOptions(config) {
23 | if (config.shape || config.size || config.color) {
24 | this.instance.setStyles({
25 | shape: config.shape ? global[config.shape] : global[this.config.shape],
26 | size: config.shape ? global[config.size] : global[this.config.size],
27 | color: config.color || this.config.color,
28 | });
29 | }
30 |
31 | if (config.path) {
32 | this.instance.setPoints(processPoints(config.path));
33 | }
34 | }
35 | }
36 |
37 | export default PointCollection;
38 |
--------------------------------------------------------------------------------
/src/core/Overlay/Polygon.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 | import OPTIONS from '../options/polygon';
4 | import BaseOverlay from './BaseOverlay';
5 |
6 | const getPolygonOptions = config => ({
7 | strokeColor: config.strokeColor,
8 | fillColor: config.fillColor,
9 | strokeWeight: config.strokeWeight,
10 | strokeOpacity: config.strokeOpacity,
11 | fillOpacity: config.fillOpacity,
12 | strokeStyle: config.strokeStyle,
13 | enableMassClear: config.massClear,
14 | enableClicking: config.clicking,
15 | });
16 |
17 | const processPoints = (points = []) => points.map(item => Util.convert2BPoint(item));
18 |
19 | class Polygon extends BaseOverlay {
20 | outOfRangeOpts = ['clicking']
21 |
22 | init(config = {}) {
23 | const options = getPolygonOptions(config);
24 | const points = processPoints(config.path);
25 | this.instance = BMapUtil.BPolygon(points, options);
26 | this.map.addOverlay(this.instance);
27 | this.processOptions(config);
28 | }
29 |
30 | processOptions(config) {
31 | if (config.path && Array.isArray(config.path)) {
32 | config.path = processPoints(config.path);
33 | }
34 |
35 | Util.processSetOptions(this.instance, OPTIONS.SET, config);
36 | Util.processBooleanOptions(this.instance, OPTIONS.BOOLEAN, config);
37 | }
38 | }
39 |
40 | export default Polygon;
41 |
--------------------------------------------------------------------------------
/src/core/Overlay/Polyline.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 | import OPTIONS from '../options/polyline';
4 | import BaseOverlay from './BaseOverlay';
5 |
6 | const getPolylineOptions = config => ({
7 | strokeColor: config.strokeColor,
8 | strokeWeight: config.strokeWeight,
9 | strokeOpacity: config.strokeOpacity,
10 | strokeStyle: config.strokeStyle,
11 | enableMassClear: config.massClear,
12 | enableClicking: config.clicking,
13 | icons: config.icons,
14 | });
15 |
16 | const processPoints = (points = []) => points.map(item => Util.convert2BPoint(item));
17 |
18 | class Polyline extends BaseOverlay {
19 | outOfRangeOpts = ['clicking']
20 |
21 | init(config = {}) {
22 | const options = getPolylineOptions(config);
23 | const points = processPoints(config.path);
24 | this.instance = BMapUtil.BPolyline(points, options);
25 | this.map.addOverlay(this.instance);
26 | this.processOptions(config);
27 | }
28 |
29 | processOptions(config) {
30 | if (config.path && Array.isArray(config.path)) {
31 | config.path = processPoints(config.path);
32 | }
33 |
34 | Util.processSetOptions(this.instance, OPTIONS.SET, config);
35 | Util.processBooleanOptions(this.instance, OPTIONS.BOOLEAN, config);
36 | }
37 | }
38 |
39 | export default Polyline;
40 |
--------------------------------------------------------------------------------
/src/core/Overlay/Symbol.js:
--------------------------------------------------------------------------------
1 | import Util from '../utils';
2 | import BMapUtil from '../utils/map';
3 |
4 | const getSymbolOptions = config => ({
5 | anchor: config.anchor && Util.convert2BSize(config.anchor),
6 | fillColor: config.fillColor,
7 | fillOpacity: config.fillOpacity,
8 | scale: config.scale,
9 | rotation: config.rotation,
10 | strokeColor: config.strokeColor,
11 | strokeOpacity: config.strokeOpacity,
12 | strokeWeight: config.strokeWeight,
13 | });
14 |
15 | const processPath = path => (global[path] ? global[path] : path);
16 |
17 | class Symbol {
18 | constructor(config = {}) {
19 | const options = getSymbolOptions(config);
20 | const path = processPath(config.path);
21 | return BMapUtil.BSymbol(path, options);
22 | }
23 | }
24 |
25 | export default Symbol;
26 |
--------------------------------------------------------------------------------
/src/core/constants/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 标注的动画效果
3 | */
4 | const ANIMATION = {
5 | DROP: 'BMAP_ANIMATION_DROP',
6 | BOUNCE: 'BMAP_ANIMATION_BOUNCE',
7 | };
8 |
9 | /**
10 | * 内置的右键菜单图标
11 | */
12 | const CONTEXT_MENU_ICON = {
13 | ZOOM_IN: 'BMAP_CONTEXT_MENU_ICON_ZOOMIN',
14 | ZOOM_OUT: 'BMAP_CONTEXT_MENU_ICON_ZOOMOUT',
15 | };
16 |
17 | /**
18 | * 控件的定位
19 | */
20 | const CONTROL_ANCHOR = {
21 | TOP_LEFT: 'BMAP_ANCHOR_TOP_LEFT',
22 | TOP_RIGHT: 'BMAP_ANCHOR_TOP_RIGHT',
23 | BOTTOM_LEFT: 'BMAP_ANCHOR_BOTTOM_LEFT',
24 | BOTTOM_RIGHT: 'BMAP_ANCHOR_BOTTOM_RIGHT',
25 | };
26 |
27 | /**
28 | * 长度单位制
29 | */
30 | const LENGTH_UNIT = {
31 | METRIC: 'BMAP_UNIT_METRIC',
32 | IMPERIAL: 'BMAP_UNIT_IMPERIAL',
33 | };
34 |
35 | /**
36 | * 地图上所有覆盖物的容器集合
37 | */
38 | const MAP_PANES = {
39 | FLOAT: 'floatPane', // 信息窗口所在容器
40 | FLOAT_SHADOW: 'floatShadow', // 信息窗口阴影所在容器
41 | LABEL: 'labelPane', // 文本标注所在容器
42 | MARKER: 'markerPane', // 标注图标所在容器
43 | MARKER_MOUSE: 'markerMouseTarget', // 标注点击区域所在容器
44 | MARKER_SHADOW: 'markerShadow', // 标注阴影所在容器
45 | MAP: 'mapPane', // 折现、多边形等矢量图形所在容器
46 | };
47 |
48 | /**
49 | * 地图类型
50 | */
51 | const MAP_TYPE = {
52 | NORMAL: 'BMAP_NORMAL_MAP',
53 | PERSPECTIVE: 'BMAP_PERSPECTIVE_MAP',
54 | SATELLITE: 'BMAP_SATELLITE_MAP',
55 | HYBRID: 'BMAP_HYBRID_MAP',
56 | };
57 |
58 | /**
59 | * MapTypeControl的外观样式
60 | */
61 | const MAP_TYPE_CONTROL_TYPE = {
62 | HORIZONTAL: 'BMAP_MAPTYPE_CONTROL_HORIZONTAL',
63 | DROPDOWN: 'BMAP_MAPTYPE_CONTROL_DROPDOWN',
64 | MAP: 'BMAP_MAPTYPE_CONTROL_MAP',
65 | };
66 |
67 | /**
68 | * 平移缩放控件的类型
69 | */
70 | const NAVIGATION_CONTROL_TYPE = {
71 | LARGE: 'BMAP_NAVIGATION_CONTROL_LARGE',
72 | SMALL: 'BMAP_NAVIGATION_CONTROL_SMALL',
73 | PAN: 'BMAP_NAVIGATION_CONTROL_PAN',
74 | ZOOM: 'BMAP_NAVIGATION_CONTROL_ZOOM',
75 | };
76 |
77 | /**
78 | * 海量点预设的不同形状
79 | */
80 | const SHAPE_TYPE = {
81 | CIRCLE: 'BMAP_POINT_SHAPE_CIRCLE',
82 | STAR: 'BMAP_POINT_SHAPE_STAR',
83 | SQUARE: 'BMAP_POINT_SHAPE_SQUARE',
84 | RHOMBUS: 'BMAP_POINT_SHAPE_RHOMBUS',
85 | WATERDROP: 'BMAP_POINT_SHAPE_WATERDROP',
86 | };
87 |
88 | /**
89 | * 海量点预设的不同尺寸
90 | */
91 | const SIZE_TYPE = {
92 | TINY: 'BMAP_POINT_SIZE_TINY',
93 | SMALLER: 'BMAP_POINT_SIZE_SMALLER',
94 | SMALL: 'BMAP_POINT_SIZE_SMALL',
95 | NORMAL: 'BMAP_POINT_SIZE_NORMAL',
96 | BIG: 'BMAP_POINT_SIZE_BIG',
97 | BIGGER: 'BMAP_POINT_SIZE_BIGGER',
98 | HUGE: 'BMAP_POINT_SIZE_HUGE',
99 | };
100 |
101 | /**
102 | * 矢量图标类预设的图标样式
103 | */
104 | const SYMBOL_SHAPE_TYPE = {
105 | CIRCLE: 'BMap_Symbol_SHAPE_CIRCLE',
106 | RECTANGLE: 'BMap_Symbol_SHAPE_RECTANGLE',
107 | RHOMBUS: 'BMap_Symbol_SHAPE_RHOMBUS',
108 | STAR: 'BMap_Symbol_SHAPE_STAR',
109 | BACKWARD_CLOSED_ARROW: 'BMap_Symbol_SHAPE_BACKWARD_CLOSED_ARROW',
110 | FORWARD_CLOSED_ARROW: 'BMap_Symbol_SHAPE_FORWARD_CLOSED_ARROW',
111 | BACKWARD_OPEN_ARROW: 'BMap_Symbol_SHAPE_BACKWARD_OPEN_ARROW',
112 | FORWARD_OPEN_ARROW: 'BMap_Symbol_SHAPE_FORWARD_OPEN_ARROW',
113 | POINT: 'BMap_Symbol_SHAPE_POINT',
114 | PLANE: 'BMap_Symbol_SHAPE_PLANE',
115 | CAMERA: 'BMap_Symbol_SHAPE_CAMERA',
116 | WARNING: 'BMap_Symbol_SHAPE_WARNING',
117 | SMILE: 'BMap_Symbol_SHAPE_SMILE',
118 | CLOCK: 'BMap_Symbol_SHAPE_CLOCK',
119 | };
120 |
121 | /**
122 | * 驾车方案的策略配置
123 | */
124 | const DRIVING_POLICY = {
125 | DEFAULT: 'BMAP_DRIVING_POLICY_DEFAULT',
126 | FIRST_HIGHWAYS: 'BMAP_DRIVING_POLICY_FIRST_HIGHWAYS',
127 | AVOID_HIGHWAYS: 'BMAP_DRIVING_POLICY_AVOID_HIGHWAYS',
128 | AVOID_CONGESTION: 'BMAP_DRIVING_POLICY_AVOID_CONGESTION',
129 | };
130 |
131 | /**
132 | * 跨城公交换乘策略
133 | */
134 | const INTERCITY_POLICY = {
135 | LEAST_TIME: 'BMAP_INTERCITY_POLICY_LEAST_TIME',
136 | EARLY_START: 'BMAP_INTERCITY_POLICY_EARLY_START',
137 | CHEAP_PRICE: 'BMAP_INTERCITY_POLICY_CHEAP_PRICE',
138 | };
139 |
140 | /**
141 | * 市内公交方案换乘策略
142 | */
143 | const TRANSIT_POLICY = {
144 | RECOMMEND: 'BMAP_TRANSIT_POLICY_RECOMMEND',
145 | LEAST_TIME: 'BMAP_TRANSIT_POLICY_LEAST_TIME',
146 | LEAST_TRANSFER: 'BMAP_TRANSIT_POLICY_LEAST_TRANSFER',
147 | LEAST_WALKING: 'BMAP_TRANSIT_POLICY_LEAST_WALKING',
148 | AVOID_SUBWAYS: 'BMAP_TRANSIT_POLICY_AVOID_SUBWAYS',
149 | FIRST_SUBWAYS: 'BMAP_TRANSIT_POLICY_FIRST_SUBWAYS',
150 | };
151 |
152 | /**
153 | * 跨城交通方式策略
154 | */
155 | const TRANSIT_TYPE_POLICY = {
156 | TRAIN: 'BMAP_TRANSIT_TYPE_POLICY_TRAIN',
157 | AIRPLANE: 'BMAP_TRANSIT_TYPE_POLICY_AIRPLANE',
158 | COACH: 'BMAP_TRANSIT_TYPE_POLICY_COACH',
159 | };
160 |
161 | export default {
162 | ANIMATION,
163 | CONTEXT_MENU_ICON,
164 | CONTROL_ANCHOR,
165 | LENGTH_UNIT,
166 | MAP_PANES,
167 | MAP_TYPE,
168 | MAP_TYPE_CONTROL_TYPE,
169 | NAVIGATION_CONTROL_TYPE,
170 | SHAPE_TYPE,
171 | SIZE_TYPE,
172 | SYMBOL_SHAPE_TYPE,
173 | DRIVING_POLICY,
174 | INTERCITY_POLICY,
175 | TRANSIT_POLICY,
176 | TRANSIT_TYPE_POLICY,
177 | };
178 |
--------------------------------------------------------------------------------
/src/core/index.js:
--------------------------------------------------------------------------------
1 | import Map from './Map';
2 | import BMapUtil from './utils/map';
3 | import Util from './utils';
4 | import initCustomControl from './Control/Custom';
5 | import CityList from './Control/CityList';
6 | import Copyright from './Control/Copyright';
7 | import Navigation from './Control/Navigation';
8 | import MapType from './Control/MapType';
9 | import Scale from './Control/Scale';
10 | import Panorama from './Control/Panorama';
11 | import OverviewMap from './Control/OverviewMap';
12 | import Geolocation from './Control/Geolocation';
13 | import initCustomOverlay from './Overlay/Custom';
14 | import Marker from './Overlay/Marker';
15 | import InfoWindow from './Overlay/InfoWindow';
16 | import Circle from './Overlay/Circle';
17 | import Polygon from './Overlay/Polygon';
18 | import Polyline from './Overlay/Polyline';
19 | import Label from './Overlay/Label';
20 | import GroundOverlay from './Overlay/GroundOverlay';
21 | import PointCollection from './Overlay/PointCollection';
22 | import Icon from './Overlay/Icon';
23 | import IconSequence from './Overlay/IconSequence';
24 | import Symbol from './Overlay/Symbol';
25 | import AutoComplete from './AutoComplete';
26 | import Constants from './constants';
27 | import TileLayer from './Layer/TileLayer';
28 | import TrafficLayer from './Layer/TrafficLayer';
29 | import DistanceTool from './Library/DistanceTool';
30 | import HeatMap from './Library/HeatMap';
31 | import CurveLine from './Library/CurveLine';
32 |
33 | export {
34 | BMapUtil,
35 | Util,
36 | initCustomControl,
37 | CityList,
38 | Copyright,
39 | Navigation,
40 | MapType,
41 | Scale,
42 | Panorama,
43 | OverviewMap,
44 | Geolocation,
45 | initCustomOverlay,
46 | Marker,
47 | Circle,
48 | Polygon,
49 | Label,
50 | InfoWindow,
51 | Polyline,
52 | Constants,
53 | AutoComplete,
54 | GroundOverlay,
55 | PointCollection,
56 | Icon,
57 | IconSequence,
58 | Symbol,
59 | TileLayer,
60 | TrafficLayer,
61 | DistanceTool,
62 | HeatMap,
63 | CurveLine,
64 | };
65 |
66 | const addBMapScript = (ak, version = 3) => {
67 | if (!global.BMap && !global.mapLoader) {
68 | global.mapLoader = new Promise((resolve) => {
69 | const script = document.createElement('script');
70 | script.src = `https://api.map.baidu.com/api?v=${version}.0&ak=${ak}&callback=initBMapCallBack`;
71 | document.head.appendChild(script);
72 | global.initBMapCallBack = () => {
73 | resolve(global.BMap);
74 | document.head.removeChild(script);
75 | delete global.mapLoader;
76 | delete global.initBMapCallBack;
77 | };
78 | });
79 | }
80 | return global.mapLoader;
81 | };
82 |
83 | const initMap = async (container, config) => {
84 | await addBMapScript(config.ak, config.version);
85 | return new Map(container, config);
86 | };
87 |
88 | export default initMap;
89 |
--------------------------------------------------------------------------------
/src/core/options/autoComplete.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'types',
4 | 'location',
5 | 'inputValue',
6 | ],
7 | };
8 |
--------------------------------------------------------------------------------
/src/core/options/circle.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'center',
4 | 'radius',
5 | 'strokeColor',
6 | 'fillColor',
7 | 'strokeOpacity',
8 | 'fillOpacity',
9 | 'strokeWeight',
10 | 'strokeStyle',
11 | ],
12 | BOOLEAN: [
13 | 'editing',
14 | 'massClear',
15 | ],
16 | };
17 |
--------------------------------------------------------------------------------
/src/core/options/ground.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'bounds',
4 | 'opacity',
5 | 'imageURL',
6 | 'displayOnMinLevel',
7 | 'displayOnMaxLevel',
8 | ],
9 | };
10 |
--------------------------------------------------------------------------------
/src/core/options/infoWindow.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'width',
4 | 'height',
5 | 'title',
6 | 'content',
7 | 'maxContent',
8 | ],
9 | BOOLEAN: [
10 | 'autoPan',
11 | 'closeOnClick',
12 | ],
13 | };
14 |
--------------------------------------------------------------------------------
/src/core/options/label.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'style',
4 | 'content',
5 | 'position',
6 | 'offset',
7 | 'title',
8 | 'zIndex',
9 | ],
10 | BOOLEAN: [
11 | 'massClear',
12 | ],
13 | };
14 |
--------------------------------------------------------------------------------
/src/core/options/map.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'center',
4 | 'minZoom',
5 | 'maxZoom',
6 | 'defaultCursor',
7 | 'draggingCursor',
8 | 'mapStyle',
9 | 'mapStyleV2',
10 | 'zoom',
11 | ],
12 | BOOLEAN: [
13 | 'dragging',
14 | 'scrollWheelZoom',
15 | 'doubleClickZoom',
16 | 'keyboard',
17 | 'inertialDragging',
18 | 'continuousZoom',
19 | 'pinchToZoom',
20 | 'autoResize',
21 | ],
22 | };
23 |
--------------------------------------------------------------------------------
/src/core/options/marker.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'icon',
4 | 'position',
5 | 'offset',
6 | 'label',
7 | 'title',
8 | 'zIndex',
9 | 'animation',
10 | 'rotation',
11 | ],
12 | BOOLEAN: [
13 | 'massClear',
14 | 'dragging',
15 | ],
16 | };
17 |
--------------------------------------------------------------------------------
/src/core/options/polygon.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'path',
4 | 'strokeColor',
5 | 'fillColor',
6 | 'strokeOpacity',
7 | 'fillOpacity',
8 | 'strokeWeight',
9 | 'strokeStyle',
10 | ],
11 | BOOLEAN: [
12 | 'editing',
13 | 'massClear',
14 | ],
15 | };
16 |
--------------------------------------------------------------------------------
/src/core/options/polyline.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'path',
4 | 'strokeColor',
5 | 'strokeOpacity',
6 | 'strokeWeight',
7 | 'strokeStyle',
8 | ],
9 | BOOLEAN: [
10 | 'editing',
11 | 'massClear',
12 | ],
13 | };
14 |
--------------------------------------------------------------------------------
/src/core/options/symbol.js:
--------------------------------------------------------------------------------
1 | export default {
2 | SET: [
3 | 'path',
4 | 'anchor',
5 | 'rotation',
6 | 'scale',
7 | 'strokeWeight',
8 | 'strokeColor',
9 | 'strokeOpacity',
10 | 'fillColor',
11 | 'fillOpacity',
12 | ],
13 | };
14 |
--------------------------------------------------------------------------------
/src/core/utils/index.js:
--------------------------------------------------------------------------------
1 | import isEqual from 'lodash.isequal';
2 | import BMapUtil from './map';
3 |
4 | const numberRe = /^[0-9]+.?[0-9]*/;
5 |
6 | /**
7 | * 是否为Point
8 | * @param {*} point
9 | */
10 | const isPoint = point => numberRe.test(point.lng) && typeof numberRe.test(point.lat);
11 |
12 | /**
13 | * 是否为BMap.Point
14 | * @param {*} point
15 | */
16 | const isBPoint = point => isPoint(point) && point.equals;
17 |
18 | /**
19 | * 是否为Size
20 | * @param {*} point
21 | */
22 | const isSize = size => numberRe.test(size.width) && typeof numberRe.test(size.height);
23 |
24 | /**
25 | * 是否为BMap.Size
26 | * @param {*} size
27 | */
28 | const isBSize = size => isSize(size) && size.equals;
29 |
30 | /**
31 | * 是否为矩形范围
32 | * @param {*} bounds
33 | */
34 | const isBounds = bounds => numberRe.test(bounds.sw) && numberRe.test(bounds.ne);
35 |
36 | /**
37 | * 是否为BMap.Bounds
38 | * @param {*} bounds
39 | */
40 | const isBBounds = bounds => isBounds(bounds) && bounds.equals;
41 |
42 | /**
43 | * 是否为空
44 | * @param {*} obj
45 | */
46 | const isNil = obj => obj === undefined || obj === null;
47 |
48 | /**
49 | * 是否为字符串
50 | * @param {*} str
51 | */
52 | const isString = str => typeof str === 'string';
53 |
54 | /**
55 | * 首字母转为大写
56 | * @param {*} str
57 | */
58 | const firstUpperCase = str => str.replace(/^\S/, s => s.toUpperCase());
59 |
60 | /**
61 | * 首字母转为小写
62 | * @param {*} str
63 | */
64 | const firstLowerCase = str => str.replace(/^\S/, s => s.toLowerCase());
65 |
66 | /**
67 | * 获取行政区包含点集合
68 | * @param {*} name 行政区名称
69 | */
70 | const getBoundary = name => new Promise((resolve, reject) => {
71 | const boundary = new global.BMap.Boundary();
72 |
73 | boundary.get(name, (res) => {
74 | const count = res.boundaries.length;
75 | if (count === 0) {
76 | reject();
77 | }
78 | const area = [];
79 | let allPoints = [];
80 | for (let i = 0; i < count; i += 1) {
81 | const arr = res.boundaries[i].split(';').map((item) => {
82 | const pointArr = item.split(',');
83 | return BMapUtil.BPoint({ lng: pointArr[0], lat: pointArr[1].trim() });
84 | });
85 | allPoints = allPoints.concat(arr);
86 | area.push(arr);
87 | }
88 |
89 | resolve({
90 | area,
91 | points: allPoints,
92 | });
93 | });
94 | });
95 |
96 | /**
97 | * 将传入值转换为 BMap.Point
98 | * @param {*} point 点对象 { lng, lat }
99 | * @param {*} propsName 用于错误提示
100 | */
101 | const convert2BPoint = (point, propsName = 'point') => {
102 | if (isNil(point)) {
103 | throw Error(`Missing property \`${propsName}\``);
104 | }
105 | if (!isPoint(point)) {
106 | throw Error(`The \`${propsName}\` property should be a literal value \`{ lng, lat }\``);
107 | } else if (!isBPoint(point)) {
108 | point = BMapUtil.BPoint({ ...point });
109 | }
110 | return point;
111 | };
112 |
113 | /**
114 | * 将传入值转换为 BMap.Size
115 | * @param {*} point 矩形尺寸 { width, height }
116 | * @param {*} propsName 用于错误提示
117 | */
118 | const convert2BSize = (size, propsName = 'size') => {
119 | if (isNil(size)) {
120 | throw Error(`Missing property \`${propsName}\``);
121 | }
122 | if (!isSize(size)) {
123 | throw Error(`The \`${propsName}\` property should be a literal value \`{ width, height }\``);
124 | }
125 | if (!isBSize(size)) {
126 | size = BMapUtil.BSize({ ...size });
127 | }
128 | return size;
129 | };
130 |
131 | /**
132 | * 将值转换为 BMap.Bounds
133 | * @param {*} point 矩形区域 { sw, ne }
134 | * @param {*} propsName 用于错误提示
135 | */
136 | const convert2BBounds = (bounds, propsName = 'bounds') => {
137 | if (isNil(bounds)) {
138 | throw Error(`Missing property \`${propsName}\``);
139 | }
140 | if (!isBounds(bounds)) {
141 | throw Error(`The \`${propsName}\` property should be a literal value \`{ width, height }\``);
142 | }
143 | if (!isBBounds(bounds)) {
144 | bounds = BMapUtil.BBounds({ ...bounds });
145 | }
146 | return bounds;
147 | };
148 |
149 | /**
150 | * 为目标对象绑定事件
151 | * @param {*} target 目标对象
152 | * @param {*} events 事件集合
153 | */
154 | const bindEvents = (target, events = {}) => {
155 | Object.keys(events).forEach((eventName) => {
156 | const eventType = typeof events[eventName];
157 | if (eventType !== 'function') {
158 | console.warn(`Events's props value should be a function, but got '${eventType}'`);
159 | }
160 | const callback = (...args) => {
161 | if (eventType === 'function') {
162 | events[eventName].call(null, ...args);
163 | }
164 | };
165 | target.events = target.events || {};
166 | target.addEventListener(eventName, callback);
167 | target.events[`${eventName}`] = callback;
168 | });
169 | };
170 |
171 | /**
172 | * 将目标对象中已绑定事件移除
173 | * @param {*} target
174 | */
175 | const unbindEvents = (target) => {
176 | const { events = {} } = target;
177 | Object.keys(events).forEach((eventName) => {
178 | const event = events[eventName];
179 | target.removeEventListener(eventName, event);
180 | });
181 | target.events = {};
182 | };
183 |
184 | /**
185 | * 处理 target.setXXX 方法
186 | * @param {*} target 目标对象
187 | * @param {*} options 属性集合
188 | * @param {*} values 值集合
189 | */
190 | const processSetOptions = (target, options, values) => {
191 | options.forEach((key) => {
192 | if (values[key] || typeof values[key] === 'boolean') {
193 | const upKey = firstUpperCase(key);
194 | if (target[`set${upKey}`]) {
195 | target[`set${upKey}`](values[key]);
196 | }
197 | }
198 | });
199 | };
200 |
201 | /**
202 | * 处理 target.enableXXX 、 target.disableXXX 方法
203 | * @param {*} target 目标对象
204 | * @param {*} options 属性集合
205 | * @param {*} values 值集合
206 | */
207 | const processBooleanOptions = (target, options, values) => {
208 | options.forEach((key) => {
209 | if (values[key] || typeof values[key] === 'boolean') {
210 | const upKey = firstUpperCase(key);
211 | const prefix = values[key] ? 'enable' : 'disable';
212 | if (target[`${prefix}${upKey}`]) {
213 | target[`${prefix}${upKey}`]();
214 | }
215 | }
216 | });
217 | };
218 |
219 | /**
220 | * 比较新旧config,返回差异集合
221 | * @param {*} oldConfig
222 | * @param {*} newConfig
223 | */
224 | const compareConfig = (oldConfig, newConfig) => {
225 | const result = { ...oldConfig, ...newConfig };
226 | const keys = Object.keys(result);
227 | for (let i = 0, len = keys.length; i < len; i += 1) {
228 | const key = keys[i];
229 | if (!isNil(oldConfig[key]) && isEqual(oldConfig[key], result[key])) {
230 | delete result[key];
231 | }
232 | }
233 | return result;
234 | };
235 |
236 | /**
237 | * 转换Control配置项
238 | * @param {*} param0
239 | */
240 | const convertControlOptions = ({ anchor, offset }) => {
241 | const result = {};
242 |
243 | if (anchor) {
244 | result.anchor = !isNil(global[anchor]) ? global[anchor] : anchor;
245 | }
246 |
247 | if (offset) {
248 | result.offset = convert2BSize(offset, 'offset');
249 | }
250 | return result;
251 | };
252 |
253 | /**
254 | * 处理Control显示隐藏
255 | * @param {*} target
256 | * @param {*} visible
257 | */
258 | const processControlVisible = (target, visible) => {
259 | if (!isNil(target) && !isNil(visible)) {
260 | return visible ? target.show() : target.hide();
261 | }
262 | return null;
263 | };
264 |
265 | const libScriptsMap = {};
266 | /**
267 | * 同步请求第三方script
268 | * @param {*} src script链接
269 | *
270 | * 此处保证每个script在整个文档流中有且只有一个,不重复添加
271 | */
272 | const syncScript = (src) => {
273 | let scriptLoader = libScriptsMap[src];
274 | if (!scriptLoader) {
275 | // eslint-disable-next-line no-multi-assign
276 | libScriptsMap[src] = scriptLoader = new Promise((resolved) => {
277 | const script = document.createElement('script');
278 | script.src = src;
279 | // eslint-disable-next-line no-multi-assign
280 | script.onload = script.onreadystatechange = function loaded() {
281 | // for IE
282 | if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
283 | resolved();
284 | }
285 | };
286 | document.head.appendChild(script);
287 | });
288 | }
289 |
290 | return scriptLoader;
291 | };
292 |
293 | export default {
294 | syncScript,
295 | isPoint,
296 | isBPoint,
297 | isSize,
298 | isBSize,
299 | isBounds,
300 | isBBounds,
301 | isNil,
302 | isString,
303 | getBoundary,
304 | convert2BPoint,
305 | convert2BSize,
306 | convert2BBounds,
307 | bindEvents,
308 | unbindEvents,
309 | processSetOptions,
310 | processBooleanOptions,
311 | compareConfig,
312 | firstLowerCase,
313 | convertControlOptions,
314 | processControlVisible,
315 | };
316 |
--------------------------------------------------------------------------------
/src/core/utils/map.js:
--------------------------------------------------------------------------------
1 | const BMapUtil = {
2 | BMap(container, opts) {
3 | return new global.BMap.Map(container, opts);
4 | },
5 | BPoint({ lng, lat }) {
6 | return new global.BMap.Point(lng, lat);
7 | },
8 | BSize({ width, height }) {
9 | return new global.BMap.Size(Number(width), Number(height));
10 | },
11 | BPixel({ x, y }) {
12 | return new global.BMap.Pixel(x, y);
13 | },
14 | BBounds({ sw, ne }) {
15 | const swPoint = BMapUtil.BPoint(sw);
16 | const nePoint = BMapUtil.BPoint(ne);
17 |
18 | return new global.BMap.Bounds(swPoint, nePoint);
19 | },
20 | BMenuItem(text, callback, opts) {
21 | return new global.BMap.MenuItem(text, callback, opts);
22 | },
23 | BContextMenu(subMenus = []) {
24 | const contextMenu = new global.BMap.ContextMenu();
25 | subMenus.forEach((item) => {
26 | contextMenu.addItem(item);
27 | if (item.separator) {
28 | contextMenu.addSeparator();
29 | }
30 | });
31 | return contextMenu;
32 | },
33 | BIcon(url, size, opts) {
34 | return new global.BMap.Icon(url, size, opts);
35 | },
36 | BIconSequence(symbol, offset, repeat, fixedRotation) {
37 | return new global.BMap.IconSequence(symbol, offset, repeat, fixedRotation);
38 | },
39 | BControl() {
40 | return new global.BMap.Control();
41 | },
42 | BCityListControl(opts) {
43 | return new global.BMap.CityListControl(opts);
44 | },
45 | BCopyrightControl(opts) {
46 | return new global.BMap.CopyrightControl(opts);
47 | },
48 | BNavigationControl(opts) {
49 | return new global.BMap.NavigationControl(opts);
50 | },
51 | BMapTypeControl(opts) {
52 | return new global.BMap.MapTypeControl(opts);
53 | },
54 | BScaleControl(opts) {
55 | return new global.BMap.ScaleControl(opts);
56 | },
57 | BPanoramaControl(opts) {
58 | return new global.BMap.PanoramaControl(opts);
59 | },
60 | BOverviewMapControl(opts) {
61 | return new global.BMap.OverviewMapControl(opts);
62 | },
63 | BGeolocationControl(opts) {
64 | return new global.BMap.GeolocationControl(opts);
65 | },
66 | BOverlay() {
67 | return new global.BMap.Overlay();
68 | },
69 | BMarker(point, opts) {
70 | return new global.BMap.Marker(point, opts);
71 | },
72 | BLabel(content, opts) {
73 | return new global.BMap.Label(content, opts);
74 | },
75 | BCircle(center, radius, opts) {
76 | return new global.BMap.Circle(center, radius, opts);
77 | },
78 | BPolyline(points, opts) {
79 | return new global.BMap.Polyline(points, opts);
80 | },
81 | BInfoWindow(content, opts) {
82 | return new global.BMap.InfoWindow(content, opts);
83 | },
84 | BPolygon(points, opts) {
85 | return new global.BMap.Polygon(points, opts);
86 | },
87 | BGroundOverlay(bounds, opts) {
88 | return new global.BMap.GroundOverlay(bounds, opts);
89 | },
90 | BPointCollection(points, opts) {
91 | return new global.BMap.PointCollection(points, opts);
92 | },
93 | BAutocomplete(opts) {
94 | return new global.BMap.Autocomplete(opts);
95 | },
96 | BSymbol(path, opts) {
97 | return new global.BMap.Symbol(path, opts);
98 | },
99 | BTileLayer(opts) {
100 | return new global.BMap.TileLayer(opts);
101 | },
102 | BTrafficLayer(opts) {
103 | return new global.BMap.TrafficLayer(opts);
104 | },
105 | BLocalSearch(location, opts) {
106 | return new global.BMap.LocalSearch(location, opts);
107 | },
108 | BGeolocation() {
109 | return new global.BMap.Geolocation();
110 | },
111 | BConvertor() {
112 | return new global.BMap.Convertor();
113 | },
114 | BTransitRoute(location, opts) {
115 | return new global.BMap.TransitRoute(location, opts);
116 | },
117 | BWalkingRoute(location, opts) {
118 | return new global.BMap.WalkingRoute(location, opts);
119 | },
120 | BRidingRoute(location, opts) {
121 | return new global.BMap.RidingRoute(location, opts);
122 | },
123 | BDrivingRoute(location, opts) {
124 | return new global.BMap.DrivingRoute(location, opts);
125 | },
126 | /**
127 | * 根据关键字查询位置信息
128 | * @param {*} keyword 关键字
129 | * @param {*} location 定位信息[map实例/string/point]
130 | */
131 | search(keyword, location) {
132 | return new Promise((resolve) => {
133 | const local = BMapUtil.BLocalSearch(location, {
134 | onSearchComplete(result) {
135 | const list = [];
136 | for (let i = 0, len = result.getCurrentNumPois(); i < len - 1; i += 1) {
137 | list.push(result.getPoi(i));
138 | }
139 | resolve(result);
140 | },
141 | });
142 | local.search(keyword);
143 | });
144 | },
145 |
146 | /**
147 | * 获取当前位置信息
148 | */
149 | getCurrentPosition() {
150 | return new Promise((resolve, reject) => {
151 | const geo = BMapUtil.BGeolocation();
152 | geo.getCurrentPosition((result) => {
153 | const status = geo.getStatus();
154 | if (status === global.BMAP_STATUS_SUCCESS) {
155 | resolve(result);
156 | } else {
157 | reject(status);
158 | }
159 | });
160 | });
161 | },
162 |
163 | /**
164 | * 对指定的地址进行解析,返回坐标点
165 | * @param {*} address
166 | * @param {*} city
167 | */
168 | getPoint(address, city) {
169 | return new Promise((resolve, reject) => {
170 | const geo = new global.BMap.Geocoder();
171 | geo.getPoint(address, (point) => {
172 | if (point) {
173 | resolve(point);
174 | } else {
175 | reject();
176 | }
177 | }, city);
178 | });
179 | },
180 |
181 | /**
182 | * 对指定坐标点解析,返回地址信息
183 | * @param {*} point
184 | */
185 | getLocation(point) {
186 | return new Promise((resolve, reject) => {
187 | const geo = new global.BMap.Geocoder();
188 | // change the point to bpoint
189 | if (point.lng && point.lat) {
190 | point = BMapUtil.BPoint(point);
191 | }
192 | geo.getLocation(point, (result) => {
193 | if (result) {
194 | resolve(result);
195 | } else {
196 | reject();
197 | }
198 | });
199 | });
200 | },
201 | };
202 |
203 | export default BMapUtil;
204 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 基础类
3 | */
4 | export { default as Base } from './components/Base';
5 |
6 | /**
7 | * 基础组件
8 | */
9 | export { default as Map } from './components/Map';
10 | export { default as CustomControl } from './components/Control/Custom';
11 | export { default as CustomOverlay } from './components/Overlay/Custom';
12 | export { default as AutoComplete } from './components/AutoComplete';
13 |
14 | /**
15 | * 常用控件
16 | */
17 | export { default as Navigation } from './components/Control/Navigation';
18 | export { default as OverviewMap } from './components/Control/OverviewMap';
19 | export { default as Scale } from './components/Control/Scale';
20 | export { default as MapType } from './components/Control/MapType';
21 | export { default as CopyrightControl } from './components/Control/CopyrightControl';
22 | export { default as Geolocation } from './components/Control/Geolocation';
23 | export { default as Panorama } from './components/Control/Panorama';
24 | export { default as CityList } from './components/Control/CityList';
25 |
26 | /**
27 | * 常用覆盖物
28 | */
29 | export { default as Marker } from './components/Overlay/Marker';
30 | export { default as Label } from './components/Overlay/Label';
31 | export { default as Polyline } from './components/Overlay/Polyline';
32 | export { default as Polygon } from './components/Overlay/Polygon';
33 | export { default as Circle } from './components/Overlay/Circle';
34 | export { default as InfoWindow } from './components/Overlay/InfoWindow';
35 | export { default as Ground } from './components/Overlay/Ground';
36 | export { default as PointCollection } from './components/Overlay/PointCollection';
37 | export { default as Boundary } from './components/Overlay/Boundary';
38 |
39 | /**
40 | * 地图图层
41 | */
42 | export { default as TileLayer } from './components/Layer/TileLayer';
43 | export { default as TrafficLayer } from './components/Layer/TrafficLayer';
44 |
45 | /**
46 | * 第三方开源库
47 | */
48 | export { default as DistanceTool } from './components/Library/DistanceTool';
49 | export { default as HeatMap } from './components/Library/HeatMap';
50 | export { default as CurveLine } from './components/Library/CurveLine';
51 |
52 | export { default as Constants } from './core/constants';
53 | export { default as BMapUtil } from './core/utils/map';
54 |
--------------------------------------------------------------------------------