Reputation: 5557
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!
Upvotes: 2
Views: 1206
Reputation: 10979
Have you tried giving the <svg>
element itself an id attribute? e.g.
<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>
Upvotes: 0
Reputation: 60976
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:
<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>
Seems to work just fine in Chrome, Firefox and Opera.
Upvotes: 1