因此,在React中,我复制并粘贴了一个d3气泡图元素,而对React不太了解。我用自己的json数据将数据输入气泡图。但是,当我运行它时,由于d.data.Name.substring(0,d.r / 3),它给出了“无法从未定义中读取”的信息。我觉得我没有正确定义我的json对象(d3.hierachy和某些函数似乎在要求孩子或其他东西),这是我的代码:
RoadmapList.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
Bubble.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;
谢谢!
答案 0 :(得分:0)
以下是使用气泡图并使用d3.packSiblings进行反应的示例。
<svg>
元素具有reference,因此,在安装组件时,可以使用d3创建/更新/删除元素。
注意:
dataForPacking
只是一个映射,用于创建d3打包所需的属性,例如r,x,z,然后是数据名称Count。
有一个输入框,用于说明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>