这是基于先前的帖子I made here的-我正在其中的工作是在嵌套在g元素内的圆和文本元素上实现d3常规更新模式。下面是一个可重现的示例:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
mybutton: "A"
}
}
handleButtonChange = (event) => {
this.setState({
mybutton: event.target.value
});
};
drawPoints() {
const {
mybutton
} = this.state;
const myData = [{
x1: 30,
x2: 140,
y1: 50,
y2: 60,
letter: "A"
},
{
x1: 50,
x2: 150,
y1: 60,
y2: 120,
letter: "B"
},
{
x1: 70,
x2: 120,
y1: 70,
y2: 110,
letter: "C"
}
];
const pointsLayer = d3.select('#my-svg').select('g.points')
const xShift = function(d) {
if (mybutton === "A") {
return d.x1
} else {
return d.x2
}
}
const yShift = function(d) {
if (mybutton === "A") {
return d.y1
} else {
return d.y2
}
}
const textChange = function(d) {
if (mybutton === "A") {
return "white"
} else {
return "black"
}
}
const circleColorChange = function(d) {
if (mybutton === "A") {
return "#FF0000"
} else {
return "#FFAAAA"
}
}
let groups = pointsLayer.selectAll(".myGroups")
.data(myData);
const groupsExit = groups.exit().remove();
const groupsEnter = groups.enter()
.append("g")
.attr("class", "myGroups");
groupsEnter.append("circle")
.attr("r", 20)
.attr("fill", d => circleColorChange(d));
groupsEnter.selectAll("circle")
.transition()
.duration(1000)
.delay((d, i) => i * 0.5)
.attr("fill", d => circleColorChange(d))
groupsEnter.append("text")
.style("text-anchor", "middle")
.style("dominant-baseline", "central")
.text(d => d.letter);
groups = groupsEnter.merge(groups)
.attr("transform", d => "translate(" + xShift(d) + "," + yShift(d) + ")");
// .on("mouseover", ...)
// .on("mouseout", ...)
}
componentDidMount() {
d3.select('#my-svg')
.attr('width', '100%')
.attr('height', '100%')
.attr('viewBox', "0 0 " + (800) + " " + 600)
.attr('preserveAspectRatio', "xMaxYMax")
this.drawPoints();
}
componentDidUpdate() {
this.drawPoints()
}
render() {
const {
mybutton
} = this.state;
return ( <
div >
<
form >
<
div >
<
label >
<
input type = {
"radio"
}
value = {
"A"
}
checked = {
mybutton === "A"
}
onChange = {
this.handleButtonChange
}
/> <
span > {
"A"
} < /span> < /
label > <
/div> <
div >
<
label >
<
input type = {
"radio"
}
value = {
"B"
}
checked = {
mybutton === "B"
}
onChange = {
this.handleButtonChange
}
/> <
span > {
"B"
} < /span> < /
label > <
/div> < /
form >
<
svg id = "my-svg" >
<
g className = "points" / >
<
/svg> < /
div >
);
}
}
ReactDOM.render( <
App / > ,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.development.js"></script>
<div id='root'>
Come On Work!
</div>
上面示例中可能不正确的相关代码行如下:
groupsEnter.selectAll("circle")
.transition()
.duration(1000)
.delay((d, i) => i * 0.5)
.attr("fill", d => circleColorChange(d))
在单击A或B的按钮时,我正在寻求以下行为:
circleColorChange()
函数的颜色变化circleColorChange()
的功能,但显然可以为文本着色对于我的散点图(对于圆/文本的堆叠)而言,圆和文本在g个元素内非常重要。然而,尽管大约30分钟阅读了d3选择文档,但这种转移到带有圆圈/文本的g元素给我实现一般更新模式带来了很多问题。
一如既往,在此感谢您的帮助-非常好奇我在这里做错了什么。
答案 0 :(得分:2)
您基于<p>
组而不是现有组进行了颜色更改更新。我更改为以下内容以更新现有组:
enter()
groups.selectAll("circle")
.transition()
.duration(1000)
.delay((d, i) => i * 0.5)
.attr("fill", d => circleColorChange(d))
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
mybutton: "A"
}
}
handleButtonChange = (event) => {
this.setState({
mybutton: event.target.value
});
};
drawPoints() {
const {
mybutton
} = this.state;
const myData = [{
x1: 30,
x2: 140,
y1: 50,
y2: 60,
letter: "A"
},
{
x1: 50,
x2: 150,
y1: 60,
y2: 120,
letter: "B"
},
{
x1: 70,
x2: 120,
y1: 70,
y2: 110,
letter: "C"
}
];
const pointsLayer = d3.select('#my-svg').select('g.points')
const xShift = function(d) {
if (mybutton === "A") {
return d.x1
} else {
return d.x2
}
}
const yShift = function(d) {
if (mybutton === "A") {
return d.y1
} else {
return d.y2
}
}
const textChange = function(d) {
if (mybutton === "A") {
return "white"
} else {
return "black"
}
}
const circleColorChange = function(d) {
if (mybutton === "A") {
return "#FF0000"
} else {
return "#FFAAAA"
}
}
let groups = pointsLayer.selectAll(".myGroups")
.data(myData);
const groupsExit = groups.exit().remove();
const groupsEnter = groups.enter()
.append("g")
.attr("class", "myGroups");
groupsEnter.append("circle")
.attr("r", 20)
.attr("fill", d => circleColorChange(d));
groups.selectAll("circle")
.transition()
.duration(1000)
.delay((d, i) => i * 0.5)
.attr("fill", d => circleColorChange(d))
groupsEnter.append("text")
.style("text-anchor", "middle")
.style("dominant-baseline", "central")
.text(d => d.letter);
groups = groupsEnter.merge(groups)
.attr("transform", d => "translate(" + xShift(d) + "," + yShift(d) + ")");
// .on("mouseover", ...)
// .on("mouseout", ...)
}
componentDidMount() {
d3.select('#my-svg')
.attr('width', '100%')
.attr('height', '100%')
.attr('viewBox', "0 0 " + (800) + " " + 600)
.attr('preserveAspectRatio', "xMaxYMax")
this.drawPoints();
}
componentDidUpdate() {
this.drawPoints()
}
render() {
const {
mybutton
} = this.state;
return ( <
div >
<
form >
<
div >
<
label >
<
input type = {
"radio"
}
value = {
"A"
}
checked = {
mybutton === "A"
}
onChange = {
this.handleButtonChange
}
/> <
span > {
"A"
} < /span> < /
label > <
/div> <
div >
<
label >
<
input type = {
"radio"
}
value = {
"B"
}
checked = {
mybutton === "B"
}
onChange = {
this.handleButtonChange
}
/> <
span > {
"B"
} < /span> < /
label > <
/div> < /
form >
<
svg id = "my-svg" >
<
g className = "points" / >
<
/svg> < /
div >
);
}
}
ReactDOM.render( <
App / > ,
document.getElementById('root')
);