@ohos-ports/jsvectormap 1.7.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/jsvectormap.cjs +2355 -0
- package/dist/jsvectormap.css +147 -0
- package/dist/jsvectormap.esm.js +2293 -0
- package/dist/jsvectormap.js +2301 -0
- package/dist/jsvectormap.min.css +1 -0
- package/dist/jsvectormap.min.js +1 -0
- package/dist/maps/world-merc.js +1 -0
- package/dist/maps/world.js +1 -0
- package/package.json +49 -0
- package/src/js/components/base.js +18 -0
- package/src/js/components/concerns/interactable.js +68 -0
- package/src/js/components/line.js +50 -0
- package/src/js/components/marker.js +109 -0
- package/src/js/components/region.js +53 -0
- package/src/js/components/route.js +76 -0
- package/src/js/components/tooltip.js +88 -0
- package/src/js/core/applyTransform.js +43 -0
- package/src/js/core/coordsToPoint.js +22 -0
- package/src/js/core/createLines.js +44 -0
- package/src/js/core/createMarkers.js +55 -0
- package/src/js/core/createRegions.js +23 -0
- package/src/js/core/createRoutes.js +16 -0
- package/src/js/core/createSeries.js +13 -0
- package/src/js/core/getInsetForPoint.js +13 -0
- package/src/js/core/getMarkerPosition.js +12 -0
- package/src/js/core/index.js +41 -0
- package/src/js/core/repositionLabels.js +21 -0
- package/src/js/core/repositionLines.js +30 -0
- package/src/js/core/repositionMarkers.js +11 -0
- package/src/js/core/resize.js +15 -0
- package/src/js/core/setFocus.js +46 -0
- package/src/js/core/setScale.js +65 -0
- package/src/js/core/setupContainerEvents.js +50 -0
- package/src/js/core/setupContainerTouchEvents.js +85 -0
- package/src/js/core/setupElementEvents.js +112 -0
- package/src/js/core/setupZoomButtons.js +40 -0
- package/src/js/core/updateSize.js +7 -0
- package/src/js/dataVisualization.js +87 -0
- package/src/js/defaults/events.js +11 -0
- package/src/js/defaults/options.js +90 -0
- package/src/js/eventHandler.js +47 -0
- package/src/js/index.js +25 -0
- package/src/js/legend.js +69 -0
- package/src/js/map.js +367 -0
- package/src/js/projection.js +127 -0
- package/src/js/scales/ordinalScale.js +21 -0
- package/src/js/series.js +68 -0
- package/src/js/svg/baseElement.js +53 -0
- package/src/js/svg/canvasElement.js +99 -0
- package/src/js/svg/imageElement.js +49 -0
- package/src/js/svg/shapeElement.js +48 -0
- package/src/js/svg/textElement.js +13 -0
- package/src/js/util/deepMerge.js +129 -0
- package/src/js/util/index.js +81 -0
- package/src/scss/_variables.scss +37 -0
- package/src/scss/jsvectormap.scss +153 -0
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ohos-ports/jsvectormap",
|
|
3
|
+
"version": "1.7.0-beta.0",
|
|
4
|
+
"description": "A lightweight Javascript library for creating interactive maps",
|
|
5
|
+
"main": "dist/jsvectormap.min.js",
|
|
6
|
+
"jsdelivr": "dist/jsvectormap.min.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/jsvectormap.esm.js",
|
|
10
|
+
"default": "./dist/jsvectormap.min.js",
|
|
11
|
+
"require": "./dist/jsvectormap.cjs",
|
|
12
|
+
"style": "./dist/jsvectormap.css",
|
|
13
|
+
"sass": "./src/scss/jsvectormap.scss"
|
|
14
|
+
},
|
|
15
|
+
"./*": "./*"
|
|
16
|
+
},
|
|
17
|
+
"style": "dist/jsvectormap.min.css",
|
|
18
|
+
"sass": "src/scss/jsvectormap.scss",
|
|
19
|
+
"author": {
|
|
20
|
+
"name": "Mustafa Omar",
|
|
21
|
+
"email": "themustafaomar@gmail.com"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"dev": "rollup --config --watch",
|
|
25
|
+
"build": "rollup --config ./build/package.js"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"javascript",
|
|
29
|
+
"interactive",
|
|
30
|
+
"vector",
|
|
31
|
+
"map",
|
|
32
|
+
"svg"
|
|
33
|
+
],
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"src",
|
|
37
|
+
"LICENSE"
|
|
38
|
+
],
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/ohos-ports/ohos-ports.git",
|
|
42
|
+
"directory": "ports/jsvectormap/1.7.0"
|
|
43
|
+
},
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/ohos-ports/ohos-ports/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://jvm-docs.vercel.app",
|
|
48
|
+
"license": "MIT"
|
|
49
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { removeElement } from '../util'
|
|
2
|
+
|
|
3
|
+
class BaseComponent {
|
|
4
|
+
dispose() {
|
|
5
|
+
if (this._tooltip) {
|
|
6
|
+
removeElement(this._tooltip)
|
|
7
|
+
} else {
|
|
8
|
+
// @todo: move shape in base component in v2
|
|
9
|
+
this.shape.remove()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
for (const propertyName of Object.getOwnPropertyNames(this)) {
|
|
13
|
+
this[propertyName] = null
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default BaseComponent
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const Interactable = {
|
|
2
|
+
getLabelText(key, label) {
|
|
3
|
+
if (!label) {
|
|
4
|
+
return
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
if (typeof label.render === 'function') {
|
|
8
|
+
let params = []
|
|
9
|
+
|
|
10
|
+
// Pass additional paramater (Marker config object) in case it's a Marker.
|
|
11
|
+
if (this.constructor.Name === 'marker') {
|
|
12
|
+
params.push(this.getConfig())
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Becuase we need to add the key always at the end
|
|
16
|
+
params.push(key)
|
|
17
|
+
|
|
18
|
+
return label.render.apply(this, params)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return key
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
getLabelOffsets(key, label) {
|
|
25
|
+
if (typeof label.offsets === 'function') {
|
|
26
|
+
return label.offsets(key)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// If offsets are an array of offsets e.g offsets: [ [0, 25], [10, 15] ]
|
|
30
|
+
if (Array.isArray(label.offsets)) {
|
|
31
|
+
return label.offsets[key]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return [0, 0]
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
setStyle(property, value) {
|
|
38
|
+
this.shape.setStyle(property, value)
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
remove() {
|
|
42
|
+
this.shape.remove()
|
|
43
|
+
if (this.label) this.label.remove()
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
hover(state) {
|
|
47
|
+
this._setStatus('isHovered', state)
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
select(state) {
|
|
51
|
+
this._setStatus('isSelected', state)
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
// Private
|
|
55
|
+
|
|
56
|
+
_setStatus(property, state) {
|
|
57
|
+
this.shape[property] = state
|
|
58
|
+
this.shape.updateStyle()
|
|
59
|
+
this[property] = state
|
|
60
|
+
|
|
61
|
+
if (this.label) {
|
|
62
|
+
this.label[property] = state
|
|
63
|
+
this.label.updateStyle()
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default Interactable
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import BaseComponent from './base'
|
|
2
|
+
|
|
3
|
+
const LINE_CLASS = 'jvm-line'
|
|
4
|
+
|
|
5
|
+
class Line extends BaseComponent {
|
|
6
|
+
constructor(options, style) {
|
|
7
|
+
super()
|
|
8
|
+
this._options = options
|
|
9
|
+
this._style = { initial: style }
|
|
10
|
+
this._draw()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
setStyle(property, value) {
|
|
14
|
+
this.shape.setStyle(property, value)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getConfig() {
|
|
18
|
+
return this._options.config
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
_draw() {
|
|
22
|
+
const { index, group, map } = this._options
|
|
23
|
+
const config = {
|
|
24
|
+
d: this._getDAttribute(),
|
|
25
|
+
fill: 'none',
|
|
26
|
+
dataIndex: index,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.shape = map.canvas.createPath(config, this._style, group)
|
|
30
|
+
this.shape.addClass(LINE_CLASS)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
_getDAttribute() {
|
|
34
|
+
const { x1, y1, x2, y2, curvature } = this._options
|
|
35
|
+
return `M${x1},${y1}${this._getQCommand(x1, y1, x2, y2, curvature)}${x2},${y2}`
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_getQCommand(x1, y1, x2, y2, curvature) {
|
|
39
|
+
if (!curvature) {
|
|
40
|
+
return ' '
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const curveX = (x1 + x2) / 2 + curvature * (y2 - y1)
|
|
44
|
+
const curveY = (y1 + y2) / 2 - curvature * (x2 - x1)
|
|
45
|
+
|
|
46
|
+
return ` Q${curveX},${curveY} `
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default Line
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { inherit } from '../util'
|
|
2
|
+
import BaseComponent from './base'
|
|
3
|
+
import Interactable from './concerns/interactable'
|
|
4
|
+
|
|
5
|
+
const NAME = 'marker'
|
|
6
|
+
const JVM_PREFIX = 'jvm-'
|
|
7
|
+
const MARKER_CLASS = `${JVM_PREFIX}element ${JVM_PREFIX}marker`
|
|
8
|
+
const MARKER_LABEL_CLASS = `${JVM_PREFIX}element ${JVM_PREFIX}label`
|
|
9
|
+
|
|
10
|
+
class Marker extends BaseComponent {
|
|
11
|
+
static get Name() {
|
|
12
|
+
return NAME
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
constructor(options, style) {
|
|
16
|
+
super()
|
|
17
|
+
|
|
18
|
+
this._options = options
|
|
19
|
+
this._style = style
|
|
20
|
+
this._labelX = null
|
|
21
|
+
this._labelY = null
|
|
22
|
+
this._offsets = null
|
|
23
|
+
this._isImage = !!style.initial.image
|
|
24
|
+
|
|
25
|
+
this._draw()
|
|
26
|
+
|
|
27
|
+
if (this._options.label) {
|
|
28
|
+
this._drawLabel()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (this._isImage) {
|
|
32
|
+
this.updateLabelPosition()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getConfig() {
|
|
37
|
+
return this._options.config
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
updateLabelPosition() {
|
|
41
|
+
const map = this._options.map
|
|
42
|
+
if (this.label) {
|
|
43
|
+
this.label.set({
|
|
44
|
+
x:
|
|
45
|
+
this._labelX * map.scale +
|
|
46
|
+
this._offsets[0] +
|
|
47
|
+
map.transX * map.scale +
|
|
48
|
+
5 +
|
|
49
|
+
(this._isImage
|
|
50
|
+
? (this.shape.width || 0) / 2
|
|
51
|
+
: this.shape.node.r.baseVal.value),
|
|
52
|
+
y:
|
|
53
|
+
this._labelY * map.scale +
|
|
54
|
+
map.transY * this._options.map.scale +
|
|
55
|
+
this._offsets[1],
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
_draw() {
|
|
61
|
+
const { index, map, group, cx, cy } = this._options
|
|
62
|
+
const shapeType = this._isImage ? 'createImage' : 'createCircle'
|
|
63
|
+
|
|
64
|
+
this.shape = map.canvas[shapeType](
|
|
65
|
+
{ dataIndex: index, cx, cy },
|
|
66
|
+
this._style,
|
|
67
|
+
group
|
|
68
|
+
)
|
|
69
|
+
this.shape.addClass(MARKER_CLASS)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
_drawLabel() {
|
|
73
|
+
const {
|
|
74
|
+
index,
|
|
75
|
+
map,
|
|
76
|
+
label,
|
|
77
|
+
labelsGroup,
|
|
78
|
+
cx,
|
|
79
|
+
cy,
|
|
80
|
+
config,
|
|
81
|
+
isRecentlyCreated,
|
|
82
|
+
} = this._options
|
|
83
|
+
const labelText = this.getLabelText(index, label)
|
|
84
|
+
|
|
85
|
+
this._labelX = cx / map.scale - map.transX
|
|
86
|
+
this._labelY = cy / map.scale - map.transY
|
|
87
|
+
this._offsets = isRecentlyCreated && config.offsets ? config.offsets : this.getLabelOffsets(index, label)
|
|
88
|
+
this.label = map.canvas.createText(
|
|
89
|
+
{
|
|
90
|
+
text: labelText,
|
|
91
|
+
dataIndex: index,
|
|
92
|
+
x: this._labelX,
|
|
93
|
+
y: this._labelY,
|
|
94
|
+
dy: '0.6ex',
|
|
95
|
+
},
|
|
96
|
+
map.params.markerLabelStyle,
|
|
97
|
+
labelsGroup
|
|
98
|
+
)
|
|
99
|
+
this.label.addClass(MARKER_LABEL_CLASS)
|
|
100
|
+
|
|
101
|
+
if (isRecentlyCreated) {
|
|
102
|
+
this.updateLabelPosition()
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
inherit(Marker, Interactable)
|
|
108
|
+
|
|
109
|
+
export default Marker
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { inherit } from '../util'
|
|
2
|
+
import BaseComponent from './base'
|
|
3
|
+
import Interactable from './concerns/interactable'
|
|
4
|
+
|
|
5
|
+
class Region extends BaseComponent {
|
|
6
|
+
constructor({ map, code, path, style, label, labelStyle, labelsGroup }) {
|
|
7
|
+
super()
|
|
8
|
+
|
|
9
|
+
this._map = map
|
|
10
|
+
this.shape = this._createRegion(path, code, style)
|
|
11
|
+
|
|
12
|
+
const text = this.getLabelText(code, label)
|
|
13
|
+
|
|
14
|
+
// If label is passed and render function returns something
|
|
15
|
+
if (label && text) {
|
|
16
|
+
const bbox = this.shape.getBBox()
|
|
17
|
+
const offsets = this.getLabelOffsets(code, label)
|
|
18
|
+
|
|
19
|
+
this.labelX = bbox.x + bbox.width / 2 + offsets[0]
|
|
20
|
+
this.labelY = bbox.y + bbox.height / 2 + offsets[1]
|
|
21
|
+
|
|
22
|
+
this.label = this._map.canvas.createText({
|
|
23
|
+
text,
|
|
24
|
+
textAnchor: 'middle',
|
|
25
|
+
alignmentBaseline: 'central',
|
|
26
|
+
dataCode: code,
|
|
27
|
+
x: this.labelX,
|
|
28
|
+
y: this.labelY,
|
|
29
|
+
}, labelStyle, labelsGroup)
|
|
30
|
+
|
|
31
|
+
this.label.addClass('jvm-region jvm-element')
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_createRegion(path, code, style) {
|
|
36
|
+
path = this._map.canvas.createPath({ d: path, dataCode: code }, style)
|
|
37
|
+
path.addClass('jvm-region jvm-element')
|
|
38
|
+
return path
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
updateLabelPosition() {
|
|
42
|
+
if (this.label) {
|
|
43
|
+
this.label.set({
|
|
44
|
+
x: this.labelX * this._map.scale + this._map.transX * this._map.scale,
|
|
45
|
+
y: this.labelY * this._map.scale + this._map.transY * this._map.scale
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
inherit(Region, Interactable)
|
|
52
|
+
|
|
53
|
+
export default Region
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import Component from './base';
|
|
2
|
+
|
|
3
|
+
export class Route extends Component {
|
|
4
|
+
constructor(options, style) {
|
|
5
|
+
super();
|
|
6
|
+
this._options = options;
|
|
7
|
+
this._style = style;
|
|
8
|
+
this._draw();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
_draw() {
|
|
12
|
+
const { node: path } = this._options.map.canvas.createPath(
|
|
13
|
+
{
|
|
14
|
+
d: this._getDAttribute(),
|
|
15
|
+
fill: 'none',
|
|
16
|
+
stroke: '#666',
|
|
17
|
+
strokeWidth: 1,
|
|
18
|
+
dataIndex: this._options.index,
|
|
19
|
+
'stroke-dasharray': '2 4 2',
|
|
20
|
+
},
|
|
21
|
+
this.style,
|
|
22
|
+
this._options.group
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
// Get the total length of the path
|
|
26
|
+
const totalLength = path.getTotalLength();
|
|
27
|
+
|
|
28
|
+
// Initialize the stroke dash array and offset to create the drawing effect
|
|
29
|
+
path.style.strokeDasharray = totalLength;
|
|
30
|
+
path.style.strokeDashoffset = totalLength;
|
|
31
|
+
|
|
32
|
+
// Animate the stroke dash offset to draw the line
|
|
33
|
+
path.animate([{ strokeDashoffset: totalLength }, { strokeDashoffset: 0 }], {
|
|
34
|
+
duration: 4000, // Duration of the animation
|
|
35
|
+
easing: 'linear', // Easing function
|
|
36
|
+
fill: 'forwards', // Keep the line visible after animation ends
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_getDAttribute() {
|
|
41
|
+
const curvature = -0.2;
|
|
42
|
+
const points = this._getPoints();
|
|
43
|
+
let d = `M${points[0].x},${points[0].y}`;
|
|
44
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
45
|
+
const nextPoint = points[i + 1];
|
|
46
|
+
const cpX =
|
|
47
|
+
(points[i].x + nextPoint.x) / 2 +
|
|
48
|
+
curvature * (nextPoint.y - points[i].y);
|
|
49
|
+
const cpY =
|
|
50
|
+
(points[i].y + nextPoint.y) / 2 -
|
|
51
|
+
curvature * (nextPoint.x - points[i].x);
|
|
52
|
+
d += ` Q${cpX},${cpY} ${nextPoint.x},${nextPoint.y}`;
|
|
53
|
+
}
|
|
54
|
+
// let d = `M${points[0].x},${points[0].y}`
|
|
55
|
+
// for (let i = 1; i < points.length; i++) {
|
|
56
|
+
// d += ` L${points[i].x},${points[i].y}`
|
|
57
|
+
// }
|
|
58
|
+
return d
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
_getPoints() {
|
|
62
|
+
const map = this._options.map;
|
|
63
|
+
const points = [];
|
|
64
|
+
|
|
65
|
+
for (let i = 0; i < this._options.waypoints.length; i++) {
|
|
66
|
+
const p = this._options.map.getMarkerPosition({
|
|
67
|
+
coords: [
|
|
68
|
+
this._options.waypoints[i].lat,
|
|
69
|
+
this._options.waypoints[i].lng,
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
points.push(p);
|
|
73
|
+
}
|
|
74
|
+
return points;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createElement,
|
|
3
|
+
findElement,
|
|
4
|
+
} from '../util'
|
|
5
|
+
import EventHandler from '../eventHandler'
|
|
6
|
+
import BaseComponent from './base'
|
|
7
|
+
|
|
8
|
+
class Tooltip extends BaseComponent {
|
|
9
|
+
constructor(map) {
|
|
10
|
+
super()
|
|
11
|
+
|
|
12
|
+
const tooltip = createElement('div', 'jvm-tooltip')
|
|
13
|
+
|
|
14
|
+
this._map = map
|
|
15
|
+
this._tooltip = document.body.appendChild(tooltip)
|
|
16
|
+
|
|
17
|
+
this._bindEventListeners()
|
|
18
|
+
|
|
19
|
+
return this
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_bindEventListeners() {
|
|
23
|
+
EventHandler.on(this._map.container, 'mousemove', event => {
|
|
24
|
+
if (!this._tooltip.classList.contains('active')) {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const container = findElement(this._map.container, '#jvm-regions-group').getBoundingClientRect()
|
|
29
|
+
const space = 5 // Space between the cursor and tooltip element
|
|
30
|
+
|
|
31
|
+
// Tooltip
|
|
32
|
+
const { height, width } = this._tooltip.getBoundingClientRect()
|
|
33
|
+
const topIsPassed = event.clientY <= (container.top + height + space)
|
|
34
|
+
let top = event.pageY - height - space
|
|
35
|
+
let left = event.pageX - width - space
|
|
36
|
+
|
|
37
|
+
// Ensure the tooltip will never cross outside the canvas area(map)
|
|
38
|
+
if (topIsPassed) { // Top:
|
|
39
|
+
top += height + space
|
|
40
|
+
|
|
41
|
+
// The cursor is a bit larger from left side
|
|
42
|
+
left -= space * 2
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (event.clientX < (container.left + width + space)) { // Left:
|
|
46
|
+
left = event.pageX + space + 2
|
|
47
|
+
|
|
48
|
+
if (topIsPassed) {
|
|
49
|
+
left += space * 2
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
this.css({ top: `${top}px`, left: `${left}px` })
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getElement() {
|
|
58
|
+
return this._tooltip
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
show() {
|
|
62
|
+
this._tooltip.classList.add('active')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
hide() {
|
|
66
|
+
this._tooltip.classList.remove('active')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
text(string, html = false) {
|
|
70
|
+
const property = html ? 'innerHTML' : 'textContent'
|
|
71
|
+
|
|
72
|
+
if (!string) {
|
|
73
|
+
return this._tooltip[property]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
this._tooltip[property] = string
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
css(css) {
|
|
80
|
+
for (let style in css) {
|
|
81
|
+
this._tooltip.style[style] = css[style]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default Tooltip
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export default function applyTransform() {
|
|
2
|
+
let maxTransX, maxTransY, minTransX, minTransY
|
|
3
|
+
|
|
4
|
+
if (this._defaultWidth * this.scale <= this._width) {
|
|
5
|
+
maxTransX = (this._width - this._defaultWidth * this.scale) / (2 * this.scale)
|
|
6
|
+
minTransX = (this._width - this._defaultWidth * this.scale) / (2 * this.scale)
|
|
7
|
+
} else {
|
|
8
|
+
maxTransX = 0
|
|
9
|
+
minTransX = (this._width - this._defaultWidth * this.scale) / this.scale
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (this._defaultHeight * this.scale <= this._height) {
|
|
13
|
+
maxTransY = (this._height - this._defaultHeight * this.scale) / (2 * this.scale)
|
|
14
|
+
minTransY = (this._height - this._defaultHeight * this.scale) / (2 * this.scale)
|
|
15
|
+
} else {
|
|
16
|
+
maxTransY = 0
|
|
17
|
+
minTransY = (this._height - this._defaultHeight * this.scale) / this.scale
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (this.transY > maxTransY) {
|
|
21
|
+
this.transY = maxTransY
|
|
22
|
+
} else if (this.transY < minTransY) {
|
|
23
|
+
this.transY = minTransY
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (this.transX > maxTransX) {
|
|
27
|
+
this.transX = maxTransX
|
|
28
|
+
} else if (this.transX < minTransX) {
|
|
29
|
+
this.transX = minTransX
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.canvas.applyTransformParams(this.scale, this.transX, this.transY)
|
|
33
|
+
|
|
34
|
+
if (this._markers) {
|
|
35
|
+
this._repositionMarkers()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (this._lines) {
|
|
39
|
+
this._repositionLines()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this._repositionLabels()
|
|
43
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Map from '../map'
|
|
2
|
+
import Proj from '../projection'
|
|
3
|
+
|
|
4
|
+
export default function coordsToPoint(lat, lng) {
|
|
5
|
+
const projection = Map.maps[this.params.map].projection
|
|
6
|
+
let { x, y } = Proj[projection.type](lat, lng, projection.centralMeridian)
|
|
7
|
+
let inset = this.getInsetForPoint(x, y)
|
|
8
|
+
|
|
9
|
+
if (!inset) {
|
|
10
|
+
return false
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let bbox = inset.bbox
|
|
14
|
+
|
|
15
|
+
x = (x - bbox[0].x) / (bbox[1].x - bbox[0].x) * inset.width * this.scale
|
|
16
|
+
y = (y - bbox[0].y) / (bbox[1].y - bbox[0].y) * inset.height * this.scale
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
x: x + this.transX * this.scale + inset.left * this.scale,
|
|
20
|
+
y: y + this.transY * this.scale + inset.top * this.scale
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { merge, getLineUid } from '../util'
|
|
2
|
+
import Line from '../components/line'
|
|
3
|
+
|
|
4
|
+
export default function createLines(lines) {
|
|
5
|
+
let point1 = false, point2 = false
|
|
6
|
+
const { curvature, ...lineStyle } = this.params.lineStyle
|
|
7
|
+
|
|
8
|
+
for (let index in lines) {
|
|
9
|
+
const lineConfig = lines[index]
|
|
10
|
+
|
|
11
|
+
for (let { config: markerConfig } of Object.values(this._markers)) {
|
|
12
|
+
if (markerConfig.name === lineConfig.from) {
|
|
13
|
+
point1 = this.getMarkerPosition(markerConfig)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (markerConfig.name === lineConfig.to) {
|
|
17
|
+
point2 = this.getMarkerPosition(markerConfig)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (point1 !== false && point2 !== false) {
|
|
22
|
+
const {
|
|
23
|
+
curvature: curvatureOption,
|
|
24
|
+
...style
|
|
25
|
+
} = lineConfig.style || {}
|
|
26
|
+
|
|
27
|
+
// Register lines with unique keys
|
|
28
|
+
this._lines[getLineUid(lineConfig.from, lineConfig.to)] = new Line(
|
|
29
|
+
{
|
|
30
|
+
index,
|
|
31
|
+
map: this,
|
|
32
|
+
group: this._linesGroup,
|
|
33
|
+
config: lineConfig,
|
|
34
|
+
x1: point1.x,
|
|
35
|
+
y1: point1.y,
|
|
36
|
+
x2: point2.x,
|
|
37
|
+
y2: point2.y,
|
|
38
|
+
curvature: curvatureOption == 0 ? 0 : (curvatureOption || curvature),
|
|
39
|
+
},
|
|
40
|
+
merge(lineStyle, style, true)
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { merge } from '../util'
|
|
2
|
+
import Marker from '../components/marker'
|
|
3
|
+
|
|
4
|
+
export default function createMarkers(markers = {}, isRecentlyCreated = false) {
|
|
5
|
+
for (let index in markers) {
|
|
6
|
+
const config = markers[index]
|
|
7
|
+
const point = this.getMarkerPosition(config)
|
|
8
|
+
const uid = config.coords.join(':')
|
|
9
|
+
|
|
10
|
+
if (!point) {
|
|
11
|
+
continue
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// We're checking if recently created marker does already exist
|
|
15
|
+
// If it does we don't need to create it again, so we'll continue
|
|
16
|
+
// Becuase we may have more than one marker submitted via `addMarkers` method.
|
|
17
|
+
if (isRecentlyCreated) {
|
|
18
|
+
if (
|
|
19
|
+
Object.keys(this._markers).filter(i => this._markers[i]._uid === uid).length
|
|
20
|
+
) {
|
|
21
|
+
continue
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
index = Object.keys(this._markers).length
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const marker = new Marker(
|
|
28
|
+
{
|
|
29
|
+
index,
|
|
30
|
+
map: this,
|
|
31
|
+
label: this.params.labels && this.params.labels.markers,
|
|
32
|
+
labelsGroup: this._markerLabelsGroup,
|
|
33
|
+
cx: point.x,
|
|
34
|
+
cy: point.y,
|
|
35
|
+
group: this._markersGroup,
|
|
36
|
+
config,
|
|
37
|
+
isRecentlyCreated,
|
|
38
|
+
},
|
|
39
|
+
merge(this.params.markerStyle, { ...(config.style || {}) }, true)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
// Check for marker duplication
|
|
43
|
+
// this is useful when for example: a user clicks a button for creating marker two times
|
|
44
|
+
// so it will remove the old one and the new one will take its place.
|
|
45
|
+
if (this._markers[index]) {
|
|
46
|
+
this.removeMarkers([index])
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this._markers[index] = {
|
|
50
|
+
_uid: uid,
|
|
51
|
+
config: config,
|
|
52
|
+
element: marker,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|