我在AJAX网络应用程序中使用SVG图表。当收到初始数据时,我想将图表元素(如条形图)从默认的0值设置为新的数据值。如果用户选择了新数据集,我会从服务器请求新数据,然后将条形图从上一个值设置为新值。
<rect x="0" y="0" width="1px" height="20px" fill="red">
<animate id="anim" attributeName="width" attributeType="XML"
begin="indefinite" from="0" to="100px" dur="0.8s" fill="remove"/>
</rect>
每次收到数据时,我都会设置from
和to
属性并致电beginElement()
。
如果我在SVG动画中设置fill="remove"
,则每次加载新数据集时,条形图都会正确设置动画,但当然,在动画之间,条形图会返回其默认宽度。
设置width.baseVal.value
以在调用beginElement()
之后或之前建立新的基值会导致非常讨厌的闪烁。
所以我尝试使用fill="freeze"
让条形图在每个动画结束时保持宽度。问题是第一个动画有效,但每次对beginElement()
的调用都会立即将栏恢复为默认宽度,动画将停止工作。
我正在使用Chrome 12.0进行测试。下面是一个示例,了解动画在使用冻结时如何中断。
<!DOCTYPE html>
<html>
<head><title>Test SVG animation</title></head>
<body>
<svg width="200px" height="20px" xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect x="0" y="10px" width="200px" height="2px"/>
<rect x="0" y="0" width="1px" height="20px" fill="red">
<animate id="anim" attributeName="width" attributeType="XML" begin="indefinite" from="0" to="100px" dur="1.3s" fill="freeze"/>
</rect>
parent.anim = document.getElementById('anim');
</svg>
<br/>
<a href="javascript:anim.beginElement();">anim.beginElement();</a>
<br/>
<a href="javascript:anim.endElement();">anim.endElement();</a>
<br/>
<br/>
<a href="javascript:anim.setAttribute('to', '50px');">anim.setAttribute('to', '50px');</a>
<br/>
<a href="javascript:anim.setAttribute('to', '150px');">anim.setAttribute('to', '150px');</a>
<br/>
<br/>
<a href="javascript:anim.setAttribute('fill', 'remove');">anim.setAttribute('fill', 'remove');</a>
<br/>
<a href="javascript:anim.setAttribute('fill', 'freeze');">anim.setAttribute('fill', 'freeze');</a>
<br/>
</body>
</html>
如何为条形图的宽度设置动画,让它保持新的宽度,然后在它们到达时反复将其设置为新值?
答案 0 :(得分:1)
您可以在必要元素上调用suspendRedraw方法以避免闪烁。 HTH
答案 1 :(得分:1)
我认为当您更新下一个'to'值时,将当前'to'值更新为矩形对象的width属性以及动画的'from'属性。当你正在更新这个时,请确保你设置fill-&gt;删除,并在更改属性值后恢复fill-&gt;冻结。看看下面的代码是否有效。
<!DOCTYPE html>
<html>
<head><title>Test SVG animation</title>
<script type='text/javascript'>
var animNode = 0;
function OnEndHandler(evt)
{
if(!animNode)
animNode = evt.target;
var previousToValue = animNode.getAttribute('to');
animNode.parentNode.setAttribute('width', previousToValue);
animNode.setAttribute('from', previousToValue);
}
function OnBtnHandler(event)
{
if(!animNode)
animNode = document.querySelector('#anim');
if(event.target.id == 'nextBtn')
{
animNode.setAttribute('fill', 'remove');
animNode.setAttribute('to', '150px');
animNode.setAttribute('fill', 'freeze');
animNode.beginElement();
}
else if(event.target.id == 'startBtn')
{
animNode.setAttribute('to', '50px');
animNode.beginElement();
}
}
</script>
</head>
<body>
<input id= 'startBtn' type='button' value='StartBar' onclick='OnBtnHandler(event)' />
<input id='nextBtn' type='button' value='NextBar' onclick='OnBtnHandler(event)' />
<svg width="200px" height="20px" xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect x="0" y="10px" width="200px" height="2px"/>
<rect x="0" y="0" width="1px" height="20px" fill="red">
<animate id="anim" attributeName="width" attributeType="XML" begin="indefinite" from="0" to="100px" dur="1.3s" fill="freeze" onend='OnEndHandler(evt)' />
</rect>
</svg>
<br/>
<a href="javascript:anim.beginElement();">anim.beginElement();</a>
<br/>
<a href="javascript:anim.endElement();">anim.endElement();</a>
<br/>
<br/>
<a href="javascript:anim.setAttribute('to', '50px');">anim.setAttribute('to', '50px');</a>
<br/>
<a href="javascript:anim.setAttribute('to', '150px');">anim.setAttribute('to', '150px'); </a>
<br/>
<br/>
<a href="javascript:anim.setAttribute('fill', 'remove');">anim.setAttribute('fill', 'remove');</a>
<br/>
<a href="javascript:anim.setAttribute('fill', 'freeze');">anim.setAttribute('fill', 'freeze');</a>
<br/>
</body>
</html>
答案 2 :(得分:0)
只是一个想法:设置&#39;开始&#39;属性是自页面加载以来经过的当前秒数 有点像:
function seconds_elapsed () {
var date_now = new Date ();
var time_now = date_now.getTime ();
var time_diff = time_now - startTime;
var seconds_elapsed = Math.floor ( time_diff / 1000 );
return ( seconds_elapsed );
}
和/或使用.appendChild()添加新动画,而不是摆弄现有值。