我有一个SVG
,它有一个简化的结构:
<svg viewbox="0 0 1000 2000">
<image width="1024" height="2048" transform="<matrix A>" … />
</svg>
我想用html5 qazxsw poi元素替换图像,使用qazxsw poi如下:
<video>
因此我有这个代码:
<foreignObject>
基本上到目前为止一切都运行正常,但我不能让<svg viewbox="0 0 1000 2000">
<g transform="<matrix A>">
<foreignObject x="0" y="0" width="100%" height="100%">
<video style="display:block; width: 100%; height: 100%;">
<source src="…" type="…">
</video>
</foreignObject>
</g>
<!--
<image width="1024" height="2048" transform="<matrix in here>" … />
-->
</svg>
出现在与图像大小相同的位置。规格说:
(一世)
[...]包含的外国图形内容受SVG转换,过滤,剪裁,屏蔽和合成[...]
(II)
HTML解析器将'foreignObject'中的元素等同于HTML文档片段内的元素。 [...]
考虑(I):通过用从图像复制的所有变换的 [...document.querySelectorAll('image')].forEach(img => {
const
g = document.createElementNS('…', 'g'),
fo = g.appendChild(document.createElementNS('…', 'foreignObject')),
video = fo.appendChild(document.createElement('video')),
src = video.appendChild(document.createElement('source'))
;
g.setAttribute('transform', img.getAttribute('transform'));
fo.setAttribute('x', 0);
fo.setAttribute('y', 0);
fo.setAttribute('width', '100%');
fo.setAttribute('height', '100%');
video.style.cssText = `
position: absolute;
top: 100px;
left: 100px;
background-color: #00ff00;
`
video.setAttribute('width', 100);
video.setAttribute('height', 100);
img.parentNode.appendChild(g);
img.parentNode.removeChild(img);
});
替换图像,视频应该“生活在坐标空间”中。
考虑到(II),<video>
应该成为新文档片段的根节点,并且适合给定区域。
但结果看起来像这样:
<g>
其中:黑色区域代表整个SVG,白色区域代表整个HTML文档,其中包括SVG。两个绿色区域都是/ seam是视频,其中较大的一个是我想要的视频。
为什么/我错过了什么?
UPDATE
由于这太过分了,我创建了这个基本的svg:
<video>
什么在Firefox中完美运行,但在Chromium中没有。我可以设法通过在视频中添加来播放视频,但<svg
width="200"
height="200"
viewBox="0 0 200 200"
preserveAspectRatio="xMidYMid meet"
xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clip">
<circle cx="100" cy="100" r="100" />
</clipPath>
</defs>
<rect
x="0"
y="0"
width="200"
height="200"
style="fill:#ff0000;stroke:none"
clip-path="url(#clip)" />
<g clip-path="url(#clip)">
<foreignObject x="0" y="0" width="200" height="200" >
<video
autoplay=""
width="100%" height="100%">
<source src="/path/to/a/video.mp4" type="video/mp4" />
</video>
</foreignObject>
</g>
<text x="100" y="100">Hello</text>
</svg>
不会出现在视频前面,以铬为单位。
考虑到视频的坐标,这有效:
style="clip-path: url(#clip)"
您的视口是1000x2000,但图像是1024x2048。我认为这会剪辑你的形象。可能是混乱的一部分。
下一页:图像比视频更自由缩放,因为您通常希望保留视频的宽高比。这就是为什么当视频大小不适合容器时你会出现黑色边框。确保视频大小,图像大小和SVG视口都一致。
我也有点怀疑浏览器可以将所有SVG转换应用于视频。至少在过去,浏览器不会自己渲染视频,而是在页面中保留矩形区域,并将该区域的坐标发送到视频渲染器(可以使用覆盖窗口在另一个进程中)。如果您无法使用此功能,请尝试将整个SVG替换为视频。
此外,不是在JavaScript中执行此操作,而是构建一个小的本地HTML文件,您可以快速调整,直到视频看起来正确。当它工作时,然后从可以在两者之间转换的代码开始。否则,你会打开太多的蠕虫。
[更新1]
欢迎来到地狱。停留片刻 ...
您可以尝试使用开发人员工具来了解Chromium在这种情况下正在做什么。也许创建第二个本地测试用例,你尝试在视频上放置带有一些文本的<text>
。如果这不起作用,那么Chromium正在为这种类型的视频使用外部渲染器。
这在屏幕上看起来是一样的,但在幕后,Chromium要求另一个进程在屏幕上放置另一个窗口,使其看起来好像是页面的一部分。如果您有一个工具可以显示屏幕上所有应用程序窗口的坐标,您可以看到有一个工具停留在浏览器窗口的顶部。点击进入该窗口,Chromium无法看到它们,并且它无法在该窗口前面呈现任何内容,因为它是其他人的窗口(就像您不希望Chromium在文本编辑器上呈现恰好是通过浏览器窗口打开)。
选项:
const
{ top,
left,
width,
height } = foreignObject.getBoundingClientRect()
;
Object.entries({ width, height}).forEach(
([k,v]) => video.setAttribute(k,v)
);
video.style.left = `${left}px`;
video.style.top = `${top}px`;
以获取列表。那可能只是VP8,VP9和Theora(=任何“开放”视频格式)。 H.264和MPEG-4可能不起作用,因为电影制片厂恐慌你可以窃取他们的宝贵。