- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我从 Mike Bostock's example of using D3 to create a line drawing tool 中提取了以下代码.
此工具创建拖动行为,使用户能够通过在 SVG Canvas 上拖动来绘制曲线。
当拖动行为开始时,此事件的监听器捕获行为开始的坐标并创建新的 SVG 路径。该监听器还将一个新的监听器附加到在拖动行为继续时触发的事件;此监听器(“拖动”监听器)更新 SVG 路径。这发生在代码行开头:active.attr("d", line)
。
“拖动”监听器如何在没有将坐标数据(作为变量“d”存储在监听器的闭包中)重新绑定(bind)到 SVG 路径的附加行的情况下更新 SVG 路径?
根据我对 d3 工作原理的理解,这个工具不应该工作。相反,必须将:active.attr("d", line)
更改为 active.datum(d).attr("d", line)
。
如有任何帮助,我们将不胜感激!
var line = d3.line()
.curve(d3.curveBasis);
var svg = d3.select("svg")
.call(d3.drag()
.container(function() { return this; })
.subject(function() { var p = [d3.event.x, d3.event.y]; return [p, p]; })
.on("start", dragstarted));
function dragstarted() {
var d = d3.event.subject,
active = svg.append("path").datum(d),
x0 = d3.event.x,
y0 = d3.event.y;
d3.event.on("drag", function() {
var x1 = d3.event.x,
y1 = d3.event.y,
dx = x1 - x0,
dy = y1 - y0;
if (dx * dx + dy * dy > 100) d.push([x0 = x1, y0 = y1]);
else d[d.length - 1] = [x1, y1];
active.attr("d", line);
});
}
<!DOCTYPE html>
<meta charset="utf-8">
<style>
path {
fill: none;
stroke: #000;
stroke-width: 3px;
stroke-linejoin: round;
stroke-linecap: round;
}
</style>
<svg width="960" height="500">
<rect fill="#fff" width="100%" height="100%"></rect>
</svg>
<script src="//d3js.org/d3.v4.min.js"></script>
更新 1:我已经尝试了一个基本的闭包结构(即一个用户启动的闭包,它返回一个类似于用户可以通过控制台调用的“拖动”事件监听器的函数)但我无法复制上面脚本的工作方式。我完全糊涂了。
最佳答案
在此示例中,没有需要重新绑定(bind)的数据更新。事实上,只有一个 datum 在拖动手势期间被修改。当拖动实际开始时,subject由
指定.subject(function() { var p = [d3.event.x, d3.event.y]; return [p, p]; })
被捕获并存储在变量d
中:
var d = d3.event.subject,
从上面两行可以看出,这将作为一个数组开始,其中包含两个定义路径起点和终点的坐标对,它们最初是相同的。
下一行将此单个数据/主题绑定(bind)到为此拖动手势新创建的路径:
active = svg.append("path").datum(d),
请务必记住,变量 d
包含对绑定(bind)到路径的实际数据的引用。当修改 d
时,您实际上是在修改预先绑定(bind)的数据。发生这种情况是因为您正在处理引用。
也就是说,接下来的步骤非常简单,因为在手势期间,坐标数组通过调整坐标值或将新值推送到数组来保持最新。同样,这实际上是在修改绑定(bind)到路径的数据。
最后在路径的d
属性上设置线生成器line
时
active.attr("d", line);
生成器将被调用,隐式传递基准边界的新值,从而生成在手势期间跟随指针移动的路径。
关于javascript - D3 : Using a closure to update a selection without re-binding data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39590283/
我是一名优秀的程序员,十分优秀!