UNPKG

@antv/util

Version:

> AntV 底层依赖的工具库,不建议在自己业务中使用。

69 lines 2.52 kB
import { parsePathString } from '../parser/parse-path-string'; import { normalizePath } from '../process/normalize-path'; import { getPointAtLength } from './get-point-at-length'; import { getPropertiesAtLength } from './get-properties-at-length'; import { getTotalLength } from './get-total-length'; /** * Returns the point and segment in path closest to a given point as well as * the distance to the path stroke. * @see https://bl.ocks.org/mbostock/8027637 */ export function getPropertiesAtPoint(pathInput, point) { var path = parsePathString(pathInput); var normalPath = normalizePath(path); var pathLength = getTotalLength(path); var distanceTo = function (p) { var dx = p.x - point.x; var dy = p.y - point.y; return dx * dx + dy * dy; }; var precision = 8; var scan; var scanDistance = 0; var closest; var bestLength = 0; var bestDistance = Infinity; // linear scan for coarse approximation for (var scanLength = 0; scanLength <= pathLength; scanLength += precision) { scan = getPointAtLength(normalPath, scanLength); scanDistance = distanceTo(scan); if (scanDistance < bestDistance) { closest = scan; bestLength = scanLength; bestDistance = scanDistance; } } // binary search for precise estimate precision /= 2; var before; var after; var beforeLength = 0; var afterLength = 0; var beforeDistance = 0; var afterDistance = 0; while (precision > 0.5) { beforeLength = bestLength - precision; before = getPointAtLength(normalPath, beforeLength); beforeDistance = distanceTo(before); afterLength = bestLength + precision; after = getPointAtLength(normalPath, afterLength); afterDistance = distanceTo(after); if (beforeLength >= 0 && beforeDistance < bestDistance) { closest = before; bestLength = beforeLength; bestDistance = beforeDistance; } else if (afterLength <= pathLength && afterDistance < bestDistance) { closest = after; bestLength = afterLength; bestDistance = afterDistance; } else { precision /= 2; } } var segment = getPropertiesAtLength(path, bestLength); var distance = Math.sqrt(bestDistance); return { closest: closest, distance: distance, segment: segment }; } //# sourceMappingURL=get-properties-at-point.js.map