Embedding Video in SVG issues - html

I want to embed a video into an SVG to be displayed on a website, but I'm facing some issues with both playback and also responsive sizing. the code is below:
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 1050 550" style="enable-background:new 0 0 1050 550;" preserveAspectRatio="xMaxYMid" xmlns="http://www.w3.org/2000/svg" xmlns:bx="https://boxy-svg.com">
<style type="text/css">
.background{fill:#4D4D4D;}
.box{stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}
</style>
<rect id="Background" class="background" width="1050" height="550" bx:origin="0 0">
<title>background</title>
</rect>
<foreignObject>
<video xmlns="http://www.w3.org/1999/xhtml" width="800" controls="" style="position: fixed; left: 101px; top: 51px;">>
<source src="http://techslides.com/demos/sample-videos/small.mp4" type="video/mp4"></source>
</video>
</foreignObject>
<rect id="Box" class="box" width="800" height="450" y="50" style="fill: none;" x="100" bx:origin="0 0">
<title>background</title>
</rect>
</svg>
RE: sizing - I've tried using "vw" and "em" sizing conventions for this but when I do, the video doesn't show at all.
RE: playback - there is no way I can add "controls" to the foreignObject class - it just gives me an error and won't render the SVG.
Can anyone help or think of any ideas here? Would be really grateful :)

Then main issue is that the <foreignObject> should have a size, just like other SVG elements.
I couldn't get the video to show, so I picked another one.
<svg viewBox="0 0 340 200" xmlns="http://www.w3.org/2000/svg">
<rect id="Background" class="background" width="340"
height="200" fill="gray" />
<foreignObject width="320" height="180" x="10" y="10">
<video xmlns="http://www.w3.org/1999/xhtml" width="320"
height="180" controls>
<source src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" type="video/mp4"/>
</video>
</foreignObject>
<rect width="340" height="100" y="100" fill="black"
opacity=".3" pointer-events="none" />
</svg>
Update
I'm not able to reproduce the error "error on line 14 at column 56: Specification mandates value for attribute controls", but make sure that the control attribute has a value (or, like here controls=""), now that it is an XML document.
In the following example I have the SVG document and a HTML document. Both documents have a stylesheet that behaves responsive at 300 and 400 pixel width. This seams to work fine.
SVG document (video.svg)
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 340 200" xmlns="http://www.w3.org/2000/svg">
<style>
.backgrond {
fill: gray;
}
#media (min-width: 300px) {
.background {
fill: orange;
}
}
</style>
<rect class="background" width="340" height="200" fill="gray" />
<foreignObject width="320" height="180" x="10" y="10">
<video xmlns="http://www.w3.org/1999/xhtml" width="320"
height="180" controls="">
<source src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" type="video/mp4"/>
</video>
</foreignObject>
<rect width="340" height="100" y="100" fill="black"
opacity=".3" pointer-events="none" />
</svg>
HTML document
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.video {
width: 100%;
}
#media (min-width: 400px) {
.video {
width: 400px;
}
}
</style>
</head>
<body>
<object class="video" type="image/svg+xml" data="video.svg"></object>
</body>
</html>

Related

Can SVG foreignObject HTML5 be used?

What can be done to make HTML5 work
your code:
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
<foreignObject width="100%" height="100%">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<video width="100%" controls controlsList="nodownload" muted autoplay poster="https://www.dl.dropboxusercontent.com/s/tyrcl7la31nw446/SACKBOY%20A%20Big%20Adventure%20_%20Trailer%20PC%20%284K%29%281080P_60FPS%29_1_0.png?dl=1">
<source src="https://www.dl.dropboxusercontent.com/s/5qcr6kvv2gfrzxt/SACKBOY%20A%20Big%20Adventure%20_%20Trailer%20PC%20%284K%29%281080P_60FPS%29_1.mp4?dl=1">
</video>
</body>
</html>
</foreignObject>
</svg>
What to do for HTML5
You can run the link

<picture> equivalent for fallback from webp to jepg

I have the following classic SVG code:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
<image
xlink:href="foo.webp"
height="100"
width="100"
x="0"
y="0"
image-rendering="optimizeQuality"
/>
</svg>
However, on some browsers, webp is not yet supported (iOS and macOS I am looking at you: https://caniuse.com/?search=webp) ...
So, is there a way similar to the <picture> element to do something like this (syntax obviously wrong, but I hope it does convey the idea):
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
<image
xlink:href="foo.webp"
height="100"
width="100"
x="0"
y="0"
image-rendering="optimizeQuality"
/>
<fallback_to>
<image
xlink:href="foo.jpg"
height="100"
width="100"
x="0"
y="0"
image-rendering="optimizeQuality"
/>
</svg>
... without of course getting the double-http-hit problem. And without using client-side Javascript (modernizr or other).
Many thanks!
Maybe you could use <foreignObject>. Inside the element you can specify the HTML that you need, like the <picture> element.
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" width="400">
<foreignObject x="0" y="0" width="300" height="200">
<picture xmlns="http://www.w3.org/1999/xhtml">
<source srcset="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Johnrogershousemay2020.webp/200px-Johnrogershousemay2020.webp" type="image/webp">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Johnrogershousemay2020.webp/200px-Johnrogershousemay2020.webp.png" alt="logo">
</picture>
</foreignObject>
</svg>
You could detect WebP support and hide the relevant <image> element based on the results.

video tag embedded in svg

I'm trying to embed a video inside an svg (the svg will only ever be viewed on the web). For that, I'm using the foreignObject tag:
<svg version="1.1" class="center-block" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="800" height="600"
style="border: 1px solid black;">
<g>
<g transform="translate(151,104) scale(1,1)">
<rect x="0" y="0" width="300" height="200"></rect>
<foreignObject x="0" y="0" width="300" height="200">
<video width="300" height="200" controls="" style="position: fixed; left: 151px; top: 104px;">
<source src="http://techslides.com/demos/sample-videos/small.mp4" type="video/mp4">
</video>
</foreignObject>
</g>
</g>
</svg>
It "works" in the sense that the video is displayed, but it's off by several pixels relative to its parent <g>. I tried several combinations: with style for the video, without styles, with namespaced video tag, etc. This works a lot better in firefox, but breaks completely in Chrome (Mac and Linux). I don't want to add an html tag outside the svg as this will be more hassle (the svg is created dynamically with React).
Has anyone been able to get something similar working?
There you go:
Translate moves the origin from the top left to the specified coordinates. If you embed an object at 0,0 it will be placed at the new origin. In this case you must embed it at -translation coordinates.
Even so, I had to increase the width and height. Why? I don't know. It doesn't seem to be a scale by 2. If someone knows I am curious to know.
<svg version="1.1" class="center-block" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800" height="600" style="border: 1px solid black;">
<g>
<g transform="translate(151,104) scale(1,1)">
<rect x="0" y="0" width="300" height="200"></rect>
<foreignObject x="-151" y="-104" width="500" height="400">
<video xmlns="http://www.w3.org/1999/xhtml" width="300" height="200" controls="" style="position: fixed; left: 151px; top: 104px;">
<source src="http://techslides.com/demos/sample-videos/small.mp4" type="video/mp4" />
</video>
</foreignObject>
</g>
</g>
</svg>

Why this code is not showing the background image on svg rectangale

My code below is not working as expected. Not showing the image in the background of the rectangle.
<html>
<body>
<svg width="600" height="700">
<rect width="300" height="400" class="eq__NEcontainer__currentAlarmAction" style="fill:url(#godhelpme);">
<title stroke="blue">My test</title>
</rect>
<defs id="godhelpme">
<pattern width="200" height="200" x="0" y="0" patternUnits="userSpaceOnUse">
<image width="200" height="200" class="eq__NEcontainer__currentAlarmAction" xlink:href="CurrentList.png"></image>
</pattern>
</defs>
</svg>
</body>
</html>
The rectangle is always black as in the image. Any ideas ?. I have tried debugging using chrome. In the debugger clicking on the image tag shows empty. I have attached the images for reference.. Any help would be of greatly appreciated.
You cannot reference a <defs> element as the fill, you want the <pattern>. So put the id on the <pattern> element instead. Also in general you should aim to put your <defs> elements before where they're used, it's more efficient that way.
Like this:
<html>
<body>
<svg width="600" height="700">
<defs>
<pattern id="godhelpme" width="200" height="200" x="0" y="0"
patternUnits="userSpaceOnUse">
<image width="200" height="200"
class="eq__NEcontainer__currentAlarmAction"
xlink:href="CurrentList.png"></image>
</pattern>
</defs>
<rect width="300" height="400" class="eq__NEcontainer__currentAlarmAction"
style="fill:url(#godhelpme);">
<title stroke="blue">My test</title>
</rect>
</svg>
</body>
</html>

Cutting a hole in a parent element with CSS

I don't know if this is possible, but I would like to cut holes in an opaque wrapper set to the height and width of the window to a layer of video beneath it using a div positioned within wrapper.
Here is a jsFiddle with the desired layout set up and further explanation:
http://jsfiddle.net/XuYxg/
Any help, or an alternate method would be very helpful. Thanks!
You could use a transparent png or svg to create the shape overlay, with the blank areas in effect becoming the mask or you could use the clip or mask property in CSS.
Here's a jsFiddle example using svg.
External JS/CSS:
<link href="http://vjs.zencdn.net/4.3/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/4.3/video.js"></script>
HTML:
<body>
<!--VideoJS linked to default video for placeholder -->
<div id="videoDiv">
<video id="example_video_1" class="video-js vjs-default-skin" autoplay controls preload="none" width="900" height="600"
poster="http://video-js.zencoder.com/oceans-clip.png"
data-setup="{}">
<source src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
<source src="http://video-js.zencoder.com/oceans-clip.webm" type='video/webm' />
<source src="http://video-js.zencoder.com/oceans-clip.ogv" type='video/ogg' />
<track kind="captions" src="demo.captions.vtt" srclang="en" label="English"></track><!-- Tracks need an ending tag thanks to IE9 -->
<track kind="subtitles" src="demo.captions.vtt" srclang="en" label="English"></track><!-- Tracks need an ending tag thanks to IE9 -->
</video>
</div>
<!--End Video JS-->
<!--SVG Mask, output from Adobe Illustrator -->
<div id="wrapper">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="900px" height="600px" viewBox="0 0 900 600" enable-background="new 0 0 900 600" xml:space="preserve">
<g>
<path stroke="#FFFFFF" stroke-miterlimit="10" d="M0,0v600h900V0H0z M316.549,351.231h-30.796v-92.803l-23.729,92.803h-27.875
l-23.685-92.803v92.803h-30.796V229.542h49.452l19.07,74.043l18.936-74.043h49.422V351.231z M421.439,351.231l-6.088-20.088h-42.69
l-5.932,20.088h-38.394l45.737-121.689h41.017l45.727,121.689H421.439z M570.138,333.218c-4.316,6.586-10.349,11.58-18.096,14.983
c-7.748,3.403-17.515,5.105-29.302,5.105c-20.697,0-35.029-3.984-42.998-11.953s-12.479-18.096-13.53-30.381l35.776-2.241
c0.774,5.811,2.352,10.238,4.731,13.281c3.873,4.926,9.407,7.388,16.602,7.388c5.367,0,9.505-1.258,12.409-3.777
c2.906-2.517,4.358-5.437,4.358-8.757c0-3.154-1.384-5.977-4.15-8.467c-2.768-2.49-9.187-4.842-19.258-7.056
c-16.491-3.707-28.251-8.633-35.278-14.775c-7.084-6.143-10.625-13.973-10.625-23.491c0-6.253,1.812-12.161,5.438-17.722
c3.623-5.562,9.074-9.932,16.352-13.115c7.276-3.182,17.252-4.773,29.925-4.773c15.55,0,27.405,2.892,35.569,8.674
c8.161,5.783,13.018,14.983,14.567,27.6l-35.444,2.075c-0.941-5.479-2.92-9.463-5.936-11.953c-3.017-2.49-7.18-3.735-12.492-3.735
c-4.372,0-7.665,0.927-9.878,2.781c-2.214,1.855-3.32,4.109-3.32,6.765c0,1.938,0.913,3.681,2.739,5.229
c1.771,1.606,5.977,3.1,12.617,4.482c16.436,3.542,28.208,7.126,35.32,10.75c7.109,3.625,12.285,8.122,15.521,13.489
c3.238,5.368,4.856,11.372,4.856,18.013C576.612,319.439,574.454,326.633,570.138,333.218z M678.392,351.231l-25.657-50.045
l-19.428,20.35v29.695h-37.603V229.542h37.603v45.986l39.389-45.986h50.011L678.3,275.473l46.398,75.758H678.392z"/>
<polygon stroke="#FFFFFF" stroke-miterlimit="10" points="380.828,304.83 407.552,304.83 394.12,261.084 "/>
</g>
</svg>
</div>
<!--End SVG Mask-->
</body>
CSS:
#wrapper {
position: absolute;
height: 100%;
width: 100%;
z-index: 5;
}
#videoDiv {
position: absolute;
z-index: -5;
}