SVG AnimateTransform 在 Safari 中不工作..?
SVG AnimateTransform not working in Safari..?
为什么这个动画在 FF 和 Chrome 中有效,但在 Safari 中无效(begin="click"
不会触发 Safari 中的 animateTransform;将 click
替换为例如 0 和你会看到它被触发)?
<svg version="1.1" baseProfile="full" viewBox="0 0 1000 200" xmlns="http://www.w3.org/2000/svg" id="timeline-container">
<rect id="project-10-activator" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="block">
<animateTransform id="activate_project_10" begin="click" fill="freeze" dur="0.5s"></animateTransform>
<set attributeName="display" to="block" begin="inactivate_project_10.end" fill="freeze"></set>
<set attributeName="display" to="none" begin="activate_project_10.end" fill="freeze"></set>
</rect>
<rect id="project-10-inactivator" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="none">
<animateTransform id="inactivate_project_10" begin="click" fill="freeze" dur="0.5s"></animateTransform>
<set attributeName="display" to="block" begin="activate_project_10.end" fill="freeze"></set>
<set attributeName="display" to="none" begin="inactivate_project_10.end" fill="freeze"></set>
</rect>
<text data-project-id="10" x="17" y="121.2" transform="rotate(-90,17,121.2)" class="timeline-project-label label-above-project-point">
<tspan>Upper Title</tspan>
<tspan class="project-name-span" x="17" dy="15">lower title</tspan>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 16.609375 139.7156219482422" to="90 16.609375 139.7156219482422" additive="sum" fill="freeze">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 0" to="-33.140625 -10" additive="sum" fill="freeze"></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 0" to="33.140625 10" additive="sum" fill="freeze"></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 16.609375 139.7156219482422" to="-90 16.609375 139.7156219482422" additive="sum" fill="freeze">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" repeatCount="1" dur="0.01s" from="-90 17 121.2" to="-90 17 121.2" fill="freeze" additive="replace" accumulate="sum" begin="inactivate_project_10.end"></animateTransform>
</text>
</svg>
仅在添加以下js时:
document.getElementById( "project-10-activator" )
.addEventListener( "click", function() {
document.getElementById( "activate_project_10" ).beginElement();
});
document.getElementById( "project-10-inactivator" )
.addEventListener( "click", function() {
document.getElementById( "inactivate_project_10" ).beginElement();
});
动画可以打开和关闭一次,但再次失败。根据规范,Safari 应该支持 animateTransform(我想我会放弃使用 fakesmile 来做到这一点,所以忘记 IE..)。
关于如何使它在 Safari 中以与在 Chrome + FF 中相同的方式工作的任何想法??
更新
越来越近了,但还不够完美(多次点击矩形,你会发现它远未优化)......:fiddle
编辑对应于添加此脚本:
document.getElementById( "project-10-activator" )
.addEventListener( "click", function() {
// Reset the timer every time a new toggle cycle is initiated
document.getElementById( "timeline-container" ).setCurrentTime(0);
// Unpause the animation clock
document.getElementById( "timeline-container" ).unpauseAnimations();
// Trigger the animations used to activate the label
document.getElementById( "activate_project_10" ).beginElement();
// Wait for the animation to complete + 100ms to account for delays, then
// pause the animation clock
window.setTimeout(function(){
document.getElementById( "timeline-container" ).pauseAnimations();
},600);
});
document.getElementById( "project-10-inactivator" )
.addEventListener( "click", function() {
// Unpause the animation clock
document.getElementById( "timeline-container" ).unpauseAnimations();
// Start with the animations used to inactivate the label back to start
document.getElementById( "inactivate_project_10" ).beginElement();
// Wait for the reverse animation to complete, then again pause the animation clock
window.setTimeout(function(){
document.getElementById( "timeline-container" ).pauseAnimations();
},600);
});
最好处理在动画结束时触发的事件,然后暂停动画。有这样的事吗?我会继续挖掘...
好的,我已经设法为 Safari(版本 14)编写了一个合适的 polyfill 解决方案,其中包括避免动画在已经 运行:
时被触发
// Initiate variable which keeps track if the concerned element is being
// animated or not.
var animActive = false;
document.getElementById("project-10-activator")
.addEventListener("click", function() {
// Only trigger animation if it is not currently running
if (!animActive) {
// Update the value of animActive, to indicate that this animation is
// running
animActive = true;
// Reset animation clock back to 0
document.getElementById("timeline-container").setCurrentTime(0);
// Unpause the animation clock
document.getElementById("timeline-container").unpauseAnimations();
// Trigger the activation animation
document.getElementById("activate_project_10").beginElement();
// when the end of the last animation bound to that one is reached
window.setTimeout(function() {
// Pause the animation clock
document.getElementById("timeline-container").pauseAnimations();
// And reset the value of animActive
animActive = false;
}, 600);
}
});
document.getElementById("project-10-inactivator")
.addEventListener("click", function() {
// Also only trigger this animation if it is not already running
if (!animActive) {
// Update the value of animActive, to indicate that this animation is
// running
animActive = true;
// Unpause the animation clock
document.getElementById("timeline-container").unpauseAnimations();
// Trigger the animation
document.getElementById("inactivate_project_10").beginElement();
// when the end of the last animation bound to that one is reached
window.setTimeout(function() {
// Pause the animation clock
document.getElementById("timeline-container").pauseAnimations();
// And reset the value of animActive
animActive = false;
}, 600);
}
});
这里是更新后的 snippet.
不过,我想知道以下问题:
更简洁的解决方案是使用元素(在此示例中例如 activate_project_10
元素)endEvent。 IE。触发 setTimeout
的回调部分作为该事件的事件侦听器,以获得最大的计时精度。
但是,即使我使用与上面 link 中的代码完全相同的代码来注册 endEvent
侦听器,它也会在 FF 和 Chrome 中被触发,但 Safari 甚至不会触发endEvent
,虽然元素有动画。为什么..?
注意
此 polyfill 仅适用于 Safari;它在 FF 中不起作用;它可以简单地省略(并且两个主要动画元素的 begin
属性需要设置回 click
)。仍然对比这更通用的解决方案感兴趣...
好的,在查阅文档无数次之后,终于得到了这个 SMIL - 唯一的解决方案。对于 Safari,实际上不需要使用 beginElement()
的 js polyfill;因为目前的解决方案适用于所有 FF、Chrome 和 Safari,完美无瑕:
<svg version="1.1" baseProfile="full" viewBox="0 0 1000 200" xmlns="http://www.w3.org/2000/svg" id="timeline-container">
<rect id="activator_10" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="block">
<set attributeName="display" to="block" begin="inactivate_project_10.end" fill="freeze" dur="0.5s"></set>
<set attributeName="display" to="none" begin="activate_project_10.end" fill="freeze" dur="0.5s"></set>
</rect>
<rect id="inactivator_10" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="none">
<set attributeName="display" to="block" begin="activate_project_10.end" fill="freeze" dur="0.5s"></set>
<set attributeName="display" to="none" begin="inactivate_project_10.end" fill="freeze" dur="0.5s"></set>
</rect>
<text data-project-id="10" x="17" y="121.2" transform="rotate(-90,17,121.2)" class="timeline-project-label label-above-project-point">
<tspan>Upper Title</tspan>
<tspan class="project-name-span" x="17" dy="15">lower title</tspan>
<animateTransform id="activate_project_10" attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="activator_10.click" from="0 16.609375 139.7156219482422" to="90 16.609375 139.7156219482422" additive="sum" fill="freeze" restart="whenNotActive"/>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 0" to="-33.140625 -10" additive="sum" fill="freeze"/>
<animateTransform id="inactivate_project_10" attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="inactivator_10.click" from="0 0" to="33.140625 10" additive="sum" fill="freeze" restart="whenNotActive"/>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 16.609375 139.7156219482422" to="-90 16.609375 139.7156219482422" additive="sum" fill="freeze"/>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" repeatCount="1" dur="0.5s" from="-90 17 121.2" to="-90 17 121.2" fill="freeze" additive="replace" accumulate="sum" begin="inactivate_project_10.end"/>
</text>
</svg>
我对 SMIL 动画的标记实际上并不正确,有趣的是,FF 和 Chrome 仍然能够 运行 动画正确,而 Safari 则不能。您可以将我问题的初始片段与此答案中的片段进行比较,以检查差异/问题;它主要是关于时间以及触发不同元素的时间和方式(begin
属性等)。没有改变 x 或 y 值的转换,实际上都是关于如何对不同的时间进行编码!
为什么这个动画在 FF 和 Chrome 中有效,但在 Safari 中无效(begin="click"
不会触发 Safari 中的 animateTransform;将 click
替换为例如 0 和你会看到它被触发)?
<svg version="1.1" baseProfile="full" viewBox="0 0 1000 200" xmlns="http://www.w3.org/2000/svg" id="timeline-container">
<rect id="project-10-activator" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="block">
<animateTransform id="activate_project_10" begin="click" fill="freeze" dur="0.5s"></animateTransform>
<set attributeName="display" to="block" begin="inactivate_project_10.end" fill="freeze"></set>
<set attributeName="display" to="none" begin="activate_project_10.end" fill="freeze"></set>
</rect>
<rect id="project-10-inactivator" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="none">
<animateTransform id="inactivate_project_10" begin="click" fill="freeze" dur="0.5s"></animateTransform>
<set attributeName="display" to="block" begin="activate_project_10.end" fill="freeze"></set>
<set attributeName="display" to="none" begin="inactivate_project_10.end" fill="freeze"></set>
</rect>
<text data-project-id="10" x="17" y="121.2" transform="rotate(-90,17,121.2)" class="timeline-project-label label-above-project-point">
<tspan>Upper Title</tspan>
<tspan class="project-name-span" x="17" dy="15">lower title</tspan>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 16.609375 139.7156219482422" to="90 16.609375 139.7156219482422" additive="sum" fill="freeze">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 0" to="-33.140625 -10" additive="sum" fill="freeze"></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 0" to="33.140625 10" additive="sum" fill="freeze"></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 16.609375 139.7156219482422" to="-90 16.609375 139.7156219482422" additive="sum" fill="freeze">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" repeatCount="1" dur="0.01s" from="-90 17 121.2" to="-90 17 121.2" fill="freeze" additive="replace" accumulate="sum" begin="inactivate_project_10.end"></animateTransform>
</text>
</svg>
仅在添加以下js时:
document.getElementById( "project-10-activator" )
.addEventListener( "click", function() {
document.getElementById( "activate_project_10" ).beginElement();
});
document.getElementById( "project-10-inactivator" )
.addEventListener( "click", function() {
document.getElementById( "inactivate_project_10" ).beginElement();
});
动画可以打开和关闭一次,但再次失败。根据规范,Safari 应该支持 animateTransform(我想我会放弃使用 fakesmile 来做到这一点,所以忘记 IE..)。
关于如何使它在 Safari 中以与在 Chrome + FF 中相同的方式工作的任何想法??
更新
越来越近了,但还不够完美(多次点击矩形,你会发现它远未优化)......:fiddle
编辑对应于添加此脚本:
document.getElementById( "project-10-activator" )
.addEventListener( "click", function() {
// Reset the timer every time a new toggle cycle is initiated
document.getElementById( "timeline-container" ).setCurrentTime(0);
// Unpause the animation clock
document.getElementById( "timeline-container" ).unpauseAnimations();
// Trigger the animations used to activate the label
document.getElementById( "activate_project_10" ).beginElement();
// Wait for the animation to complete + 100ms to account for delays, then
// pause the animation clock
window.setTimeout(function(){
document.getElementById( "timeline-container" ).pauseAnimations();
},600);
});
document.getElementById( "project-10-inactivator" )
.addEventListener( "click", function() {
// Unpause the animation clock
document.getElementById( "timeline-container" ).unpauseAnimations();
// Start with the animations used to inactivate the label back to start
document.getElementById( "inactivate_project_10" ).beginElement();
// Wait for the reverse animation to complete, then again pause the animation clock
window.setTimeout(function(){
document.getElementById( "timeline-container" ).pauseAnimations();
},600);
});
最好处理在动画结束时触发的事件,然后暂停动画。有这样的事吗?我会继续挖掘...
好的,我已经设法为 Safari(版本 14)编写了一个合适的 polyfill 解决方案,其中包括避免动画在已经 运行:
时被触发// Initiate variable which keeps track if the concerned element is being
// animated or not.
var animActive = false;
document.getElementById("project-10-activator")
.addEventListener("click", function() {
// Only trigger animation if it is not currently running
if (!animActive) {
// Update the value of animActive, to indicate that this animation is
// running
animActive = true;
// Reset animation clock back to 0
document.getElementById("timeline-container").setCurrentTime(0);
// Unpause the animation clock
document.getElementById("timeline-container").unpauseAnimations();
// Trigger the activation animation
document.getElementById("activate_project_10").beginElement();
// when the end of the last animation bound to that one is reached
window.setTimeout(function() {
// Pause the animation clock
document.getElementById("timeline-container").pauseAnimations();
// And reset the value of animActive
animActive = false;
}, 600);
}
});
document.getElementById("project-10-inactivator")
.addEventListener("click", function() {
// Also only trigger this animation if it is not already running
if (!animActive) {
// Update the value of animActive, to indicate that this animation is
// running
animActive = true;
// Unpause the animation clock
document.getElementById("timeline-container").unpauseAnimations();
// Trigger the animation
document.getElementById("inactivate_project_10").beginElement();
// when the end of the last animation bound to that one is reached
window.setTimeout(function() {
// Pause the animation clock
document.getElementById("timeline-container").pauseAnimations();
// And reset the value of animActive
animActive = false;
}, 600);
}
});
这里是更新后的 snippet.
不过,我想知道以下问题:
更简洁的解决方案是使用元素(在此示例中例如 activate_project_10
元素)endEvent。 IE。触发 setTimeout
的回调部分作为该事件的事件侦听器,以获得最大的计时精度。
但是,即使我使用与上面 link 中的代码完全相同的代码来注册 endEvent
侦听器,它也会在 FF 和 Chrome 中被触发,但 Safari 甚至不会触发endEvent
,虽然元素有动画。为什么..?
注意
此 polyfill 仅适用于 Safari;它在 FF 中不起作用;它可以简单地省略(并且两个主要动画元素的 begin
属性需要设置回 click
)。仍然对比这更通用的解决方案感兴趣...
好的,在查阅文档无数次之后,终于得到了这个 SMIL - 唯一的解决方案。对于 Safari,实际上不需要使用 beginElement()
的 js polyfill;因为目前的解决方案适用于所有 FF、Chrome 和 Safari,完美无瑕:
<svg version="1.1" baseProfile="full" viewBox="0 0 1000 200" xmlns="http://www.w3.org/2000/svg" id="timeline-container">
<rect id="activator_10" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="block">
<set attributeName="display" to="block" begin="inactivate_project_10.end" fill="freeze" dur="0.5s"></set>
<set attributeName="display" to="none" begin="activate_project_10.end" fill="freeze" dur="0.5s"></set>
</rect>
<rect id="inactivator_10" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="none">
<set attributeName="display" to="block" begin="activate_project_10.end" fill="freeze" dur="0.5s"></set>
<set attributeName="display" to="none" begin="inactivate_project_10.end" fill="freeze" dur="0.5s"></set>
</rect>
<text data-project-id="10" x="17" y="121.2" transform="rotate(-90,17,121.2)" class="timeline-project-label label-above-project-point">
<tspan>Upper Title</tspan>
<tspan class="project-name-span" x="17" dy="15">lower title</tspan>
<animateTransform id="activate_project_10" attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="activator_10.click" from="0 16.609375 139.7156219482422" to="90 16.609375 139.7156219482422" additive="sum" fill="freeze" restart="whenNotActive"/>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 0" to="-33.140625 -10" additive="sum" fill="freeze"/>
<animateTransform id="inactivate_project_10" attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="inactivator_10.click" from="0 0" to="33.140625 10" additive="sum" fill="freeze" restart="whenNotActive"/>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 16.609375 139.7156219482422" to="-90 16.609375 139.7156219482422" additive="sum" fill="freeze"/>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" repeatCount="1" dur="0.5s" from="-90 17 121.2" to="-90 17 121.2" fill="freeze" additive="replace" accumulate="sum" begin="inactivate_project_10.end"/>
</text>
</svg>
我对 SMIL 动画的标记实际上并不正确,有趣的是,FF 和 Chrome 仍然能够 运行 动画正确,而 Safari 则不能。您可以将我问题的初始片段与此答案中的片段进行比较,以检查差异/问题;它主要是关于时间以及触发不同元素的时间和方式(begin
属性等)。没有改变 x 或 y 值的转换,实际上都是关于如何对不同的时间进行编码!