diff --git a/example/index.module.html b/example/index.module.html
index f8e7285..8fb2a21 100644
--- a/example/index.module.html
+++ b/example/index.module.html
@@ -2,101 +2,66 @@
-
-
-
-
+
+
+
+
+
+
-
diff --git a/package-lock.json b/package-lock.json
index da29e59..ed47ec9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1884,6 +1884,11 @@
"array-find-index": "^1.0.1"
}
},
+ "d3-array": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.9.1.tgz",
+ "integrity": "sha512-Ob7RdOtkqsjx1NWyQHMFLtCSk6/aKTxDdC4ZIolX+O+mDD2RzrsYgAyc0WGAlfYFVELLSilS7w8BtE3PKM8bHg=="
+ },
"d3-dispatch": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
@@ -1898,6 +1903,14 @@
"d3-selection": "2"
}
},
+ "d3-geo": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-2.0.1.tgz",
+ "integrity": "sha512-M6yzGbFRfxzNrVhxDJXzJqSLQ90q1cCyb3EWFZ1LF4eWOBYxFypw7I/NFVBNXKNqxv1bqLathhYvdJ6DC+th3A==",
+ "requires": {
+ "d3-array": ">=2.5"
+ }
+ },
"d3-selection": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz",
diff --git a/package.json b/package.json
index eb87f9f..79dcbba 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
"homepage": "https://github.com/zhenyanghua/MeasureTool-GoogleMaps-V3#readme",
"dependencies": {
"d3-drag": "^2.0.0",
+ "d3-geo": "^2.0.1",
"d3-selection": "^2.0.0"
},
"devDependencies": {
diff --git a/rollup.config.js b/rollup.config.js
index 932b74a..6f81ec4 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -46,4 +46,4 @@ const esm = {
onwarn
};
-export default [umd, esm];
+export default [esm];
diff --git a/src/geometry.js b/src/geometry.js
index e6d6244..7ae226f 100644
--- a/src/geometry.js
+++ b/src/geometry.js
@@ -12,6 +12,20 @@ export class Geometry {
return segments;
}
+ get lingString() {
+ return Geometry.toLineString(this._nodes);
+ }
+
+ static toLineString(points) {
+ return {
+ "type": "Feature",
+ "geometry": {
+ "type": "LineString",
+ "coordinates": points
+ }
+ }
+ }
+
constructor() {
this._nodes = [];
}
@@ -31,4 +45,20 @@ export class Geometry {
insertNode(i, point) {
this._nodes.splice(i, 0, point);
}
+
+ static equals(segments1, segments2) {
+ if (segments1.length !== segments2.length) {
+ return false;
+ }
+ for (let i = 0; i < segments1.length; i++) {
+ if (segments1[i][0][0] !== segments2[i][0][0] ||
+ segments1[i][0][1] !== segments2[i][0][1] ||
+ segments1[i][1][0] !== segments2[i][1][0] ||
+ segments1[i][1][1] !== segments2[i][1][1]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
}
diff --git a/src/helper.js b/src/helper.js
index 6842e6d..04637e7 100644
--- a/src/helper.js
+++ b/src/helper.js
@@ -1,10 +1,12 @@
import { UnitTypeId } from './UnitTypeId';
+import { Geometry } from './geometry';
export default class Helper {
constructor(options) {
this._options = {
unit: UnitTypeId.METRIC,
};
Object.assign(this._options, options);
+ this._lastInterpolatedPoints = { segments: [], length: 0, points: [] };
this.init();
}
@@ -196,7 +198,7 @@ export default class Helper {
* @private
*/
static _interpolate(p1, p2, fraction) {
- let point = google.maps.geometry.spherical.interpolate(
+ const point = google.maps.geometry.spherical.interpolate(
new google.maps.LatLng(p1[1], p1[0]),
new google.maps.LatLng(p2[1], p2[0]),
fraction
@@ -209,4 +211,62 @@ export default class Helper {
// let y = m * x + b;
// return [x, y];
}
+
+ /**
+ * if last segment length (start with 0) adds current segment length is less than tick length,
+ * segment length = last segment length + segment length
+ * last segment length = segment length;
+ * move on to the next segment
+ *
+ * current point = compute the latlng using fraction (tick length - last segment length ) / current segment length
+ * between current segment start point and end point.
+ * segment length = segment length - (tick length - last segment length)
+ *
+ * While the given minimum tick length is less than the segment length,
+ * compute the latlng at the fraction between current point and the end point.
+ * push the latlng
+ * assign the latlng to current point.
+ * segment length subtracts tick length.
+ *
+ * @param segments
+ * @param length
+ * @param includeSegmentNodes
+ */
+ interpolatePointsOnPath(segments, length, includeSegmentNodes = false) {
+ if (this._lastInterpolatedPoints.length === length &&
+ Geometry.equals(this._lastInterpolatedPoints.segments, segments)) {
+ return this._lastInterpolatedPoints.points;
+ }
+ console.debug('interpolatePointsOnPath called')
+ if (segments.length === 0) return [];
+ let lastSegmentLength = 0, curPoint = segments[0][0], points = [];
+ for (let i = 0; i < segments.length; i++) {
+ if (includeSegmentNodes) points.push(segments[i][0]);
+ let segmentLength = this.computeLengthBetween(segments[i][0], segments[i][1]);
+ if (lastSegmentLength + segmentLength < length) {
+ segmentLength += lastSegmentLength;
+ lastSegmentLength = segmentLength;
+ continue;
+ }
+ curPoint = Helper._interpolate(
+ segments[i][0],
+ segments[i][1],
+ (length - lastSegmentLength) / segmentLength);
+ segmentLength -= (length - lastSegmentLength);
+ points.push(curPoint);
+ while(length < segmentLength) {
+ curPoint = Helper._interpolate(curPoint, segments[i][1], length / segmentLength);
+ points.push(curPoint);
+ segmentLength -= length;
+ lastSegmentLength = segmentLength;
+ }
+ }
+ if (includeSegmentNodes) points.push(segments[segments.length - 1][1]);
+ this._lastInterpolatedPoints = {
+ length,
+ segments,
+ points
+ };
+ return points;
+ }
}
diff --git a/src/index.js b/src/index.js
index 1ff50a2..ba9305f 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,5 +1,6 @@
import { drag } from 'd3-drag';
import { select, selectAll } from 'd3-selection';
+import { geoPath, geoTransform, geoClipRectangle, geoProjection, geoMercator } from 'd3-geo';
import { Config } from './config';
import ContextMenu from './context-menu';
import Tooltip from './tooltip';
@@ -66,13 +67,14 @@ export default class MeasureTool {
initialSegments: [],
language: navigator ? navigator.language : 'en',
invertColor: false,
- ...options,
+ ...options
};
this._map = map;
this._map.setClickableIcons(false);
this._id = Helper.makeId(4);
this._events = new Map();
this._geometry = new Geometry();
+ this._computeTickLength();
this._init();
}
@@ -105,7 +107,7 @@ export default class MeasureTool {
}
this._helper = new Helper({
- unit: this._options.unit,
+ unit: this._options.unit
});
this._initOverlay();
}
@@ -275,6 +277,27 @@ export default class MeasureTool {
.append('svg')
.attr('class', `${Config.prefix}-svg-overlay`);
+ const { paths, gmPath } = this._getProjectedPath();
+ this._tickPath = this._svgOverlay
+ .append('g')
+ .attr('class', 'tick-path');
+ this._tickPath.selectAll('path').data(paths);
+
+ this._ticks = this._svgOverlay
+ .append('g')
+ .attr('class', 'ticks');
+ this._ticks.append('marker')
+ .attr('id', 'marker-small-ticks')
+ .attr('markerHeight', 3)
+ .attr('markerWidth', 1)
+ .attr('markerUnits', 'strokeWidth')
+ .attr('orient', 'auto')
+ .attr('refX', 0)
+ .attr('refY', 0)
+ .attr('viewBox', '-1 0 2 5')
+ .append('path')
+ .attr('d', 'M 0,0 m -1,0 L 1,0 L 1,5 L -1,5 Z');
+
this._linesBase = this._svgOverlay.append('g').attr('class', 'base');
this._linesBase.selectAll('line').data(this._geometry.lines);
@@ -328,6 +351,7 @@ export default class MeasureTool {
this._updateCircles();
this._updateTouchCircles();
this._updateLine();
+ this._updatePath();
if (this._options.showSegmentLength) {
this._updateSegmentText();
}
@@ -386,12 +410,12 @@ export default class MeasureTool {
: getClass('cover-circle', this._options.invertColor)
)
.attr('r', nodeTargetRadius)
- .attr('cx', ([d]) => this._projectionUtility.latLngToSvgPoint(d)[0])
- .attr('cy', ([d]) => this._projectionUtility.latLngToSvgPoint(d)[1])
- .on('mouseover', function (event, [d, i]) {
+ .attr('cx', ([d]) => this._projectionUtility.lngLatToSvgPoint(d)[0])
+ .attr('cy', ([d]) => this._projectionUtility.lngLatToSvgPoint(d)[1])
+ .on('mouseover', function(event, [d, i]) {
self._onOverCircle(d, i, this);
})
- .on('mouseout', function (event, [d, i]) {
+ .on('mouseout', function(event, [d, i]) {
self._onOutCircle(d, i, this);
})
.on('mousedown', () => this._hideTooltip());
@@ -402,12 +426,12 @@ export default class MeasureTool {
.append('circle')
.attr('class', getClass('cover-circle', this._options.invertColor))
.attr('r', nodeTargetRadius)
- .attr('cx', ([d]) => this._projectionUtility.latLngToSvgPoint(d)[0])
- .attr('cy', ([d]) => this._projectionUtility.latLngToSvgPoint(d)[1])
- .on('mouseover', function (event, [d, i]) {
+ .attr('cx', ([d]) => this._projectionUtility.lngLatToSvgPoint(d)[0])
+ .attr('cy', ([d]) => this._projectionUtility.lngLatToSvgPoint(d)[1])
+ .on('mouseover', function(event, [d, i]) {
self._onOverCircle(d, i, this);
})
- .on('mouseout', function (event, [d, i]) {
+ .on('mouseout', function(event, [d, i]) {
self._onOutCircle(d, i, this);
})
.on('mousedown', () => this._hideTooltip());
@@ -429,19 +453,19 @@ export default class MeasureTool {
: getClass('touch-circle', this._options.invertColor)
)
.attr('r', touchTargetRadius)
- .attr('cx', ([d]) => this._projectionUtility.latLngToSvgPoint(d)[0])
- .attr('cy', ([d]) => this._projectionUtility.latLngToSvgPoint(d)[1])
- .on('mouseover', function (event, [d, i]) {
+ .attr('cx', ([d]) => this._projectionUtility.lngLatToSvgPoint(d)[0])
+ .attr('cy', ([d]) => this._projectionUtility.lngLatToSvgPoint(d)[1])
+ .on('mouseover', function(event, [d, i]) {
self._onOverCircle(d, i, this);
})
- .on('mouseout', function (event, [d, i]) {
+ .on('mouseout', function(event, [d, i]) {
self._onOutCircle(d, i, this);
})
- .on('touchstart', function (event, [d, i]) {
+ .on('touchstart', function(event, [d, i]) {
event.preventDefault();
self._onOverCircle(d, i, this, true);
})
- .on('touchend', function (event, [d, i]) {
+ .on('touchend', function(event, [d, i]) {
event.preventDefault();
self._onOutCircle(d, i, this);
})
@@ -454,19 +478,19 @@ export default class MeasureTool {
.append('circle')
.attr('class', getClass('touch-circle', this._options.invertColor))
.attr('r', touchTargetRadius)
- .attr('cx', ([d]) => this._projectionUtility.latLngToSvgPoint(d)[0])
- .attr('cy', ([d]) => this._projectionUtility.latLngToSvgPoint(d)[1])
- .on('mouseover', function (event, [d, i]) {
+ .attr('cx', ([d]) => this._projectionUtility.lngLatToSvgPoint(d)[0])
+ .attr('cy', ([d]) => this._projectionUtility.lngLatToSvgPoint(d)[1])
+ .on('mouseover', function(event, [d, i]) {
self._onOverCircle(d, i, this);
})
- .on('mouseout', function (event, [d, i]) {
+ .on('mouseout', function(event, [d, i]) {
self._onOutCircle(d, i, this);
})
- .on('touchstart', function (event, [d, i]) {
+ .on('touchstart', function(event, [d, i]) {
event.preventDefault();
self._onOverCircle(d, i, this, true);
})
- .on('touchend', function (event, [d, i]) {
+ .on('touchend', function(event, [d, i]) {
event.preventDefault();
self._onOutCircle(d, i, this);
})
@@ -483,10 +507,10 @@ export default class MeasureTool {
.selectAll('line')
.data(this._geometry.lines)
.attr('class', getClass('base-line', this._options.invertColor))
- .attr('x1', (d) => this._projectionUtility.latLngToSvgPoint(d[0])[0])
- .attr('y1', (d) => this._projectionUtility.latLngToSvgPoint(d[0])[1])
- .attr('x2', (d) => this._projectionUtility.latLngToSvgPoint(d[1])[0])
- .attr('y2', (d) => this._projectionUtility.latLngToSvgPoint(d[1])[1])
+ .attr('x1', (d) => this._projectionUtility.lngLatToSvgPoint(d[0])[0])
+ .attr('y1', (d) => this._projectionUtility.lngLatToSvgPoint(d[0])[1])
+ .attr('x2', (d) => this._projectionUtility.lngLatToSvgPoint(d[1])[0])
+ .attr('y2', (d) => this._projectionUtility.lngLatToSvgPoint(d[1])[1])
.each((d) => this._updateSegment(d));
linesBase.exit().remove();
@@ -494,10 +518,10 @@ export default class MeasureTool {
.enter()
.append('line')
.attr('class', getClass('base-line', this._options.invertColor))
- .attr('x1', (d) => this._projectionUtility.latLngToSvgPoint(d[0])[0])
- .attr('y1', (d) => this._projectionUtility.latLngToSvgPoint(d[0])[1])
- .attr('x2', (d) => this._projectionUtility.latLngToSvgPoint(d[1])[0])
- .attr('y2', (d) => this._projectionUtility.latLngToSvgPoint(d[1])[1])
+ .attr('x1', (d) => this._projectionUtility.lngLatToSvgPoint(d[0])[0])
+ .attr('y1', (d) => this._projectionUtility.lngLatToSvgPoint(d[0])[1])
+ .attr('x2', (d) => this._projectionUtility.lngLatToSvgPoint(d[1])[0])
+ .attr('y2', (d) => this._projectionUtility.lngLatToSvgPoint(d[1])[1])
.each((d) => this._updateSegment(d));
let linesAux = this._linesAux
@@ -506,17 +530,17 @@ export default class MeasureTool {
.join('line')
.datum((d, i) => [d, i])
.attr('class', 'aux-line')
- .attr('x1', ([d]) => this._projectionUtility.latLngToSvgPoint(d[0])[0])
- .attr('y1', ([d]) => this._projectionUtility.latLngToSvgPoint(d[0])[1])
- .attr('x2', ([d]) => this._projectionUtility.latLngToSvgPoint(d[1])[0])
- .attr('y2', ([d]) => this._projectionUtility.latLngToSvgPoint(d[1])[1]);
+ .attr('x1', ([d]) => this._projectionUtility.lngLatToSvgPoint(d[0])[0])
+ .attr('y1', ([d]) => this._projectionUtility.lngLatToSvgPoint(d[0])[1])
+ .attr('x2', ([d]) => this._projectionUtility.lngLatToSvgPoint(d[1])[0])
+ .attr('y2', ([d]) => this._projectionUtility.lngLatToSvgPoint(d[1])[1]);
linesAux
.on('mousemove', (event, [d]) => {
let point = Helper.findTouchPoint(
[
- this._projectionUtility.latLngToSvgPoint(d[0]),
- this._projectionUtility.latLngToSvgPoint(d[1]),
+ this._projectionUtility.lngLatToSvgPoint(d[0]),
+ this._projectionUtility.lngLatToSvgPoint(d[1])
],
[event.offsetX, event.offsetY]
);
@@ -537,16 +561,65 @@ export default class MeasureTool {
.join('line')
.datum((d, i) => [d, i])
.attr('class', 'aux-line')
- .attr('x1', ([d]) => this._projectionUtility.latLngToSvgPoint(d[0])[0])
- .attr('y1', ([d]) => this._projectionUtility.latLngToSvgPoint(d[0])[1])
- .attr('x2', ([d]) => this._projectionUtility.latLngToSvgPoint(d[1])[0])
- .attr('y2', ([d]) => this._projectionUtility.latLngToSvgPoint(d[1])[1]);
+ .attr('x1', ([d]) => this._projectionUtility.lngLatToSvgPoint(d[0])[0])
+ .attr('y1', ([d]) => this._projectionUtility.lngLatToSvgPoint(d[0])[1])
+ .attr('x2', ([d]) => this._projectionUtility.lngLatToSvgPoint(d[1])[0])
+ .attr('y2', ([d]) => this._projectionUtility.lngLatToSvgPoint(d[1])[1]);
const lineDrag = this._lineDrag.selectAll('line').data([]);
lineDrag.exit().remove();
}
+ _updatePath() {
+ const { paths, gmPath } = this._getProjectedPath();
+ const tickPath = this._tickPath.selectAll('path')
+ .data(paths)
+ .attr('class', 'tick-path')
+ .attr('d', gmPath);
+
+ tickPath.exit().remove();
+ tickPath
+ .enter()
+ .append('path')
+ .attr('d', gmPath);
+ // .attr('marker-start', `url(#marker-small-ticks)`)
+ // .attr('marker-mid', `url(#marker-small-ticks)`)
+ // .attr('marker-end', `url(#marker-small-ticks)`);
+ }
+
+ _getProjectedPath() {
+ const self = this;
+ this._computeTickLength();
+ // FIXME - interpolate every points along a line that span across the world
+ // when the zoom level is large kills the performance. Need a different way
+ // of to partial interpolate the points that only within the bounds.
+ // todo - check if d3 projection handles geodesic projection for start/end
+ const points = this._helper.interpolatePointsOnPath(
+ this._geometry.lines, this._tickLength, true
+ );
+ // console.debug('points count', points.length);
+ // const paths = [Geometry.toLineString(points)];
+ const paths = [this._geometry.lingString];
+ const gmTransform = geoTransform({
+ point: function(lng, lat) {
+ // if (self._map.getBounds().contains({ lat, lng })) {
+ const [x, y] = self._projectionUtility.lngLatToSvgPoint([lng, lat]);
+ this.stream.point(x, y);
+ // }
+ }
+ });
+ // const { east, north, south, west } = this._map.getBounds().toJSON();
+ // const [x0, y0] = this._projectionUtility.lngLatToSvgPoint([south, west]);
+ // const [x1, y1] = this._projectionUtility.lngLatToSvgPoint([north, east]);
+ // const clip = geoClipRectangle(x0, y0, x1, y1);
+ const projection = geoMercator();
+ // projection.postclip(clip);
+ const gmPath = geoPath(projection).projection(gmTransform);
+
+ return { paths, gmPath };
+ }
+
_updateSegmentText() {
let text = this._segmentText
.selectAll('text')
@@ -558,8 +631,8 @@ export default class MeasureTool {
.attr('text-anchor', 'middle')
.attr('dominant-baseline', 'text-before-edge')
.attr('transform', (d) => {
- let p1 = this._projectionUtility.latLngToSvgPoint(d[0]);
- let p2 = this._projectionUtility.latLngToSvgPoint(d[1]);
+ let p1 = this._projectionUtility.lngLatToSvgPoint(d[0]);
+ let p2 = this._projectionUtility.lngLatToSvgPoint(d[1]);
return Helper.transformText(p1, p2);
})
.text((d, i) =>
@@ -576,8 +649,8 @@ export default class MeasureTool {
.attr('text-anchor', 'middle')
.attr('dominant-baseline', 'text-before-edge')
.attr('transform', (d) => {
- let p1 = this._projectionUtility.latLngToSvgPoint(d[0]);
- let p2 = this._projectionUtility.latLngToSvgPoint(d[1]);
+ let p1 = this._projectionUtility.lngLatToSvgPoint(d[0]);
+ let p2 = this._projectionUtility.lngLatToSvgPoint(d[1]);
return Helper.transformText(p1, p2);
})
.text((d, i) =>
@@ -594,14 +667,14 @@ export default class MeasureTool {
.attr('class', (d, i) =>
i === 0
? `${getClass(
- 'node-measure-text',
- this._options.invertColor
- )} head-text`
+ 'node-measure-text',
+ this._options.invertColor
+ )} head-text`
: getClass('node-measure-text', this._options.invertColor)
)
.attr('text-anchor', 'middle')
.attr('dominant-baseline', 'text-after-edge')
- .attr('x', (d) => this._projectionUtility.latLngToSvgPoint(d)[0])
+ .attr('x', (d) => this._projectionUtility.lngLatToSvgPoint(d)[0])
.attr('y', this._transformNodeTextY.bind(this))
.text((d, i) => {
let len = this._helper.computePathLength(
@@ -619,14 +692,14 @@ export default class MeasureTool {
.attr('class', (d, i) =>
i === 0
? `${getClass(
- 'node-measure-text',
- this._options.invertColor
- )} head-text`
+ 'node-measure-text',
+ this._options.invertColor
+ )} head-text`
: getClass('node-measure-text', this._options.invertColor)
)
.attr('text-anchor', 'middle')
.attr('dominant-baseline', 'text-after-edge')
- .attr('x', (d) => this._projectionUtility.latLngToSvgPoint(d)[0])
+ .attr('x', (d) => this._projectionUtility.lngLatToSvgPoint(d)[0])
.attr('y', this._transformNodeTextY.bind(this))
.text((d, i) => {
let len = this._helper.computePathLength(
@@ -651,7 +724,7 @@ export default class MeasureTool {
if (this._options.tooltip && !isTouch) {
this._tooltip.show(
- this._projectionUtility.latLngToContainerPoint(d),
+ this._projectionUtility.lngLatToContainerPoint(d),
i === 0
? Config.tooltipText2(this._options.language)
: Config.tooltipText1(this._options.language)
@@ -672,7 +745,7 @@ export default class MeasureTool {
let self = this;
let isDragged = false;
- let circleDrag = drag().on('drag', function (event, [, i]) {
+ let circleDrag = drag().on('drag', function(event, [, i]) {
isDragged = true;
self._dragging = true;
@@ -692,13 +765,13 @@ export default class MeasureTool {
);
});
- circleDrag.on('start', function (event) {
+ circleDrag.on('start', function(event) {
event.sourceEvent.stopPropagation();
select(this).raise().attr('r', nodeTargetExpandRadius);
self._disableMapScroll();
});
- circleDrag.on('end', function (event, [d, i]) {
+ circleDrag.on('end', function(event, [d, i]) {
self._enableMapScroll();
if (!isDragged) {
if (i > 0) {
@@ -751,10 +824,10 @@ export default class MeasureTool {
.enter()
.append('line')
.attr('class', getClass('base-line', this._options.invertColor))
- .attr('x1', (d) => this._projectionUtility.latLngToSvgPoint(d[0])[0])
- .attr('y1', (d) => this._projectionUtility.latLngToSvgPoint(d[0])[1])
- .attr('x2', (d) => this._projectionUtility.latLngToSvgPoint(d[1])[0])
- .attr('y2', (d) => this._projectionUtility.latLngToSvgPoint(d[1])[1]);
+ .attr('x1', (d) => this._projectionUtility.lngLatToSvgPoint(d[0])[0])
+ .attr('y1', (d) => this._projectionUtility.lngLatToSvgPoint(d[0])[1])
+ .attr('x2', (d) => this._projectionUtility.lngLatToSvgPoint(d[1])[0])
+ .attr('y2', (d) => this._projectionUtility.lngLatToSvgPoint(d[1])[1]);
this._linesBase.selectAll('line').style('display', 'none');
this._linesAux.selectAll('line').style('display', 'none');
@@ -839,7 +912,7 @@ export default class MeasureTool {
.select(`text:nth-child(${index + 1})`)
.attr('transform', (d) => {
let p1 = [event.x, event.y];
- let p2 = this._projectionUtility.latLngToSvgPoint(d[1]);
+ let p2 = this._projectionUtility.lngLatToSvgPoint(d[1]);
return Helper.transformText(p1, p2);
})
.text((d) =>
@@ -855,7 +928,7 @@ export default class MeasureTool {
this._segmentText
.select(`text:nth-child(${index})`)
.attr('transform', (d) => {
- let p1 = this._projectionUtility.latLngToSvgPoint(d[0]);
+ let p1 = this._projectionUtility.lngLatToSvgPoint(d[0]);
let p2 = [event.x, event.y];
return Helper.transformText(p1, p2);
})
@@ -878,7 +951,7 @@ export default class MeasureTool {
let offset;
if (
index > 0 &&
- this._projectionUtility.latLngToSvgPoint(
+ this._projectionUtility.lngLatToSvgPoint(
this._geometry.nodes[index - 1]
)[1] < event.y
) {
@@ -892,13 +965,13 @@ export default class MeasureTool {
let offset;
if (
index + 1 > 0 &&
- event.y < this._projectionUtility.latLngToSvgPoint(d)[1]
+ event.y < this._projectionUtility.lngLatToSvgPoint(d)[1]
) {
offset = 23;
} else {
offset = -7;
}
- return this._projectionUtility.latLngToSvgPoint(d)[1] + offset;
+ return this._projectionUtility.lngLatToSvgPoint(d)[1] + offset;
});
let followingNodes = this._nodeText
.selectAll('text')
@@ -907,7 +980,7 @@ export default class MeasureTool {
let len = this._helper.computePathLength([
...this._geometry.nodes.slice(0, index),
this._projectionUtility.svgPointToLatLng([event.x, event.y]),
- ...this._geometry.nodes.slice(index + 1, index + 1 + i),
+ ...this._geometry.nodes.slice(index + 1, index + 1 + i)
]);
if (index + i === this._geometry.nodes.length - 1) {
this._length = len;
@@ -940,12 +1013,12 @@ export default class MeasureTool {
_disableMapScroll() {
this._zoomControl = !!document.querySelector(
- "button[aria-label='Zoom in']"
+ 'button[aria-label=\'Zoom in\']'
);
this._map.setOptions({
scrollwheel: false,
gestureHandling: 'none',
- zoomControl: false,
+ zoomControl: false
});
}
@@ -953,7 +1026,7 @@ export default class MeasureTool {
this._map.setOptions({
scrollwheel: true,
gestureHandling: 'auto',
- zoomControl: this._zoomControl,
+ zoomControl: this._zoomControl
});
}
@@ -964,7 +1037,7 @@ export default class MeasureTool {
} else {
offset = -7;
}
- return this._projectionUtility.latLngToSvgPoint(d)[1] + offset;
+ return this._projectionUtility.lngLatToSvgPoint(d)[1] + offset;
}
_updateArea(i, pointToCompare) {
@@ -983,9 +1056,9 @@ export default class MeasureTool {
offset > tolerance
? 0
: this._helper.computeArea([
- pointToCompare,
- ...this._geometry.nodes.slice(1, n - 1),
- ]);
+ pointToCompare,
+ ...this._geometry.nodes.slice(1, n - 1)
+ ]);
} else if (i === n - 1) {
offset = this._helper.computeLengthBetween(
pointToCompare,
@@ -1004,10 +1077,10 @@ export default class MeasureTool {
offset > tolerance
? 0
: this._helper.computeArea([
- ...this._geometry.nodes.slice(0, i),
- pointToCompare,
- ...this._geometry.nodes.slice(i + 1),
- ]);
+ ...this._geometry.nodes.slice(0, i),
+ pointToCompare,
+ ...this._geometry.nodes.slice(i + 1)
+ ]);
} else {
offset = this._helper.computeLengthBetween(
this._geometry.nodes[0],
@@ -1077,8 +1150,15 @@ export default class MeasureTool {
area: this.area,
areaText: this.areaText,
segments: this.segments,
- points: this.points,
- },
+ points: this.points
+ }
};
}
+
+ _computeTickLength() {
+ // const metersPerPixel = 156543.03392 * Math.cos(this._map.getCenter().lat() * Math.PI / 180)
+ // / Math.pow(2, this._map.getZoom());
+ // this._tickLength = metersPerPixel * 30;
+ this._tickLength = 1600000 / Math.pow(2, this._map.getZoom() - 1);
+ }
}
diff --git a/src/index.scss b/src/index.scss
index 75831d0..1e8788a 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -26,6 +26,22 @@ $alpha-black: rgba(0, 0, 0, 1);
pointer-events: none;
}
+.tick-path {
+ fill: none;
+ stroke: red;
+ stroke-width: 6px;
+ pointer-events: none;
+}
+
+.ticks {
+ pointer-events: none;
+ marker {
+ path {
+ fill: blue;
+ }
+ }
+}
+
.base-line {
fill: none;
stroke: black;
diff --git a/src/projection-utility.js b/src/projection-utility.js
index 5f0c9fa..ac37d38 100644
--- a/src/projection-utility.js
+++ b/src/projection-utility.js
@@ -8,7 +8,7 @@ export default class ProjectionUtility {
this._projection = projection;
}
- latLngToSvgPoint(coords) {
+ lngLatToSvgPoint(coords) {
let rate = this._options.offsetRate / 2;
let latLng = new google.maps.LatLng(coords[1], coords[0]);
let svgPoint = this._projection.fromLatLngToDivPixel(latLng);
@@ -29,7 +29,7 @@ export default class ProjectionUtility {
);
}
- latLngToContainerPoint(coords) {
+ lngLatToContainerPoint(coords) {
return this._projection.fromLatLngToContainerPixel(
new google.maps.LatLng(coords[1], coords[0])
);