React Native中使用d3-shape如何根据X值获取路径对应Y值
React Native 中使用D3实现指定X值匹配路径Y值的方案
之前调用react-native-redash提供的getYForX失效,核心原因有两点:
- 生成路径时使用了
shape.curveBasis三次贝塞尔曲线插值,redash内置的getYForX默认按直线段做插值计算,没有适配贝塞尔曲线的分段采样逻辑,计算结果天然存在偏差 - 自定义了带
Extrapolate.CLAMP的缩放逻辑,且Y轴做了翻转处理(range.y 配置为[height, 0]),和redash内置的坐标映射规则不匹配,直接调用会出现坐标错位。
可直接落地的实现代码
不需要额外引入依赖,基于现有代码逻辑扩展即可:
/** * 从解析后的SVG路径中,根据屏幕坐标X查找对应屏幕坐标Y * @param parsedPath parsePath解析后的路径对象 * @param targetX 目标屏幕X坐标 * @param precision 匹配精度,默认0.5px * @returns 匹配到的屏幕Y坐标,超出范围返回边界值 */ const getPathYForScreenX = (parsedPath, targetX, precision = 0.5) => { 'worklet' let currentPath = parsedPath let lastPoint = null // 遍历所有路径段 while (currentPath) { const segments = currentPath.curves for (const segment of segments) { const segMinX = Math.min(segment.from.x, segment.to.x) const segMaxX = Math.max(segment.from.x, segment.to.x) // 定位目标X所在的曲线段 if (targetX >= segMinX && targetX <= segMaxX) { // 二分法在三次贝塞尔曲线上查找匹配点,精度可控 let tMin = 0 let tMax = 1 let matchY = null while (tMax - tMin > 0.001) { const t = (tMin + tMax) / 2 const mt = 1 - t // 三次贝塞尔坐标公式 const currentX = mt**3 * segment.from.x + 3 * mt**2 * t * segment.c1.x + 3 * mt * t**2 * segment.c2.x + t**3 * segment.to.x const currentY = mt**3 * segment.from.y + 3 * mt**2 * t * segment.c1.y + 3 * mt * t**2 * segment.c2.y + t**3 * segment.to.y if (Math.abs(currentX - targetX) < precision) { matchY = currentY break } currentX < targetX ? (tMin = t) : (tMax = t) } return matchY } lastPoint = { x: segment.to.x, y: segment.to.y } } currentPath = currentPath.next } // 超出路径X范围时返回边界Y值 if (targetX <= 0) return parsedPath.curves?.[0]?.from.y ?? null return lastPoint?.y ?? null } // 业务调用入口:输入原始数据域的X值,返回原始数据域的对应Y值 const getYByOriginalX = (originalX) => { 'worklet' // 原始X转屏幕坐标X const screenX = scale(originalX, domain.x, range.x) // 查找屏幕坐标Y const screenY = getPathYForScreenX(path, screenX) if (screenY === null) return null // 屏幕Y转回原始数据域Y值 return scaleInvert(screenY, domain.y, range.y) }
使用说明
- 该方法完全适配现有的worklet、缩放、Y轴翻转逻辑,可以直接在重绘、手势回调里同步调用
- 精度参数
precision可以根据业务需求调整,数值越小精度越高,计算耗时略有增加,一般设为0.5-1即可满足绝大多数图表场景 - 如果后续更换曲线类型(比如
curveMonotoneX、curveCatmullRom),只需要替换贝塞尔坐标计算部分的公式,整体分段匹配+二分查找的逻辑不需要改动
内容的提问来源于stack exchange,提问作者Rafael Augusto
相关产品推荐
相关产品推荐

