【问题标题】:Animating SVG with SMIL使用 SMIL 制作 SVG 动画
【发布时间】:2011-08-25 11:31:00
【问题描述】:

我正在尝试使用 SVG 为视频元素打造一个 UI。我正在寻找一个简单的解决方案来为控制栏设置动画,当鼠标在它里面时我想从窗口底部升起(比如 YouTube)。

这是我想做的:

<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="0 0 640 360" preserveAspectRatio="none" version="1.1">
  <g id="control_bar" transform="translate(0,360)">
    <animateTransform attributeName="transform" attributeType="XML" type="translate" begin="window.mouseover" from="0,360" to="0,328" dur="350ms" fill="freeze"/>
    <animateTransform attributeName="transform" attributeType="XML" type="translate" begin="window.mouseout" from="0,328" to="0,360" dur="350ms" fill="freeze"/>
    <rect x="0" y="0" width="640" height="32" fill="grey"/>
  </g>
</svg>

不幸的是,window.mouseover 没有做任何事情。相反,我创建了一个透明矩形来覆盖整个窗口,并给它一个 id="screen" 并使用 begin="screen.mouseover" 等。果然当鼠标在窗口中时,控制栏的动画就像我想要的那样,不幸的是,screen 会阻止它下面的所有元素获取自己的鼠标事件。

我正在寻找最简单的方法来实现这一点,最好只使用标记 (SMIL),因为我想避免使用大量 JavaScript 或库。

谢谢!

>>>编辑 澄清我所追求的是什么:

我想为 HTML5

我目前的解决方案:

我在我的 HTML 文档中放置了一个

<video width="640" src="myvideo.webm"/>

然后我使用以下 JavaScipt(带有 jquery):

$(function(){
  $("video").each(function(){
    var old_video = $(this);
    var width = old_video.attr("width")
    var height = Math.floor(width / (16 / 9))
    var video = $("<object/>")
    video.addClass("video")
    video.css({
      width: width,
      height: height,
    })

    var src = old_video.attr("src")     
    video.attr("data", "video.xhtml#" + src)        
    old_video.replaceWith(video)
  })
})

这会将视频元素替换为 ,其数据 uri 设置为:video.xhtml#myvideo.webm

那么video.xhtml的内容是这样的:

<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <script src="jquery.js"/>
  <script>
    $(function(){
      $(window).hover(function(){
        $("#in")[0].beginElement()
      }, function(){
        $("#out")[0].beginElement()
      })
      var video = document.createElement("video")
      video.setAttribute("src", location.hash.substr(1))
      $("div#video").replaceWith(video)
    })
  </script>
  <style>
    svg {
      position: absolute;
      top: 0;   left: 0;
    }
    video {
      position: absolute;
      top: 0;   left: 0;
      width: 100%;
      height: 100%;
      background: black;
    }
  </style>
</head>
<body>
  <div id="video"/>
  <svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="0 0 640 360" preserveAspectRatio="none" version="1.1">
    <g id="bar" transform="translate(0,360)">
      <animateTransform id="in" attributeName="transform" attributeType="XML" type="translate" begin="indefinite" from="0,360" to="0,328" dur="50ms" fill="freeze"/>
      <animateTransform id="out" attributeName="transform" attributeType="XML" type="translate" begin="indefinite" from="0,328" to="0,360" dur="350ms" fill="freeze"/>
      <rect x="0" y="0" width="640" height="32" fill="grey"/>
      <rect onclick="$('video')[0].play()" x="0" y="0" width="64" height="32" fill="blue">
        <set id="btn" attributeName="fill" to="red" begin="mousedown" end="mouseup;mouseout" dur="1s" fill="remove" />
      </rect>
    </g>
  </svg>
</body>
</html>

此文档从哈希中获取视频 uri,并在 SVG UI 后面注入一个视频元素。由于它是一个 XHTML 文档(而不是 SVG),我现在可以使用 jquery 来处理鼠标事件,这并不理想,但它似乎可以工作。唯一的问题是我收到一个 JavaScript 错误:a.compareDocumentPosition is not a function 源文件:jquery.js 行:17 在 Firefox 中。

这种方法有意义吗?有没有更好的办法?我也更喜欢仅使用 SMIL 而不是 JavaScript/jQuery 的动画解决方案。

谢谢!

【问题讨论】:

    标签: javascript xml animation svg smil


    【解决方案1】:

    begin 属性中的“窗口”部分只是一个 id。 svg 所做的是在具有该 id 的元素上注册一个事件侦听器,它甚至不必在 svg 内部,它可以是同一文档中的 HTML 元素。这是一个例子:

    <html xmlns="http://www.w3.org/1999/xhtml">
    <body>
      <div id="window">hover here</div>
      <svg xmlns="http://www.w3.org/2000/svg" height="640" width="480" viewBox="0 0 640 360" preserveAspectRatio="none" version="1.1">
        <g id="control_bar" transform="translate(0,360)">
          <animateTransform attributeName="transform" attributeType="XML" type="translate" begin="window.mouseover" from="0,360" to="0,328" dur="350ms" fill="freeze"/>
          <animateTransform attributeName="transform" attributeType="XML" type="translate" begin="window.mouseout" from="0,328" to="0,360" dur="350ms" fill="freeze"/>
          <rect x="0" y="0" width="640" height="32" fill="grey"/>
        </g>
      </svg>
    </body>
    </html>
    

    似乎在 Chrome、Firefox 和 Opera 中运行良好。

    【讨论】:

    • 我认为他正在寻找一种方法来在有人将鼠标悬停在 SVG 本身上时触发该事件。
    • 我正在尝试为 HTML5
    【解决方案2】:

    您是否尝试过为&lt;svg&gt; 元素本身赋予一个id 属性?例如

    <svg xmlns="http://www.w3.org/2000/svg" id="screen" height="100%" width="100%" viewBox="0 0 640 360" preserveAspectRatio="none" version="1.1" >
      <g id="control_bar" transform="translate(0,360)">
        <animateTransform attributeName="transform" attributeType="XML" type="translate" begin="screen.mouseover" from="0,360" to="0,328" dur="350ms" fill="freeze"/>
        <animateTransform attributeName="transform" attributeType="XML" type="translate" begin="screen.mouseout" from="0,328" to="0,360" dur="350ms" fill="freeze"/>
        <rect x="0" y="0" width="640" height="32" fill="grey"/>
      </g>
    </svg>
    

    【讨论】:

    • 是的,不幸的是,它仅在鼠标位于屏幕的空白部分时才有效。一旦鼠标悬停在任何子元素上,栏就会缩回。
    猜你喜欢
    • 2019-10-05
    • 2015-01-14
    • 1970-01-01
    • 2015-04-02
    • 2017-07-01
    • 2016-09-18
    • 2018-03-06
    • 2020-10-05
    • 2020-05-06
    相关资源
    最近更新 更多