如何在 d3.js 转换中正确更新输入元素的文本值

use*_*696 2 javascript events input transitions d3.js

我一直在尝试,一步一步地,在 d3.js 可视化中为动态动画转换一些非常漂亮但静态和非 d3 的代码

(虽然与这个问题没有直接关系,但原始代码“只是”-haha- 接受用户提供的和弦名称,例如“Amaj7”,将其分解为组件音符并显示相关波形。我正在尝试创建一个基于和弦名称数组的过渡驱动动画。)

就我而言,对于实现的每次成功的代码更新(到 d3.js 友好版本),源代码都被保存起来作为与下一个的工作比较。

在代码的当前更新中,我在尝试合并转换时遇到了一个小故障。转换本身得到了很好的证明,并且(通过日志记录)可以看到按预期触发。

在转换期间,所需的属性值更改(要处理的下一个和弦名称以及立即转换的目标)失败。将以前的(工作)版本与当前版本进行比较:

初始创建,两者通用,但在一个单独的文件中,因此元素只能通过 DOM 访问

var input = container
.append("input")
.attr("class", wavebase.animation_type + "_input")
.attr("id", "chordinput")
.attr("type", "text")
.attr("value","Amaj7");
Run Code Online (Sandbox Code Playgroud)

老的

var input = document.getElementById('chordinput');

input.addEventListener('change', inputChanged, false);
inputChanged.call(input);
Run Code Online (Sandbox Code Playgroud)

和(过渡前):

input.setAttribute("value", (waveplot.chordname + "\x0A")); 
inputChanged.call(input);
Run Code Online (Sandbox Code Playgroud)

让我们明确一点:上述工作

新的

var input = container
.select("#chordinput")

input.on('change', inputChanged, false);
inputChanged.call(input);
Run Code Online (Sandbox Code Playgroud)

后来,既不是这个:

input
.transition()
.text(function() {
    return (waveplot.chordname + "\x0A");
})
Run Code Online (Sandbox Code Playgroud)

..也不是这个:

input
.transition()
.attr("value", function() {
    return (waveplot.chordname + "\x0A");
});
Run Code Online (Sandbox Code Playgroud)

..nor 变体减去返回字符 ("\x0A") 会导致更新输入元素的值字段。顺便说一下,waveplot.chordname 总是正确定义的。

鉴于在新代码中甚至无法识别原始的 Amaj7,我的直觉是问题出在该行上

input.on('change', inputChanged, false);
Run Code Online (Sandbox Code Playgroud)

显然,在进行转换时,我的目标是使用这条线捕获多个事件。我做错了什么,或者做错了什么?例如,我是否必须使用不同的触发器(“提交”和“点击”都没有任何影响),使用 d3.dispatch(),甚至将每个事件映射到它自己的 ('change.n') 处理程序?

注意:就像我想在 jsfiddle 之类的东西中演示这个一样,整个事情都嵌入在一个框架中,也就是目前不切实际..

谢谢暴徒

Ame*_*aBR 6

这里发生了几件事情,它们都与 d3 没有直接关系。但是,在修复代码时也有一些与 d3 相关的事情需要注意,所以我在下面用斜体表示了它们。

首先,设置对.text()无效<input>,因为它改变了.textContent属性(被忽略——输入元素为空)。

即使您transition().text()在有效的文本容器元素上使用,您也不会看到“过渡”——文本会在过渡延迟后立即发生变化。

其次,value 属性输入的是一样的value 属性(即,element.value)。在任何用户脚本交互之前,属性(这是您要包含在标记中的内容)定义输入元素的初始值。在页面加载后更改它不起作用。相反,该属性定义字段的当前值,无论您是在脚本中更改它还是用户通过键入更改它。

看到这个小提琴(它只使用普通的 Javascript,而不是 d3):http :
//fiddle.jshell.net/FVF29/

var i = document.getElementById("i");
i = i;
i.setAttribute("value", "Stuff");
i.value="Good Stuff";
i.setAttribute("value", "Other Stuff");
Run Code Online (Sandbox Code Playgroud)

这两个setAttribute调用都不会影响显示——文本框包含“Good Stuff”——尽管如果您检查 DOM,您会看到该属性已更改。

虽然不经常使用,但 d3 有一种方法可以更改选择中元素的元素属性,selection.property(propertyName, valueOrFunction). 但是,转换没有等效的功能。

您可以提出一个有效的功能请求,即应该有一个transition.property()功能。根据您的示例,我当然可以看到它的用途——也许您有一个数字滑块或颜色输入,并且您希望显示的值平滑更改,而不是立即跳转到您设置的值。

但是,在您的情况下,这仍然不能很好地工作。假设属性转换函数的实现与属性或样式转换相同,字符串值的默认转换将字符串分为数字和非数字段。非数字段立即更改,数字过渡。如果您从“Cmin6”更改为“Amaj7”,这将是奇怪且随机的——您最终会得到像“Amaj6.569087098608760876”这样的和弦!

总之:我不知道为什么要使用过渡来更改文本字段,或者您期望中间值是什么。如果您清楚地知道如何计算中间值,请使用直接设置this.value. (有关如何执行此操作的示例,请参阅我为此答案this.textContent创建的小提琴,它使用自定义补间来设置。)否则,跳过过渡并仅使用:

input.property("value", waveplot.chordname);
Run Code Online (Sandbox Code Playgroud)