首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SVG AnimateTransform不在Safari工作..?

SVG AnimateTransform不在Safari工作..?
EN

Stack Overflow用户
提问于 2021-04-06 22:18:47
回答 2查看 725关注 0票数 1

为什么这个在FF和Chrome中工作的动画不能在Safari中工作(begin="click"不触发Safari中的animateTransform;用0替换click,您就会看到它被触发)?

代码语言:javascript
复制
<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时:

代码语言:javascript
复制
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();

});

动画可以切换和关闭一次,但再次失败。根据规范,animateTransform应该在Safari中得到支持(我想我会放弃使用fakesmile来做这件事,所以忘掉IE.)。

对于如何使这一工作方式与Safari在Chrome +FF中的工作方式相同,有什么想法吗?

更新

越来越近,但仍然不完美(多次点击矩形,你会发现它是远远没有优化)……:小提琴

编辑与添加此脚本相对应:

代码语言:javascript
复制
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);
    

});

也许最好是处理在动画结束时触发的事件,然后暂停动画。有这样的事吗?我会继续挖掘..。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-04-08 16:35:24

好吧,经过无数次的文档处理后,终于找到了这个SMIL的解决方案。实际上,对于Safari,不需要使用beginElement()进行js填充;因为目前的解决方案适用于所有FF、Chrome和Safari,完美无缺:

代码语言:javascript
复制
<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值被改变,实际上是关于如何编码不同的时间!

票数 1
EN

Stack Overflow用户

发布于 2021-04-07 16:44:22

好的,我已经为Safari (version 14)编写了一个正确的Poly填充解决方案,包括避免动画在运行时触发:

代码语言:javascript
复制
// 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);


    }

  });

这里更新了片段

不过,我想知道以下几点:

一个更清晰的解决方案是使用元素的endEvent (在本例中是endEvent元素)。也就是说,触发setTimeout回调的一部分作为事件的事件侦听器,以获得最大的计时精度。但是,即使我使用与上面链接中的代码完全相同的代码来注册endEvent侦听器,它也会在FF和Chrome中被触发,但是Safari甚至不会触发endEvent,尽管元素是动画的。为什么..?

注意事项

这种填充只适用于Safari;例如,它在FF中不起作用;可以简单地省略它(并且需要将两个主要动画元素的begin属性设置为click)。仍然对比这个更通用的解决方案感兴趣.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66977183

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档