得到这段代码:
export default function Chart({ data, changeData}) {
console.log(data);
const ref = useRef();
const createGraph = (data) => {
var margin = { top: 20, right: 20, bottom: 30, left: 40 },
width = 1360 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scaleBand().range([0, width]).padding(0.1);
var y = d3.scaleLinear().range([height, 0]);
var svg = d3
.select(ref.current)
.append("svg")
.attr("id", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(
data.map(function (d) {
return d.name;
})
);
y.domain([
0,
d3.max(data, function (d) {
return d.number;
}),
]);
// append the rectangles for the bar chart
const bars = svg.selectAll().data(data).enter().append("rect");
bars
.attr("class", "bar")
.attr("x", function (d) {
return x(d.name);
})
.attr("width", x.bandwidth())
.attr("y", function (d) {
return y(d.number);
})
.attr("fill", "pink")
.attr("height", function (d) {
return height - y(d.number);
})
.on("mouseenter", function (actual, i) {
d3.select(this).attr("opacity", 0.5);
d3.select(this)
.transition()
.duration(300)
.attr("opacity", 0.6)
.attr("x", (a) => x(a.name) - 5)
.attr("width", x.bandwidth() + 10);
})
.on("mouseleave", function (actual, i) {
d3.select(this).attr("opacity", 1);
d3.select(this)
.transition()
.duration(300)
.attr("opacity", 1)
.attr("x", (a) => x(a.name))
.attr("width", x.bandwidth());
});
bars
.append("text")
.attr("class", "value")
.attr("x", (a) => x(a.name) + x.bandwidth() / 2)
.attr("y", (a) => y(a.number) + 30)
.attr("fill", "blue")
.attr("text-anchor", "middle")
.text((a) => `${a.number}%`);
d3.selectAll("bars").append("text").attr("class", "divergence");
// add the x Axis
svg
.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg.append("g").call(d3.axisLeft(y));
};
useEffect(() => {
createGraph(data);
}, [data]);
return (
<React.Fragment>
<Filter>
<h2>By</h2>
<span>Popularity</span>
<span onClick={() => changeData()}>Following</span>
</Filter>
<div style={{ marginLeft: "100px" }} ref={ref}></div>
</React.Fragment>
);
}
每个渲染器如何更新数据?
我尝试创建一个删除SVG并添加一个新函数的函数,但是在第一次渲染后位置被弄乱了,我也尝试在useEffect中使用exit()和remove(),但是没有结果。
我想要实现的结果是,我有一个图形,并且数据被提取并传递到此组件中,每当我按下按钮时,数据都会改变。我现在不在看任何动画,我只想看看如何更改数据。
答案 0 :(得分:2)
有点晚了,但以防万一有人在搜索时遇到这个问题。
useEffect(() => {
*// your d3 code here*
instead of using .enter().append('rect')
use .join('rect')
}, [data]) *// runs the d3 code every time the data changes*
更多关于 .join() https://observablehq.com/@d3/selection-join
在 return 语句中指定 svg 和 g 标签。
不要在 div 上使用 ref,而是在 svg 标签上使用 useRef
而不是 .append(g),做 .select('.x-axis') 等
这样你就不会在每次 useEffect 运行时追加新的 g
<svg ref={d3Container}>
<g className="chart">
<g className="x-axis" />
<g className="y-axis" />
</g>
</svg>
在观看本系列的第 1 和第 3 个视频后,我了解到了上述内容https://muratorium.com/using-react-hooks-with-d3