基于D3.js创建带日期范围的时间线条形图技术问询
D3.js 实现指定日期范围的双轴日期标记图
核心实现步骤
1. 初始化基础配置与比例尺
先处理日期格式并定义核心比例尺:
- 日期解析:用
d3.timeParse将字符串日期转为可计算的Date对象,保证时区解析准确 - X轴时间比例尺:基于指定起止日期生成连续时间轴,同时生成20个均匀分布的中间日期刻度
- Y轴分类比例尺:绑定
Actual和Scheduled两个静态分类,分配垂直位置
// 匹配输入ISO格式的日期解析器 const parseDate = d3.timeParse("%Y-%m-%dT%H:%M:%S%Z"); // 解析起止日期 const startDate = parseDate(this.startEndDateXAxis[0]); const endDate = parseDate(this.startEndDateXAxis[1]); // X轴时间比例尺 const xScale = d3.scaleTime() .domain([startDate, endDate]) .range([margin.left, width - margin.right]); // 生成20个均匀分布的中间日期刻度 const xTicks = d3.range(0, 20).map(i => { const fraction = i / 19; // 20个点对应19个间隔 return new Date(startDate.getTime() + fraction * (endDate.getTime() - startDate.getTime())); }); // Y轴分类比例尺 const yScale = d3.scaleBand() .domain(['Actual', 'Scheduled']) .range([margin.top, height - margin.bottom]) .padding(0.3); // 控制两个分类的垂直间距
2. 绘制坐标轴
将配置好的比例尺绑定到坐标轴组件,添加到SVG容器:
// 创建X轴 const xAxis = d3.axisBottom(xScale) .tickValues(xTicks) // 使用自定义的20个刻度 .tickFormat(d3.timeFormat("%m/%d %H:%M")); // 自定义日期显示格式 svg.append("g") .attr("transform", `translate(0, ${height - margin.bottom})`) .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", ".15em") .attr("transform", "rotate(-45)"); // 旋转标签避免重叠 // 创建Y轴 const yAxis = d3.axisLeft(yScale); svg.append("g") .attr("transform", `translate(${margin.left}, 0)`) .call(yAxis);
3. 绘制Actual/Scheduled日期标记线
遍历数据,在对应位置绘制2px宽度的垂直标记线:
// 绘制Actual日期标记 svg.selectAll(".actual-mark") .data(this.timelineData) .enter() .append("line") .attr("class", "actual-mark") .attr("x1", d => xScale(parseDate(d.actualDate))) .attr("x2", d => xScale(parseDate(d.actualDate))) .attr("y1", yScale('Actual')) .attr("y2", yScale('Actual') + yScale.bandwidth()) .attr("stroke", "#2ecc71") // 绿色标记Actual .attr("stroke-width", 2); // 绘制Scheduled日期标记 svg.selectAll(".scheduled-mark") .data(this.timelineData) .enter() .append("line") .attr("class", "scheduled-mark") .attr("x1", d => xScale(parseDate(d.scheduledDate))) .attr("x2", d => xScale(parseDate(d.scheduledDate))) .attr("y1", yScale('Scheduled')) .attr("y2", yScale('Scheduled') + yScale.bandwidth()) .attr("stroke", "#3498db") // 蓝色标记Scheduled .attr("stroke-width", 2);
关键注意事项
- 时区处理:输入日期带时区偏移时,确保
d3.timeParse格式字符串包含%Z,避免解析偏差 - SVG布局:提前定义
margin、width、height变量,预留足够边距显示坐标轴标签 - 样式自定义:可通过CSS类控制标记线的颜色、宽度,或添加hover效果增强交互性
内容的提问来源于stack exchange,提问作者Mouad Ennaciri
相关产品推荐
相关产品推荐

