英文:
Add overlay text on a html5 video using Javascript
问题
var vid = document.getElementById("vid-1");
var caption1 = document.createElement("div");
caption1.innerHTML = "Video 1 - Greenery";
vid.parentNode.insertBefore(caption1, vid.nextSibling);
英文:
For this html:
<html>
<div id="vids">
<video id="vid-1" src="vid1.mp4">
</video>
<video id="vid-2" src="vid2.mp4">
</video>
</div>
</html>
The videos show up correctly.<br>
I want to add an overlay text (caption) on top of each video like: <br>
"Video 1 - Greenery"<br>
"Video 2 - Island"
How can I do this using Javascript alone without modifying the HTML?<br>
If not overlay, how do I display caption right above or below each video.
I have tried this:
var vid = document.getElementById("vid-1");
vid.insertAdjacentHTML("aftereend","Video 1 - Greenery");
But the text "Video 1 - Greenery", appears on right side of video.
If it appeared directly above or below video that would work too.
答案1
得分: 1
以下是您要翻译的代码部分:
var customStyle = "z-index: 2; background: red; position: absolute; top: 50%; right: 50%;";
var vid = document.querySelector("video");
vid.insertAdjacentHTML("afterend", `<p style="${customStyle}">Video 1 - Greenery</p>`);
请注意,代码部分已翻译如上。
英文:
var customStyle="z-index: 2; background: red; position: absolute; top: 50%; right: 50%;";
var vid = document.querySelector("video");
vid.insertAdjacentHTML("afterend",`<p style="${customStyle}">Video 1 - Greenery</p>`);
Style is just for example purposes.
Naturallly better is to use file styles.
insertAdjacentHTML renders an Element, so if You put a raw text, then it creates a textNode.
Better to wrap it in some tag - then style has access to it.
using ${customStyle}
You make it easier to maintain.
It's easier to set dynamic elements with it's inline styes than to operate on window stylesheets.
This solution makes styling Your text possible.
答案2
得分: 1
以下是您要翻译的内容:
TL;DR:
- Prefer to use
<figcaption>
(and<figure>
). - "Placing above" is solved with CSS; see e.g.
position: absolute
.
We can map video IDs to captions. Then for all entries, we can create and insert the captions before their corresponding videos:
const idToCaption = new Map();
idToCaption.set("vid-1", "Video 1 - Greenery");
idToCaption set("vid-2", "Video 2 - Island");
for (const [id, caption] of idToCaption.entries()) {
const p = document.createElement("p");
p.textContent = caption;
const video = document.getElementById(id);
// Assign caption as label
p.id = `${id}-label`;
video.setAttribute("aria-labelledby", p.id);
video.parentElement.insertBefore(p, video);
}
<div id="vids">
<video id="vid-1" src="vid1.mp4"></video>
<video id="vid-2" src="vid2.mp4"></video>
</div>
Note:
- To place the captions after their videos, reference the video's next sibling.
- For accessibility reasons we should declare the captions to label the videos, e.g. via
aria-labelledby
. (Captions labelling content is done implicitly when using<figcaption>
as below.)
Without styling, the captions will come before their videos. To place them above their videos we need styling (CSS).
Placing elements above others can be achieved by taking them out of the flow, e.g. with position: absolute
.
We want to position the captions relative to the videos. But the captions are siblings and not children of the videos, which makes relative positioning more difficult.
We can wrap each caption and its video in another element, which will effectively represent the video. That way, the caption is a child of the "video" (the wrapper), which makes positioning it correctly easier:
const idToCaption = new Map();
idToCaption.set("vid-1", "Video 1 - Greenery");
idToCaption.set("vid-2", "Video 2 - Island");
for (const [id, caption] of idToCaption.entries()) {
const p = document.createElement("p");
p.textContent = caption;
const video = document.getElementById(id);
p.id = `${id}-label`;
video.setAttribute("aria-labelledby", p.id);
// New code starts here
const wrapper = document.createElement("span");
wrapper.classList.add("wrapper");
p.classList.add("caption");
video.replaceWith(wrapper);
wrapper.append(p, video);
}
.caption {
position: absolute;
/*Example: Position at top-left*/
top: 0;
left: 0;
}
.wrapper {
/* `position:absolute` elements are relative to
* first non-`static` ancestor.
* Make wrapper non-`static`. */
position: relative;
/* `display:inline-block` makes
* `.wrapper` behave like <video>,
* but contain it (here: inherit its size). */
display: inline-block;
}
/*Ignore; presentational*/
.caption {
margin: 0;
color: white;
background-color: black;
}
video {border: 1px solid black}
<div id="vids">
<video id="vid-1" src="vid1.mp4"></video>
<video id="vid-2" src="vid2.mp4"></video>
</div>
There already exist elements for captions and the wrapper: <figcaption>
and <figure>
. You should prefer these where applicable, e.g. here:
const idToCaption = new Map();
idToCaption.set("vid-1", "Video 1 - Greenery");
idToCaption.set("vid-2", "Video 2 - Island");
for (const [id, caption] of idToCaption.entries()) {
const figcaption = document.createElement("figcaption");
figcaption.textContent = caption;
const video = document.getElementById(id);
/* Notice that <figcaption> automatically applies to its
* <figure>'s other content. No "aria-labelledby" required anymore! */
const figure = document.createElement("figure");
video.replaceWith(figure);
figure.append(figcaption, video);
}
figcaption {
position: absolute;
top: 0;
left: 0;
}
figure {position: relative}
/*Ignore; presentational*/
figcaption {
margin: 0;
color: white;
background-color: black;
}
video {border: 1px solid black}
<div id="vids">
<video id="vid-1" src="vid1.mp4"></video>
<video id="vid-2" src="vid2.mp4"></video>
</div>
Note: The <figure>
element is display: block
whereas <video>
is display: inline
by default. The stylesheet should fix this inconsistency.
英文:
TL;DR:
- Prefer to use
<figcaption>
(and<figure>
). - "Placing above" is solved with CSS; see e.g.
position: absolute
.
We can map video IDs to captions. Then for all entries, we can create and insert the captions before their corresponding videos:
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
const idToCaption = new Map();
idToCaption.set("vid-1", "Video 1 - Greenery");
idToCaption.set("vid-2", "Video 2 - Island");
for (const [id, caption] of idToCaption.entries()) {
const p = document.createElement("p");
p.textContent = caption;
const video = document.getElementById(id);
// Assign caption as label
p.id = `${id}-label`;
video.setAttribute("aria-labelledby", p.id);
video.parentElement.insertBefore(p, video);
}
<!-- language: lang-html -->
<div id="vids">
<video id="vid-1" src="vid1.mp4"></video>
<video id="vid-2" src="vid2.mp4"></video>
</div>
<!-- end snippet -->
Note:
- To place the captions after their videos, reference the video's next sibling.
- For accessibility reasons we should declare the captions to label the videos, e.g. via
aria-labelledby
. (Captions labelling content is done implicitly when using<figcaption>
as below.)
Without styling, the captions will come before their videos. To place them above their videos we need styling (CSS).
Placing elements above others can be achieved by taking them out of the flow, e.g. with position: absolute
.
We want to position the captions relative to the videos. But the captions are siblings and not children of the videos, which makes relative positioning more difficult.
We can wrap each caption and its video in another element, which will effectively represent the video. That way, the caption is a child of the "video" (the wrapper), which makes positioning it correctly easier:
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
const idToCaption = new Map();
idToCaption.set("vid-1", "Video 1 - Greenery");
idToCaption.set("vid-2", "Video 2 - Island");
for (const [id, caption] of idToCaption.entries()) {
const p = document.createElement("p");
p.textContent = caption;
const video = document.getElementById(id);
p.id = `${id}-label`;
video.setAttribute("aria-labelledby", p.id);
// New code starts here
const wrapper = document.createElement("span");
wrapper.classList.add("wrapper");
p.classList.add("caption");
video.replaceWith(wrapper);
wrapper.append(p, video);
}
<!-- language: lang-css -->
.caption {
position: absolute;
/*Example: Position at top-left*/
top: 0;
left: 0;
}
.wrapper {
/* `position:absolute` elements are relative to
* first non-`static` ancestor.
* Make wrapper non-`static`. */
position: relative;
/* `display:inline-block` makes
* `.wrapper` behave like <video>,
* but contain it (here: inherit its size). */
display: inline-block;
}
/*Ignore; presentational*/
.caption {
margin: 0;
color: white;
background-color: black;
}
video {border: 1px solid black}
<!-- language: lang-html -->
<div id="vids">
<video id="vid-1" src="vid1.mp4"></video>
<video id="vid-2" src="vid2.mp4"></video>
</div>
<!-- end snippet -->
There already exist elements for captions and the wrapper: <figcaption>
and <figure>
. You should prefer these where applicable, e.g. here:
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
const idToCaption = new Map();
idToCaption.set("vid-1", "Video 1 - Greenery");
idToCaption.set("vid-2", "Video 2 - Island");
for (const [id, caption] of idToCaption.entries()) {
const figcaption = document.createElement("figcaption");
figcaption.textContent = caption;
const video = document.getElementById(id);
/* Notice that <figcaption> automatically applies to its
* <figure>'s other content. No "aria-labelledby" required anymore! */
const figure = document.createElement("figure");
video.replaceWith(figure);
figure.append(figcaption, video);
}
<!-- language: lang-css -->
figcaption {
position: absolute;
top: 0;
left: 0;
}
figure {position: relative}
/*Ignore; presentational*/
figcaption {
margin: 0;
color: white;
background-color: black;
}
video {border: 1px solid black}
<!-- language: lang-html -->
<div id="vids">
<video id="vid-1" src="vid1.mp4"></video>
<video id="vid-2" src="vid2.mp4"></video>
</div>
<!-- end snippet -->
Note: The <figure>
element is display: block
whereas <video>
is display: inline
by default. The stylesheet should fix this inconsistency.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论