使用 SMIL 制作 SVG 动画
我正在尝试使用 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" 等。果然,当鼠标位于窗口中时,控制栏会按照我想要的方式进行动画处理不幸的是,屏幕阻止其下面的所有元素获取自己的鼠标事件。
我正在寻找最简单的方法来完成此任务,最好仅使用标记(SMIL),因为我想避免大量的 JavaScript 或库。
谢谢!
>>>编辑<<<为了澄清我所追求的是什么:
我想为 HTML5
我当前的解决方案:
我将
<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)
})
})
这将视频元素替换为
那么 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 不是函数 源文件:jquery.js 行:Firefox 中的第 17 行。
这种方法有意义吗?有更好的办法吗?我还更喜欢仅使用 SMIL 而不是 JavaScript/jQuery 的动画解决方案。
谢谢!
I'm trying to greate a UI for a video element using SVG. I'm looking for a simple solution to animating the control bar, which I want to rise up from the bottom of the window when the mouse is inside of it (like YouTube).
Here is what I would like to do:
<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>
Unfortunately, window.mouseover doesn't do anything. Instead I created a transparent rectangle to cover the entire window, and gave it an id="screen" and used begin="screen.mouseover" etc. Sure enough the control bar animates like I want it to when the mouse is in the window, unfortunately though, screen prevents all the elements below it from getting their own mouse events.
I'm looking for the simplest possible way to accomplish this, preferable with just markup (SMIL) since I'd like to avoid a ton of JavaScript or libraries.
Thanks!
>>>EDIT<<< To clarify what it is I'm after:
I wanted to create a custom SVG UI for the HTML5 <video> element. My first approach was to dynamically insert SVG into the DOM using document.createElementNS, but that got messy really fast. Next I tried Raphael, but that only made it slightly less messy. I decided I wanted the UI to be a self contained document, so I decided to create a SVG document for the UI and then create a <object> element which would load it and be overlaid on top the <video> element. My problem with that was that I couldn't get the control bar to animate and then stay in position for as long was the mouse was within the window of the UI. Also, communicating with the UI from the parent document was becoming a pain.
My current solution:
I place a <video> element in my HTML document like so:
<video width="640" src="myvideo.webm"/>
then I use the following JavaScipt (with 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)
})
})
This replaces the video element with a <object> who's data uri is set to: video.xhtml#myvideo.webm
Then the contents of video.xhtml are so:
<?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>
This document fetches the video uri from the hash and injects a video element behind the SVG UI. Since it's a XHTML document (and not SVG) I am now able to use jquery to handle the mouse events, which isn't ideal but it seems to work. Only problem with it is that I get a JavaScript error: a.compareDocumentPosition is not a function
Source File: jquery.js Line: 17 in Firefox.
Does this approach make any sense? Is there a better way? I'd also prefer a solution to the animation using SMIL only and not JavaScript/jQuery.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
开始属性中的“窗口”部分只是一个 id。 svg 的作用是在具有该 id 的元素上注册一个事件侦听器,它甚至不必位于 svg 内部,它可以是同一文档中的 HTML 元素。下面是一个示例:
似乎在 Chrome、Firefox 和 Opera 中工作得很好。
The "window" part in your begin attributes is just an id. What svg does is to register an event listener on the element that has that id, and it doesn't even have to be inside the svg, it can be an HTML element in the same document. Here's an example:
Seems to work just fine in Chrome, Firefox and Opera.
您是否尝试过为
元素本身赋予 id 属性?例如
Have you tried giving the
<svg>
element itself an id attribute? e.g.