React中基于D3.js绘制部件操作时间轴图表的技术求助
技术求助:React中用D3.js实现分层甘特图
我需要基于以下数据,用D3.js在React中实现一个图表:
export const graphData = [ { part_number: "N3241Z", serial_number: "40615705", date: "2022-12-16T00:00:00", part_desc: "PANEL ASSY, MODE CONTROL", action: "installed", description: "", service_bulletin: "SB-787-22-0002-03--.pdf", }, { part_number: "N3241AZ", serial_number: "40615705", date: "2022-12-16T00:00:00", part_desc: "PANEL ASSY, MODE CONTROL", action: "installed", description: "", service_bulletin: "SB-787-22-0002-03--.pdf", }, { part_number: "N3241AZ", serial_number: "40615705", date: "2022-12-16T00:00:00", part_desc: "PANEL ASSY, MODE CONTROL", action: "removed", description: "", service_bulletin: "SB-787-22-0002-03--.pdf", }, { part_number: "N3241AZ", serial_number: "40615705", date: "2022-12-16T00:00:00", part_desc: "PANEL ASSY, MODE CONTROL", action: "wo_created", description: "", service_bulletin: "SB-787-22-0002-03--.pdf", }, { part_number: "N3241ZX", serial_number: "40615705", date: "2022-12-16T00:00:00", part_desc: "PANEL ASSY, MODE CONTROL", action: "installed", description: "", service_bulletin: "SB-787-22-0002-03--.pdf", }, { part_number: "N3241TZ", serial_number: "40615705", date: "2022-12-16T00:00:00", part_desc: "PANEL ASSY, MODE CONTROL", action: "wo_created", description: "", service_bulletin: "SB-787-22-0002-03--.pdf", }, { part_number: "N3241TZCD", serial_number: "40615705", date: "2022-12-16T00:00:00", part_desc: "PANEL ASSY, MODE CONTROL", action: "wo_created", description: "", service_bulletin: "SB-787-22-0002-03--.pdf", }, ];
需求说明
- Y轴为日期,X轴为
part_number - 不同的
action按层级(zIndex)展示,同一part_number和日期下可以对应多个不同action - 我是D3.js新手,期望实现的UI效果是同一单元格内多个action元素分层排列的甘特图样式
以下是我目前的实现代码,请求技术帮助:
import { useEffect, useState, useRef, useCallback, useLayoutEffect, } from 'react'; import { Flex } from '@core-ui/components'; // eslint-disable-next-line import/no-extraneous-dependencies import * as d3 from 'd3'; import { ASSET_ACTIONS } from '../../util/types'; interface GanttChartProps { readonly uniqueAssets: any[]; readonly filteredTableData: any[]; readonly filteredData: any[]; readonly themeVariant: string; readonly selectedElements: number[]; } const getCodeChipColor = (code: string) => { switch (code) { case ASSET_ACTIONS.INSTALL: return '#DB9C09'; case ASSET_ACTIONS.FAULTCODE: return '#CC4948'; case ASSET_ACTIONS.REMOVED: return '#4BABBF'; case ASSET_ACTIONS.WO_CREATED: return '#4CAF80'; default: return null; } }; export const GanttChart: React.FC<GanttChartProps> = ({ uniqueAssets, filteredTableData, filteredData, themeVariant, selectedElements, }) => { const svgRef = useRef<any>(null); const visibleAssets = selectedElements.map( (index: number) => uniqueAssets[index], ); const uniqueDates = filteredTableData.map(d => d.date); useLayoutEffect(() => { console.log(selectedElements); const margin = { top: 20, right: 20, bottom: 30, left: 100 }; const width = 1000 - margin.left - margin.right; const height = 900 - margin.top - margin.bottom; const svg = d3 .select(svgRef.current) .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom) .append('g') .attr('transform', `translate(${margin.left},${margin.top})`); const x: any = d3.scaleBand().range([0, width]).padding(0.1); const y: any = d3.scaleBand().range([0, height]).padding(0.1); const xAxis = d3.axisTop(x).tickSize(0); const yAxis = d3.axisLeft(y).tickSize(0); // Update scales and axes with new data x.domain(visibleAssets); y.domain(uniqueDates); svg.append('g').call(xAxis).selectAll('.tick text'); svg.append('g').call(yAxis); const bars = svg.selectAll('.bar').data(filteredData, d => d.part_number); // Remove old bars bars.exit().remove(); // Update existing bars bars .attr('x', d => x(d.part_number)) .attr('y', d => y(d.date)) .attr('width', x.bandwidth()) .style('fill', d => getCodeChipColor(d.action)); // Append new bars bars .enter() .append('rect') .attr('class', 'bar') .attr('x', d => x(d.part_number)) .attr('y', d => y(d.date)) .attr('width', x.bandwidth()) .attr('height', 20) // You can adjust the height of the bars as needed .style('fill', d => getCodeChipColor(d.action)); }, [filteredData, selectedElements, filteredTableData]); return ( <Flex shrink align="center" justify="center" css={{ flexDirection: 'column', width: '100%' }}> <svg ref={svgRef} /> </Flex> ); };
内容的提问来源于stack exchange,提问作者Ravikant Vishwakarma
相关产品推荐
相关产品推荐

