我是 d3 的新手,從 Urvashi 女士鏈接這里找到了這個教程
我現在可以看到繪制的折線圖,但是滑鼠工具提示會導致未定義的錯誤。它是未定義的,無法找到其根本原因,因為即使 console.log() 顯示未定義,資料也是完全隨機生成的。
所以這是錯誤:
TypeError: Cannot read properties of undefined (reading 'label')
SVGRectElement.mousemove
http://localhost:3000/static/js/main.chunk.js:269:54
266 | const x0 = bisect(data, xScale.invert(xPos));
267 | const d0 = data[x0];
268 | console.log(data[x0]);
> 269 | focus.attr('transform', `translate(${xScale(d0.label)},${yScale(d0.value)})`);
| ^ 270 | tooltip.transition().duration(300).style('opacity', 0.9);
271 | tooltip.html(d0.tooltipContent || d0.label).style('transform', `translate(${xScale(d0.label) 30}px,${yScale(d0.value) - 30}px)`);
272 | } // d3.select('#container')
我一直在試圖弄清楚為什么引數 d 及其屬性未定義,但是除非懸停在圖形上,否則圖形會呈現。
這是原始代碼:
import React, { useEffect } from 'react';
import './Linechart.scss';
import * as d3 from 'd3';
const Linechart = (props) => {
const { data, width, height } = props;
useEffect(() => {
drawChart();
}, [data])
const drawChart = () => {
//clears previous chart render
d3.select('#container')
.select('svg')
.remove();
d3.select('#container')
.select('.tooltip')
.remove();
const margin = { top: 50, right: 50, bottom: 50, left: 50 };
const yMinValue = d3.min(data, d => d.value);
const yMaxValue = d3.max(data, d => d.value);
const xMinValue = d3.min(data, d => d.label);
const xMaxValue = d3.max(data, d => d.label);
const svg = d3
.select('#container')
.append('svg')
.attr('width', width margin.left margin.right)
.attr('height', height margin.top margin.bottom)
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
const xScale = d3 //x-axis
.scaleLinear()
.domain([xMinValue, xMaxValue])
.range([0, width]);
const yScale = d3 //y-axis
.scaleLinear()
.range([height, 0])
.domain([0, yMaxValue]);
const line = d3
.line()
.x(d => xScale(d.label))
.y(d => yScale(d.value))
.curve(d3.curveMonotoneX);
svg
.append('g')
.attr('class', 'grid')
.attr('transform', `translate(0,${height})`)
.call(
d3.axisBottom(xScale)
.tickSize(-height)
.tickFormat(''),
);
svg
.append('g')
.attr('class', 'grid')
.call(
d3.axisLeft(yScale)
.tickSize(-width)
.tickFormat(''),
);
svg
.append('g')
.attr('class', 'x-axis')
.attr('transform', `translate(0,${height})`)
.call(d3.axisBottom().scale(xScale).tickSize(15));
svg
.append('g')
.attr('class', 'y-axis')
.call(d3.axisLeft(yScale));
svg
.append('path')
.datum(data)
.attr('fill', 'none')
.attr('stroke', '#f6c3d0')
.attr('stroke-width', 4)
.attr('class', 'line')
.attr('d', line);
const focus = svg
.append('g')
.attr('class', 'focus')
.style('display', 'none');
focus.append('circle').attr('r', 5).attr('class', 'circle');
const tooltip = d3
.select('#container')
.append('div')
.attr('class', 'tooltip')
.style('opacity', 0);
svg
.append('rect')
.attr('class', 'overlay')
.attr('width', width)
.attr('height', height)
.style('opacity', 0)
.on('mouseover', () => {
focus.style('display', null);
})
.on('mouseout', () => {
tooltip
.transition()
.duration(300)
.style('opacity', 0);
})
.on('mousemove', mousemove);
function mousemove(event) {
const bisect = d3.bisector(d => d.label).left;
const xPos = d3.pointer(this)[0];
const x0 = bisect(data, xScale.invert(xPos));
const d0 = data[x0];
console.log(data[x0]);
focus.attr(
'transform',
`translate(${xScale(d0.label)},${yScale(d0.value)})`,
);
tooltip
.transition()
.duration(300)
.style('opacity', 0.9);
tooltip
.html(d0.tooltipContent || d0.label)
.style(
'transform',
`translate(${xScale(d0.label) 30}px,${yScale(d0.value) - 30}px)`,
);
}
}
return(
<div id="container"></div>
)
}
export default Linechart;
資料是通過這個函式生成的:
const [data, setData] = useState([]);
const regenerateData = () => {
var chartData = [];
for (let index = 0; index < 20; index ) {
var value = Math.floor(Math.random() * index 3);
var dataObject = {
label: index,
value,
tooltipContent:
`<b>x: </b> ${index} <br />
<b>y: </b> ${value}`,
}
chartData.push(dataObject);
}
setData(chartData);
}
如果只是一個引數,為什么還需要定義呢?我對此感到很困惑,我的學習速度有點慢,所以如果我不得不問一些問題,我很抱歉。
uj5u.com熱心網友回復:
找到了,最后在無數的 console.log() 之后我才能夠弄清楚。
const xPos = d3.pointer(this)[0];
const x0 = bisect(data, xScale.invert(xPos));
似乎這是一種舊方法,我只是碰巧用指標替換了滑鼠以進行遷移,但是當我 console.log(xPos) 時,它只是拋出 undefined 像為什么?基本上只需要這樣。
const xPos = d3.pointer(event);
const x0 = bisect(data, xScale.invert(xPos[0]));
const d0 = data[x0];
現在工具提示圓圈顯示在帶有自動識別坐標的懸停上。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/326036.html
標籤:d3.js
