如何正确更新d3.js转换中输入元素的文本值 [英] How to correctly update the text value of an input element in a d3.js transition

查看:125
本文介绍了如何正确更新d3.js转换中输入元素的文本值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试,一步一步,转换一些非常好但静态&非d3 代码,用于d3.js可视化中的动态动画。



(尽管与此问题没有直接关系,原始代码简单地-haha-接受用户提供的和弦名称,如Amaj7,将其分解为组件注释,显示关联的波形,我正在尝试基于一系列chordnames创建一个转换驱动的动画。)



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



在当前的更新对于代码,我打了一个尝试纳入转换的故障。过渡本身已被证明很好,(通过记录)可以看出如预期的那样火灾。



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



初始创建,两者共同,但在单独的文件和元素中只能通过DOM访问

  var input = container 
.append(input)
.attr class,wavebase.animation_type +_input)
.attr(id,chordinput)
.attr(type,text)
.attr(值, Amaj7);

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

input.addEventListener('change',inputChanged,false);
inputChanged.call(input);

和(转换前):

  input.setAttribute(value,(waveplot.chordname +\x0A)); 
inputChanged.call(input);

让我们清楚一点:上述作品



  var input = container 
。 select(#chordinput)

input.on('change',inputChanged,false);
inputChanged.call(input);

以后,这两个:

 输入
.transition()
.text(function(){
return(waveplot.chordname +\x0A);
} )

..也不是:

  input 
.transition()
.attr(value,function(){
return(waveplot.chordname +\x0A);
});

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



鉴于原来的Amaj7甚至没有在新的代码中被识别,我的直觉是,问题在于该行

  input.on('change',inputChanged,false); 

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

注意:就像我想像这样一个jsfiddle一样演示这个东西,整个东西都被嵌入在一个框架中,这个时候也是不切实际的..



感谢
Thug

解决方案

这里有几件事情,这两者都不直接与d3有关。但是,在修复代码时,还有一些与d3有关的事情需要注意,所以我以下面的斜体表示。



首先,设置 .text()将无法在< input> ; ,因为它更改了 .textContent 属性(被忽略 - 输入元素为空)。



即使您在有效的文本容器元素上使用了 transition()。text()不会看到转换 - 文本将在转换延迟之后立即更改。



其次, 属性值相同 属性(即 element.value )。在任何用户脚本交互之前,属性(即标记中包含的属性)定义输入元素的初始值。在页面加载后进行更改没有任何效果。相反,该属性定义了字段的当前值,无论您是否在脚本中进行更改,或者用户是否通过键入更改它。



看到这个小提琴(仅使用纯Java,而不是d3):

http://fiddle.jshell .net / FVF29 /

  var i = document.getElementById(i); 
i = i;
i.setAttribute(value,Stuff);
i.value =好东西;
i.setAttribute(value,Other Stuff);

setAttribute 调用影响显示 - 文本框包含好东西 - 虽然如果您检查DOM,您将看到该属性已被更改。



尽管不常用,d3一种用于更改选择元素的元素属性的方法, selection .property(propertyName,valueOrFunction) 。但是,没有等同的转换功能。



您可以制作一个有效的功能请求,其中应该是 transition.property()函数。根据你的例子,我可以看到它的用途 - 也许你有一个数字滑块或颜色输入,你希望显示的值平滑地改变,而不是瞬间跳到你设置的值。



然而,在您的情况下,这仍然无法正常工作。假设属性转换功能的实现与属性或样式转换相同,则字符串值的默认转换会将字符串分隔为数字和非数字段。非数字段立即改变,数字转换。如果您从Cmin6变为Amaj7,那将是奇怪而随机的 - 您最终会出现像Amaj6.569087098608760876一样的和弦!


$ b $总而言之:我不知道为什么要使用转换来更改文本字段,或者您期望的是内部值。如果您清楚了解如何计算中间值,请使用直接设置 this.value 的自定义补间函数。 (有关如何执行此操作的示例,请参阅我为这个答案,它使用自定义补间设置 this.textContent )否则,跳过转换,只需使用:

  input.property(value,waveplot.chordname); 


I've been trying, step by step, to convert some very nice but static & non-d3 code for dynamic animation in a d3.js visualisation.

(Though not directly relevant to this problem, the original code 'simply' -haha- accepts a user-supplied chordname such as 'Amaj7', breaks it down into it's component notes and displays the associated waveforms. I'm trying to create an transition-driven animation based on an array of chordnames.)

For my part, for each successful code update (to a d3.js friendly version) achieved, the source code was saved to act as a working comparison with the next.

In the current update to the code, I've hit a glitch trying to incorporate a transition. The transition itself is well proven, and (by means of logging) can be seen to fire as expected.

During the transition, the desired attribute value changes (the next chordname to be handled, and the goal of the immediate transition) are failing. Comparing the previous (working) version with the current:

Initial creation, common to both, but in a separate file and so element is accessible only via the DOM

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

Old

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

input.addEventListener('change', inputChanged, false);
inputChanged.call(input);

and (pre-transition):

input.setAttribute("value", (waveplot.chordname + "\x0A")); 
inputChanged.call(input);

Let's be clear: the above works.

New

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

input.on('change', inputChanged, false);
inputChanged.call(input);

Later, neither this:

input
.transition()
.text(function() {
    return (waveplot.chordname + "\x0A");
})

..nor this:

input
.transition()
.attr("value", function() {
    return (waveplot.chordname + "\x0A");
});

..nor variants minus the return character ("\x0A") result in update of the input element's value field. waveplot.chordname is, incidentally, always correctly defined.

Given that not even the original Amaj7 is not recognised in the new code, my gut feeling is that the problem lies with the line

input.on('change', inputChanged, false);

Clearly, with transitions in play, my aim is to trap multiple events using this line. What am I failing to do, or doing wrong? Must I for example use a different trigger (neither 'submit' nor 'click' have any impact), use d3.dispatch(), or even map each event to it's own ('change.n') handler?

Note: much as I'd like to demo this in the likes of a jsfiddle, the whole thing is embedded in a framework, aka for the moment impractical..

Thanks Thug

解决方案

There are a couple things going on here, neither of which are directly related to d3. However, there are also some d3-related things to be aware of as you fix your code, so I've indicated them in italics below.

First, setting .text() won't work on an <input>, because it changes the .textContent property (which is ignored -- input elements are empty).

Even if you used transition().text() on a valid text container element, you wouldn't see a "transition" -- the text would just instantaneously change after the transition delay.

Second, the value attribute of an input is not the same as the value property (i.e. element.value). The attribute (which is what you'd include in the markup) defines the initial value for the input element, before any user or script interaction. Changing it after the page is loaded has no effect. The property, in contrast, defines the current value of the field, regardless of whether you change it in the script or whether the user changes it by typing.

See this fiddle (which only uses plain Javascript, not 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");

Neither setAttribute call affects the display -- the text box contains "Good Stuff" -- although if you check the DOM you'll see that the attribute has been changed.

Although it's not often used, d3 has a method for changing element properties for the elements in a selection, selection.property(propertyName, valueOrFunction). However, there is no equivalent function for transitions.

You could make a valid feature request that there should be a transition.property() function. Based on your example, I can certainly see a use for it -- maybe you have a number slider or color input, and you want the displayed value to change smoothly instead of instantaneously jumping to the value you're setting it.

However, that still wouldn't work well in your case. Assuming the property transition function was implemented the same as an attribute or style transition, the default transition for a string value breaks the string into number and non-number segments. The non-number segments change immediately, the numbers transition. Which would be weird and random if you were changing from "Cmin6" to "Amaj7" -- you'd end up with a chord like "Amaj6.569087098608760876"!

In conclusion: I have no idea why you want to use a transition to change the text field, or what you expect the in-between values to be. If you have a clear idea of how you want in-between values to be calculated, use a custom tween function that directly sets this.value. (For an example of how to do this, see the fiddle I created for this answer, which uses a custom tween to set this.textContent.) Otherwise, skip the transition and just use:

input.property("value", waveplot.chordname);

这篇关于如何正确更新d3.js转换中输入元素的文本值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆