我是 d3 和 React 的新手,我正在嘗試使用 d3 繪制一個折線圖,其中包含通過異步休息呼叫從后端獲取的資料。當我使用 .csv 檔案中的靜態資料時,它起作用了。但是當我嘗試使用后端資料時,xScale 既不在正確的位置,也不顯示線條。
據我從控制臺輸出中可以看出,當我嘗試繪制線條時,資料已正確格式化和獲取。由于 xScale 或我的線條都不可見,我的猜測是縮放也不再起作用。
編輯:我還注意到,即使我使用 d3.axisBottom,xAxis 也會顯示在頂部
希望可以有人幫幫我。
type ChartDataType = {
timestamp: Date,
value: number
}
const LineChart = ({
width, height, top, right, bottom, left, fill, url, equipmentUUID
}: ZoomBasicLineChartProps) => {
const dispatch = useDispatch<AppDispatch>()
const [data, setData] = useState<ChartDataType[]>()
const title = useRef<string>('Default title, use label')
const containerRef = useRef<HTMLDivElement>()
let container: Selection<SVGGElement, unknown, HTMLElement, unknown>;
let zoom: d3.ZoomBehavior<HTMLDivElement, unknown>;
const chartWidth = width - left - right
const chartHeight = height - top - bottom
let xAxis: Selection<SVGGElement, unknown, HTMLElement, unknown>;
let yAxis: Selection<SVGGElement, unknown, HTMLElement, unknown>;
let path: any;
const diagramDTO = useSelector(LineChartDiagramSelectors.strippedLineChartDiagramData)
const loadStrippedLineChartDiagramData = useCallback(() => {
dispatch(LineChartDiagramDataThunks.getLineChartDiagramDataArray("services/performancemanagement/api/diagram/line-chart/7f5a2e69-0a51-4131-a77f-601ae9de24c6/0/SchlagstatistikGes_VR1?since=148"))
}, [dispatch])
const containerSelection = useMemo(() => (
d3.select<HTMLDivElement, unknown>('#ZoomLineChart')
), [containerRef.current])
const xScale = useMemo(() => {
const domain = data ? d3.extent(data, (d) => d.timestamp) : [new Date(), new Date()]
console.log("domain")
console.log(domain)
return d3
.scaleTime()
.domain([domain[0] ?? new Date(), domain[1] ?? new Date()])
.range([0, width])
}, [data])
const yScale = useMemo(() => {
const domain = data ? d3.extent(data, (d) => d.value) : [0, 0]
return d3
.scaleLinear()
.domain([domain[0] ?? 0, domain[1] ?? 0])
.range([height, 0])
}, [data])
const initSvg = (): SelectionType => (
containerSelection
.append('svg')
.attr('width', chartWidth left right)
.attr('height', chartHeight top bottom 75)
.append('g')
.attr('transform', `translate(${left},${top})`)
)
const drawAxes = (g: SelectionType): void => {
xAxis = g.append('g')
.call(d3.axisBottom(xScale))
yAxis = g.append('g')
.call(d3.axisLeft(yScale))
}
const drawLabel = (g: SelectionType): void => {
g.append('text')
.attr('text-anchor', 'start')
.attr('y', height 40)
.attr('x', 0)
.text(title.current)
}
const drawLines = (g: SelectionType): void => {
if (data) {
const lines = d3.line<ChartDataType>()
.x(d => {
// console.log(d.timestamp)
return xScale(d.timestamp)
})
.y(d => {
// console.log(d.value)
return yScale(d.value)
})
console.log("data")
console.log(data)
path = g
.append('g')
.attr('clip-path', "url(#clip)")
.append('path')
.datum(data)
.attr('class', 'line')
.attr('fill', 'none')
.attr('stroke', fill)
.attr('stroke-width', 1.5)
.attr('d', lines)
}
}
function updateChart(event: any) {
const {transform} = event;
const newX = transform.rescaleX(xScale);
xAxis.call(d3.axisBottom(newX));
path.attr("d", d3.line<ChartDataType>()
.x(d => newX(d.timestamp))
.y(d => yScale(d.value)));
}
const clip = (g: SelectionType): void => {
g.append("defs")
.append("SVG:clipPath")
.attr("id", "clip")
.append("SVG:rect")
.attr("width", width)
.attr("height", height)
.attr("x", 0)
.attr("y", 0);
}
const initZoom = (g: SelectionType): void => {
zoom = d3.zoom<HTMLDivElement, unknown>()
.scaleExtent([0.5, 5])
.on('zoom', updateChart)
containerSelection.call(zoom)
}
// Parse into data object
useEffect(() => {
if (diagramDTO) {
const updatedData = diagramDTO.payload?.map(dataPoint => {
const value = dataPoint.value
return {timestamp: dataPoint.timestamp, value}
})
setData(updatedData)
} else {
loadStrippedLineChartDiagramData()
}
}, [diagramDTO])
useEffect(() => {
container = initSvg();
initZoom(container)
clip(container)
drawAxes(container)
drawLines(container)
drawLabel(container)
}, [data])
return (
<>
<Box id='ZoomLineChart' ref={containerRef}/>
</>
)
}
示例資料播放負載:
{
"unit" : "unit.schlagstatistikges_vr1",
"label" : "label.schlagstatistikges_vr1",
"payload" : [ {
"timestamp" : "2022-06-08T03:22:00Z",
"value" : "10676"
}, {
"timestamp" : "2022-06-08T03:23:00Z",
"value" : "10583"
}, {
"timestamp" : "2022-06-08T03:24:00Z",
"value" : "10647"
}, {
"timestamp" : "2022-06-08T03:25:00Z",
"value" : "10585"
}, {
"timestamp" : "2022-06-08T03:26:00Z",
"value" : "10644"
}, {
"timestamp" : "2022-06-08T03:27:00Z",
"value" : "10227"
}, {
"timestamp" : "2022-06-08T03:28:00Z",
"value" : "10620"
}, {
"timestamp" : "2022-06-08T03:29:00Z",
"value" : "10635"
}, {
"timestamp" : "2022-06-08T03:30:00Z",
"value" : "10432"
}, {
"timestamp" : "2022-06-08T03:31:00Z",
"value" : "10295"
}, {
"timestamp" : "2022-06-08T03:32:00Z",
"value" : "10674"
}, {
"timestamp" : "2022-06-08T03:33:00Z",
"value" : "10715"
}, {
"timestamp" : "2022-06-08T03:34:00Z",
"value" : "10068"
}, {
"timestamp" : "2022-06-08T03:35:00Z",
"value" : "10262"
}, {
"timestamp" : "2022-06-08T03:36:00Z",
"value" : "10926"
}, {
"timestamp" : "2022-06-08T03:37:00Z",
"value" : "10271"
}, {
"timestamp" : "2022-06-08T03:38:00Z",
"value" : "10870"
} ],
"color" : "#80BEBF"
}
uj5u.com熱心網友回復:
我發現了問題:我的 IDE 識別了日期物件,但 d3 需要一個明確的時間分析:
const updatedData = diagramDTO.payload?.map(dataPoint => {
const parser = d3.timeParse('%Y-%m-%dT%H:%M:%S.%LZ')
const timestamp = parser(String(dataPoint.timestamp))!
const value = dataPoint.value
return {timestamp, value}
})
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/494554.html
上一篇:如何理解isNaN
