如何在D3的.join更新机制下添加固定描边无填充圆形
D3.js 实现固定描边圆形不随数据更新变化的方案
问题描述
我是D3.js与JavaScript新手,正在完成期末作业:展示咖啡适宜种植土地在2000年及2050年三种预测场景下的变化。目前已实现通过.join函数绑定数据的动态更新圆形,现需添加基于第一个数据集的固定描边无填充圆形,使其不随数据更新而改变。此前尝试新增draw函数,但因选择所有circle元素导致与原有绘制逻辑冲突,询问是否需通过类来区分元素?
解决方案
是的,通过类名区分不同类型的圆形元素是解决这个冲突的最优方案,具体实现思路:
- 给动态更新的圆形添加专属类(如
.dynamic-circle),给固定基线圆形添加另一类(如.baseline-circle),让D3能精准选择目标元素,避免操作范围重叠。 - 固定描边的基线圆形只需初始化绘制一次,不需要放入点击事件的更新逻辑中,确保它始终保留在画布上。
修改后的完整代码
JavaScript 代码
var data = [ [182.796,142.320,42.862,75.826], [131.2969,107.172,35.247,55.852], [116.3189,90.055,26.828,50.994], [104.1119,75.521,20.914,48.48] ] var canvas = d3.select("body") .append("svg") .attr("width",1500) .attr("height",1000) var marginLeft = 190 var circleOffset = 350 // 初始化绘制固定描边的基线圆形(基于第一个数据集) function drawBaseline(){ canvas.selectAll(".baseline-circle") .data(data[0]) .join("circle") .attr("class", "baseline-circle") .attr("stroke","black") .attr("stroke-width","5") .attr("cy",200) .attr("fill","none") .attr("cx",function(d,i){ return i * circleOffset + marginLeft }) .transition() .delay(300) .attr("r",function(d){ return d }) } // 动态更新的圆形绘制函数(仅操作带.dynamic-circle类的元素) function draw(dataset){ var serie = data.indexOf(dataset) canvas.selectAll(".dynamic-circle") .data(dataset) .join( function(enter){ return enter.append("circle") .attr("class", "dynamic-circle") .transition() .delay(300) }, function(update){ return update.attr("stroke","#00000000") }, function(exit){ return exit.transition() .duration(3000) .attr("r",0) .attr("cy",0) .remove() } ) .attr("stroke-width","5") .attr("cy",200) .attr("fill",function(){ if (serie === 0){ return "green" } else if ( serie === 1){ return "orange" } else if ( serie === 2){ return "red" } else { return "darkred" } }) .attr("opacity",0.5) .attr("cx",function(d,i){ return i * circleOffset + marginLeft }) .transition() .attr("r",10) .attr("r",function(d){ return d }) } // 初始化绘制基线圆形 drawBaseline() // 按钮绑定逻辑 d3.select("#buttons") .selectAll("button") .data(data) .join("button") .html(function(d,i){ if (i === 0){ return "2000" } else if ( i === 1){ return "2050 (Scenario 1)" } else if ( i === 2) { return "2050 (Scenario 2)" } else if ( i === 3) { return "2050 (Scenario 3)" }}) .on("click",function(e,d){ draw(d) })
HTML 代码
<script src="https://d3js.org/d3.v7.min.js"></script> <div id="buttons"> </div>
内容的提问来源于stack exchange,提问作者Yolko
相关产品推荐
相关产品推荐

