gpt4 book ai didi

javascript - 在单个通用更新模式中转换圆圈和文本(在 g 元素内)

转载 作者:行者123 更新时间:2023-11-30 20:10:11 25 4
gpt4 key购买 nike

重构我在大约 30 分钟前发布的问题以使其变得更好。我有以下代码,它使用一般更新模式在屏幕上移动圆圈和文本。

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"
}
}


pointsLayer
.selectAll("circle")
.data(myData)
.exit()
.transition()
.duration(100)
.attr('r', 0)
.remove();

pointsLayer
.selectAll("circle")
.data(myData)
.enter()
.append("circle")
.attr("cx", d => xShift(d))
.attr("cy", d => yShift(d))
.attr("r", 30)
.attr("fill", d => circleColorChange(d))
// .on("mouseover", ...)
// .on("mouseout", ...)

pointsLayer
.selectAll("circle")
.data(myData)
.transition()
.duration(1000)
.delay((d, i) => i * 0.5)
.attr("cx", d => xShift(d))
.attr("cy", d => yShift(d))
.attr("fill", d => circleColorChange(d))

pointsLayer.selectAll("text").remove('*')
pointsLayer
.selectAll("text")
.data(myData)
.enter()
.append('text')
.attr('x', d => xShift(d))
.attr('y', d => yShift(d))
.text(d => d.letter)
}

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>

目前,我对圈子使用通用的更新模式。对于文本,我只是删除显示的文本并重新绘制它,但是,我打算也使用通用更新模式来滑动文本。

但是,我的应用程序对圆圈具有某些 .on() 鼠标悬停和鼠标移出效果,当我的光标位于圆圈中的文本上方时,这些圆圈会变得困惑,因为我的 .on() 函数是仅放置在我的圆圈元素上。

我想在各自的元素中包含圆圈和文本,因此结构是:

<g> 
<circle>
<text>
</g>

...理想情况下,我希望对 g 元素应用一次通用更新模式,而不是对圆圈和文本各应用一次。然后 .on() 函数也可以放在 g 元素上,我想。

示例中省略了过渡时发生的其他事件,包括使用其他辅助函数(类似于 xShfit、yShift,但用于这些样式)更改圆颜色、半径、笔划等。此外,文本颜色也会在转换过程中发生变化。

根据原始问题中对此的回复,我计划在今天晚些时候和明天详细阅读 D3 文档,以更好地了解与 D3 相关的一般更新模式,但就目前而言,我仍在寻求有关此问题的帮助,希望转发能引起更多关注。

任何帮助重构此代码以便只需要一个通用更新模式来从元素内一起更新圆圈和文本,将不胜感激!!

谢谢!

编辑:使用更改圆圈颜色的函数和另一个(未使用的)函数进行编辑,假设用于更改文本颜色。

EDIT2:也不确定我当前使用的一般更新模式是否总体上是好的/正确的。我使用 exit 和 enter 和 update,但不在任何地方合并(不确定是否需要)...

最佳答案

对于初学者来说,这似乎是一个 XY problem : 如果唯一的问题是标签干扰了鼠标悬停,那就...

.attr("pointer-events", "none")

... 用于文本的选择。

此外,尽管人们通常喜欢将给定节点的所有元素(圆、文本等)放在一个组中,但请记住,这种方法并非没有问题:例如,使用正是您的坐标和圆的半径,当您将文本作为圆的兄弟放在 <g> 中时其他组的一些圈子会覆盖一些文本。

综上所述,组的模式可以是这样的:

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.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", ...)

请注意,我们不会像您在代码中所做的那样(重新)绑定(bind)退出选择的数据。

请记住,此处的所有元素都附加在输入选择中。如果您还需要它们的更新/进入/退出模式,则必须嵌套它。

最后,你说...

I use exit and enter and update, but not merge anywhere (not sure if needed)

您不需要 merge()方法,您可以在没有它的情况下编写任何 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.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>

关于javascript - 在单个通用更新模式中转换圆圈和文本(在 g 元素内),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52487457/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com