gpt4 book ai didi

javascript - 如何替换 d3.js 路径元素而不是绘制另一个元素?

转载 作者:行者123 更新时间:2023-12-02 15:29:06 24 4
gpt4 key购买 nike

我正在尝试制作一个折线图小部件,其中有一个预先存在的数据,用户可以通过单击图表上的一个点来添加信息。工作示例是 here .

现在,这些点都显示在我想要的位置,但每次单击都会导致将新线添加到图表中,而不是替换现有线。以下是图表的最初创建方式(基于 D3 in Action 的示例构建):

function lineChart(data) {

//...code setting up x and y axis...//

d3.select("svg").selectAll("circle.tweets")
.data(data)
.enter()
.append("circle")
.attr("class", "tweets")
.attr("r", 10)
.attr("cx", function(d) {return xScale(d.day)})
.attr("cy", function(d) {return yScale(d.tweets)})
.style("fill", "black")

// Here is the mousedown click function as it's set up to add new elements to the data
d3.select("svg")
.on('mousedown', function() {
x = d3.mouse(this)[0];
y = d3.mouse(this)[1];

x_day = ((x-20)/(480-20)*9.5 + 1);
y_day = 35 - ((y - 20)/(480-20)*35)

tweets.push(new newNode(x_day, y_day, 11, 11));
updateData();
});

tweetLine = d3.svg.line()
.interpolate("cardinal")
.x(function(d) {
return xScale(d.day)
})
.y(function(d) {
return yScale(d.tweets)
})

d3.select("svg")
.append("path")
.attr("d", tweetLine(data))
.attr("fill", "none")
.attr("stroke", "darkred")
.attr("stroke-width", 2)

}

这是图表的 mousedown 函数,理想情况下会添加新点并相应地重新绘制图表:

function updateData(){
d3.select("svg").selectAll("circle.tweets")
.data(tweets)
.enter()
.append("circle")
.attr("class", "tweets")
.attr("r", function(d) { console.log("doing data for " + d.day); return 10;})
.attr("cx", function(d) {return xScale(d.day)})
.attr("cy", function(d) {return yScale(d.tweets)})
.style("fill", "black")
.on('mousedown', function(d) {console.log(d);});

tweets.sort(function(a, b){
return a.day - b.day;
})

d3.select("path.line").remove();
tweetLine = d3.svg.line()
.interpolate("cardinal")
.x(function(d) {
return xScale(d.day)
})
.y(function(d) {
return yScale(d.tweets)
})

d3.select("svg")
.append("path")
.attr("d", tweetLine(tweets))
.attr("fill", "none")
.attr("stroke", "darkred")
.attr("stroke-width", 2)

}

我只想在 tweets 的所有元素中绘制 1 条路径,但现在我的更新函数会为每个点击事件添加一行,而不删除旧行。我在这里做错了什么?为什么 .remove() 调用没有效果?

此外,我尝试重写我的行以按照本文推荐的方式添加它:d3 update data and update graph使用此代码:

tweetLine = d3.svg.line()
.interpolate("cardinal")
.x(function(d) {
return xScale(d.day)
})
.y(function(d) {
return yScale(d.tweets)
})

d3.select("svg")
.selectAll("path.line")
.data(data)
.enter()
.append("svg:path")
.attr("d", tweetLine)
.attr("fill", "none")
.attr("stroke", "darkred")
.attr("stroke-width", 2)

但是这条线根本就没有画出来。以上有什么问题吗?

最佳答案

无需删除线条并重新绘制,只需更新即可。首先,在初次绘制时为其指定一个唯一的类名称,以便于重新选择。然后只需执行以下操作:

d3.select(".myLine")
.attr("d", tweetLine(tweets));

完整的工作代码:

<!DOCTYPE html>
<html>

<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<style>
svg {
height: 500px;
width: 500px;
border: 1px solid gray;
}
line {
shape-rendering: crispEdges;
stroke: #000000;
}

line.minor {
stroke: #777777;
stroke-dasharray: 2,2;
}

path.domain {
fill: none;
stroke: black;
}

</style>
</head>

<body>
<svg width="480" height="480"></svg>
<script>
var tweets, tweetLine;
assign();

function lineChart(data) {

xScale = d3.scale.linear().domain([1, 10.5]).range([20, 480]);
yScale = d3.scale.linear().domain([0, 35]).range([480, 20]);

xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.tickSize(480)
.tickValues([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

d3.select("svg").append("g").attr("id", "xAxisG").call(xAxis);

yAxis = d3.svg.axis()
.scale(yScale)
.orient("right")
.ticks(10)
.tickSize(480)
.tickSubdivide(true);

d3.select("svg").append("g").attr("id", "yAxisG").call(yAxis);

d3.select("svg").selectAll("circle.tweets")
.data(data)
.enter()
.append("circle")
.attr("class", "tweets")
.attr("r", function(d) {
console.log("doing data for " + d.day);
return 10;
})
.attr("cx", function(d) {
return xScale(d.day)
})
.attr("cy", function(d) {
return yScale(d.tweets)
})
.style("fill", "black")


d3.select("svg")
.on('mousedown', function() {
x = d3.mouse(this)[0];
y = d3.mouse(this)[1];

x_day = ((x - 20) / (480 - 20) * 9.5 + 1);
y_day = 35 - ((y - 20) / (480 - 20) * 35)
console.log("y day is " + y_day);
console.log("x is " + x_day);
tweets.push(new newNode(x_day, y_day, 11, 11));

updateData();
});

tweetLine = d3.svg.line()
.interpolate("cardinal")
.x(function(d) {
return xScale(d.day)
})
.y(function(d) {
return yScale(d.tweets)
})

d3.select("svg")
.append("path")
.attr("class", "myLine")
.attr("d", tweetLine(data))
.attr("fill", "none")
.attr("stroke", "darkred")
.attr("stroke-width", 2)

}

function newNode(day, tweets, retweets, favorites) {
this.day = day;
this.tweets = tweets;
this.retweets = retweets;
this.favorites = favorites;
}


function assign() {
tweets = [{"day":"1","tweets":"1","retweets":"2","favorites":"5"},{"day":"2","tweets":"6","retweets":"11","favorites":"3"},{"day":"3","tweets":"3","retweets":"8","favorites":"1"},{"day":"4","tweets":"5","retweets":"14","favorites":"6"}];
lineChart(tweets);
}

function updateData() {

d3.select("svg").selectAll("circle.tweets")
.data(tweets)
.enter()
.append("circle")
.attr("class", "tweets")
.attr("r", function(d) {
console.log("doing data for " + d.day);
return 10;
})
.attr("cx", function(d) {
return xScale(d.day)
})
.attr("cy", function(d) {
return yScale(d.tweets)
})
.style("fill", "black")
.on('mousedown', function(d) {
console.log(d);
});

tweets.sort(function(a, b) {
return a.day - b.day;
});

d3.select(".myLine")
.attr("d", tweetLine(tweets));

}
</script>
</body>

</html>

关于javascript - 如何替换 d3.js 路径元素而不是绘制另一个元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33482414/

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