D3.js .打开(“拖动”,拖动) 。在(“结束”,dragended)); 函数dragstarted(d){ d3.选择(this).raise().classed(“活动”,true); } 函数(d){ d3.选择(this).attr(“cx”,d.x=d3.event.x).attr(“cy”,d.y=d3.event.y); } 函数d(d){ d3.选择(此).classed(“活动”,false); } var lastIndex=0; var click=function(){ if(d3.event.defaultPrevented)返回; var p=d3.鼠标(此), x=p[0], y=p[1]; 圆[++lastIndex]={x:x,y:y}; append('circle') .基准面(圆[lastIndex]) .attr('cx',x) .attr('cy',y) .attr('r',半径) .style(“fill”,函数(d,i){返回颜色(lastIndex);}) .call(d3.drag() .on(“开始”,拖动开始) .打开(“拖动”,拖动) 。在(“结束”,dragended)); }; svg.on('click',click);
这是Gerardo Furtado的正确补充,既不是替代品,也不是替代品。我决定提供更多的信息,并分享我对这一点的看法 正如Gerardo所指出的,您认为新添加的圆的拖动行为不活动的假设是错误的。拖动行为已成功附着,并且即使对于新圆也是活动的。但是,D3.js .打开(“拖动”,拖动) 。在(“结束”,dragended)); 函数dragstarted(d){ d3.选择(this).raise().classed(“活动”,true); } 函数(d){ d3.选择(this).attr(“cx”,d.x=d3.event.x).attr(“cy”,d.y=d3.event.y); } 函数d(d){ d3.选择(此).classed(“活动”,false); } var lastIndex=0; var click=function(){ if(d3.event.defaultPrevented)返回; var p=d3.鼠标(此), x=p[0], y=p[1]; 圆[++lastIndex]={x:x,y:y}; append('circle') .基准面(圆[lastIndex]) .attr('cx',x) .attr('cy',y) .attr('r',半径) .style(“fill”,函数(d,i){返回颜色(lastIndex);}) .call(d3.drag() .on(“开始”,拖动开始) .打开(“拖动”,拖动) 。在(“结束”,dragended)); }; svg.on('click',click);,d3.js,D3.js,这是Gerardo Furtado的正确补充,既不是替代品,也不是替代品。我决定提供更多的信息,并分享我对这一点的看法 正如Gerardo所指出的,您认为新添加的圆的拖动行为不活动的假设是错误的。拖动行为已成功附着,并且即使对于新圆也是活动的。但是,draugd()函数将中断,因为它试图访问和分配绑定到被拖动圆的数据。因为新添加的圆没有数据绑定到它们,这将导致一个错误,导致拖动行为不适用于这些圆。正如Gerardo所建议的,有两种方法可以解决这个问题,一种是使用.datum()将数据绑定到新的圆
draugd()
函数将中断,因为它试图访问和分配绑定到被拖动圆的数据。因为新添加的圆没有数据绑定到它们,这将导致一个错误,导致拖动行为不适用于这些圆。正如Gerardo所建议的,有两种方法可以解决这个问题,一种是使用.datum()
将数据绑定到新的圆,另一种是取消拖动处理程序函数中的数据访问
虽然这两种方法都可以,但我更喜欢后者,因为它简单。如果除了跟踪圆的位置外,不需要任何其他目的的数据,则无需保持此模型的最新状态。因为SVGs DOM隐式地携带DOM中的定位信息,所以不需要在模型中显式地复制此信息,即在绑定到DOM元素的数据中
在图元上打印时,您肯定需要使用模型来跟踪位置更改。画布更像是一种“先画后忘”的方法,它不受分层DOM的支持。与SVG相比,它没有独特的、可选择的元素的内置概念,因此缺乏对将数据绑定到元素的支持。为了能够跟踪元素,您必须自己提供支持此视图的模型
我认为,牢记这一差异,可以更深入地了解为什么数据更新会进入链接示例,尽管Mike Bostock以其相当简洁的代码而闻名。但是块也链接到,这使用画布做同样的事情。请注意,这两个块是在同一天设置的,SVG演示,即圆圈拖动i,似乎从画布示例中得到了一些剩余代码。这是Gerardo Furtado正确的补充,不是替代品,也不是替代品。我决定提供更多的信息,并分享我对这一点的看法 正如Gerardo所指出的,您认为新添加的圆的拖动行为不活动的假设是错误的。拖动行为已成功附着,并且即使对于新圆也是活动的。但是,
draugd()
函数将中断,因为它试图访问和分配绑定到被拖动圆的数据。因为新添加的圆没有数据绑定到它们,这将导致一个错误,导致拖动行为不适用于这些圆。正如Gerardo所建议的,有两种方法可以解决这个问题,一种是使用.datum()
将数据绑定到新的圆,另一种是取消拖动处理程序函数中的数据访问
虽然这两种方法都可以,但我更喜欢后者,因为它简单。如果除了跟踪圆的位置外,不需要任何其他目的的数据,则无需保持此模型的最新状态。因为SVGs DOM隐式地携带DOM中的定位信息,所以不需要在模型中显式地复制此信息,即在绑定到DOM元素的数据中
在图元上打印时,您肯定需要使用模型来跟踪位置更改。画布更像是一种“先画后忘”的方法,它不受分层DOM的支持。与SVG相比,它没有独特的、可选择的元素的内置概念,因此缺乏对将数据绑定到元素的支持。为了能够跟踪元素,您必须自己提供支持此视图的模型
我认为,牢记这一差异,可以更深入地了解为什么数据更新会进入链接示例,尽管Mike Bostock以其相当简洁的代码而闻名。但是块也链接到,这使用画布做同样的事情。请注意,这两个块是在同一天设置的,SVG演示(即圆形拖动i)似乎从画布示例中得到了一些剩余代码。您的想法有点不正确。仅包含新引入的记录,以前未被
d3
跟踪。它并不是包含每一条记录。@MatthewHerbst我明白你的意思。但是为了找到这些额外的元素,D3将圆的元素与现有的SVG圆进行匹配。让我换一种说法。假设circles
最初为空,因此初始的svg.selectAll(“circle”).data(circles)
变得多余,我们是否能够通过svg.append('circle')…调用(d3.drag().on…`并获得正确的sync-i
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.active {
stroke: #000;
stroke-width: 2px;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
radius = 32;
var circles = [
{x: 100, y: 100},
{x: 100, y: 200},
{x: 100, y: 300}
];
var lastIndex = 2;
var color = d3.scaleOrdinal()
.range(d3.schemeCategory20);
svg.selectAll("circle")
.data(circles)
.enter().append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", radius)
.style("fill", function(d, i) { return color(i); })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
function dragstarted(d) {
d3.select(this).raise().classed("active", true);
}
function dragged(d) {
d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}
function dragended(d) {
d3.select(this).classed("active", false);
}
//----------------Addition----------------
var click = function() {
if (d3.event.defaultPrevented) return;
var p = d3.mouse(this),
x = p[0],
y = p[1];
circles[++lastIndex] = {x: x, y: y};
svg.append('circle')
.attr('cx', x)
.attr('cy', y)
.attr('r', radius)
.style("fill", function(d, i) { return color(lastIndex); })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
};
svg.on('click', click);
</script>
svg.append('circle')
.datum(circles[lastIndex])
//etc...