D3 scaleTime日期异常:初始显示2034年,缩放后仍不准确
问题分析与修复方案
核心问题
- 自定义滚轮事件覆盖默认缩放行为:自定义的滚轮处理函数重置了平移参数,导致缩放后视图偏离中心日期。
- 平移范围限制过严:
translateExtent设置为 SVG 尺寸范围,导致初始平移参数被强制截断,无法正确居中当前日期。 - 变量命名混淆:
oneYearAgo和oneYearLater实际计算的是前后一个月的日期,易引发逻辑误解。
修复代码
import { useRef, useEffect } from 'react'; import * as d3 from 'd3'; const D3Timeline = () => { const svgRef = useRef<SVGSVGElement>(null); const initializedRef = useRef(false); const height = 100; const width = 600; useEffect(() => { if (initializedRef.current) return; initializedRef.current = true; const svg = d3 .select(svgRef.current) .attr('width', width) .attr('height', height); const now = new Date(); // 修正变量命名,实际为前后一个月的日期 const oneMonthAgo = new Date( now.getFullYear(), now.getMonth() - 1, now.getDate() ); const oneMonthLater = new Date( now.getFullYear(), now.getMonth() + 1, now.getDate() ); const initialStartDate = new Date(now.getTime() - 6 * 60 * 60 * 1000); const initialEndDate = new Date(now.getTime() + 6 * 60 * 60 * 1000); const x = d3 .scaleTime() .domain([oneMonthAgo, oneMonthLater]) .range([0, width]); const xAxisGroup = svg .append('g') .attr('transform', `translate(0,${height - 20})`); svg .append('line') .attr('x1', width / 2) .attr('y1', 0) .attr('x2', width / 2) .attr('y2', height) .attr('stroke', 'red') .attr('stroke-width', 2); const zoom = d3 .zoom() .scaleExtent([1, 200]) // 扩大最大缩放比例以适配初始视图需求 .extent([ [0, 0], [width, height], ]) .on('zoom', zoomed); // 初始轴渲染 xAxisGroup.call( d3 .axisBottom(x) .ticks(width / 80) .tickSizeOuter(0) ); // 计算初始缩放和平移以居中当前日期并显示12小时范围 const initialScale = width / (x(initialEndDate) - x(initialStartDate)); const initialTranslate = -x(now) * initialScale + width / 2; const initialZoom = d3.zoomIdentity .scale(initialScale) .translate(initialTranslate, 0); svg.call(zoom).call(zoom.transform, initialZoom); function zoomed(event) { const transform = event.transform; const xz = transform.rescaleX(x); xAxisGroup.call( d3 .axisBottom(xz) .ticks(width / 80) .tickSizeOuter(0) ); const centerDate = xz.invert(width / 2); console.log(centerDate); } // 移除自定义滚轮处理,使用D3默认缩放行为 }, []); return <svg ref={svgRef}></svg>; };
修复说明
- 移除自定义滚轮事件:D3 的
zoom行为已内置滚轮处理,可正确保留平移参数并围绕鼠标位置缩放,避免视图跳转。 - 删除
translateExtent:取消平移范围限制,允许初始平移参数生效,确保视图居中当前日期。 - 调整缩放范围:将最大缩放比例从 365 提高到 200,确保初始缩放比例(约120)在允许范围内,避免被强制截断。
- 修正变量命名:将
oneYearAgo/oneYearLater改为oneMonthAgo/oneMonthLater,匹配实际逻辑,避免混淆。
内容的提问来源于stack exchange,提问作者Fabiot
相关产品推荐
相关产品推荐

