reactjs - 如何在这个 d3 气泡图中输入自己的数据以做出反应?
问题描述
所以在 React 中,我复制并粘贴了一个 d3 气泡图元素,但对 React 了解不多。我使用自己的 json 数据将数据输入到气泡图中。但是,当我运行它时,由于 d.data.Name.substring(0, dr / 3),它给出了“无法从未定义中读取”。我觉得我没有正确定义我的 json 对象(d3.hierachy 和一些函数似乎要求孩子或其他东西),这是我的代码:
路线图列表.json:
[
{
"Name": "Computer Science",
"Count": 4156
},
{
"Name": "Home Economics",
"Count": 689
},
{
"Name": "Venture Capital Investment",
"Count": 890
},
{
"Name": "Fabric design",
"Count": 167
},
{
"Name": "Deep Learning Researchers",
"Count": 812
}
]
顺便说一下,在我的气泡图组件 Bubble.js 中,当我使用状态时,它可以工作,但是由于我想要动态更新,所以我正在使用 this.props.roadmapdata
泡泡.js:
import React, { Component } from "react";
import * as d3 from "d3";
class Bubble extends Component {
constructor(props) {
super(props);
}
componentWillReceiveProps(nextProps) {
d3.select("nodes").remove("nodes");
var diameter = 600;
var color = d3.scaleOrdinal(d3.schemeCategory10);
var bubble = d3
.pack(this.props.RoadmapData)
.size([diameter, diameter])
.padding(1.5);
var svg = d3
.select("body")
.append("svg")
.attr("width", diameter)
.attr("height", diameter)
.attr("class", "bubble");
var node = svg
.selectAll(".node")
.data(this.props.RoadmapData)
.enter()
.filter(function(d) {
return !d.children;
})
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
node.append("title").text(function(d) {
return d.Name + ": " + d.Count;
});
node
.append("circle")
.attr("r", function(d) {
return d.r;
})
.style("fill", function(d, i) {
return color(i);
});
node
.append("text")
.attr("dy", ".2em")
.style("text-anchor", "middle")
.text(function(d) {
return d.data.Name.substring(0, d.r / 3);
})
.attr("font-family", "sans-serif")
.attr("font-size", function(d) {
return d.r / 5;
})
.attr("fill", "white");
node
.append("text")
.attr("dy", "1.3em")
.style("text-anchor", "middle")
.text(function(d) {
return d.data.Count;
})
.attr("font-family", "Gill Sans", "Gill Sans MT")
.attr("font-size", function(d) {
return d.r / 5;
})
.attr("fill", "white");
}
render() {
return <div>{this.node}</div>;
}
}
export default Bubble;
谢谢!
解决方案
这是一个使用气泡图并使用d3.packSiblings做出反应的示例。
<svg>
元素有一个引用,所以当组件被挂载时,你可以使用 d3 来创建/更新/删除元素。
笔记:
dataForPacking
只是一个映射,用于创建 d3 打包所需的属性,例如 r,x,z,然后是您的数据名称、计数。
有一个输入框,用于说明 setState 用新数据更新初始道具数据并重新渲染气泡。有很多更好的方法可以做到这一点,但这是一个好的开始。
const dataJSON = [
{
Name: "Computer Science",
Count: 4156
},
{
Name: "Home Economics",
Count: 689
},
{
Name: "Venture Capital Investment",
Count: 890
},
{
Name: "Fabric design",
Count: 167
},
{
Name: "Deep Learning Researchers",
Count: 812
}
];
const dataForPacking = (data) => {
return {
r: data.Count,
x: 0,
y: 0,
Count: data.Count,
Name: data.Name
};
};
class Bubble extends React.Component {
constructor(props) {
super(props);
this.state = {
width: this.props.size[0],
height: this.props.size[1],
data: this.props.data
};
this.svgRef = React.createRef();
this.drawBubble = this.drawBubble.bind(this);
}
componentDidMount() {
this.drawBubble()
}
componentDidUpdate() {
this.drawBubble()
}
drawBubble = () => {
const svg = d3.select(this.svgRef.current);
svg.select("g").remove();
const diameter = 600;
const color = d3.scaleOrdinal(d3.schemeCategory10);
const circles = svg
.append("g")
.attr("class", "circles")
.attr(
"transform",
`translate(${this.state.width / 2},
${this.state.height / 2})scale(0.02)`
);
const node = circles
.selectAll(".node")
.data(d3.packSiblings(this.state.data))
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
node.append("title").text(function(d) {
return d.Name + ": " + d.Count;
});
node
.append("circle")
.attr("r", function(d) {
return d.r;
})
.style("fill", function(d, i) {
return color(i);
});
node
.append("text")
.attr("dy", ".2em")
.style("text-anchor", "middle")
.text(function(d) {
return d.Name.substring(0, d.r / 3);
})
.attr("font-family", "sans-serif")
.attr("font-size", function(d) {
return d.r / 5;
})
.attr("fill", "white");
node
.append("text")
.attr("dy", "1.3em")
.style("text-anchor", "middle")
.text(function(d) {
return d.Count;
})
.attr("font-family", "Gill Sans", "Gill Sans MT")
.attr("font-size", function(d) {
return d.r / 5;
})
.attr("fill", "white");
};
keyPress = event => {
if (event.key === "Enter") {
const newDataArray = event.currentTarget.value.split(",");
if(!newDataArray[1] || isNaN(newDataArray[1])){
return;
}
const newData = {
Name: newDataArray[0],
Count: Number(newDataArray[1])
};
this.setState(prevState => ({
data: [...prevState.data, dataForPacking(newData)]
}))
event.currentTarget.value = "";
}
};
reset = () => {
this.setState(prevState => ({
data: this.props.data.map(e => dataForPacking(e))
}))
};
render() {
return (
<div>
<span>Name, Count </span>
<input type="text" onKeyPress={this.keyPress} />
<button onClick={this.reset}>reset</button>
<svg
ref={this.svgRef}
width={this.props.size[0]}
height={this.props.size[1]}
/>
</div>
);
}
}
ReactDOM.render(
<Bubble data={dataJSON.map(e=> dataForPacking(e))} size={[600, 200]} />,
document.getElementById("app")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.7.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.7.0/umd/react-dom.production.min.js"></script>
<div id="app"><div>
推荐阅读
- python - 熊猫重新采样数据并获得平均值
- bash - 如何在 AppleScript 变量中保存击键输出?
- python - Python将字符串转换为十六进制然后转换为字节
- terraform - 运行 Terraform apply aws_ecs_task_definition 失败并出现错误:ClientException:角色无效
- linux - 在linux终端中更改多行命令的行
- firebase - 数据更改时 Flutter Firebase 监听运行两次
- c# - 使用 SendGrid v3 发送电子邮件批处理
- c# - 调用 SaveChangesAsync() 时如何找出哪些列违反了哪些约束(和检查)
- python - 如何从文件夹中读取所有文本并将与图像jpg文件同名的txt文件保存在其他文件夹python中
- unix - 经典的 Unix 锁文件:无需竞争即可检测过时的锁