在HTML5视频上使用JavaScript添加覆盖文本。

huangapple go评论76阅读模式
英文:

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(&quot;vid-1&quot;);
vid.insertAdjacentHTML(&quot;aftereend&quot;,&quot;Video 1 - Greenery&quot;);

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=&quot;z-index: 2;    background: red;    position: absolute;    top: 50%;    right: 50%;&quot;;
    var vid = document.querySelector(&quot;video&quot;);
    vid.insertAdjacentHTML(&quot;afterend&quot;,`&lt;p style=&quot;${customStyle}&quot;&gt;Video 1 - Greenery&lt;/p&gt;`);

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:

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:


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(&quot;vid-1&quot;, &quot;Video 1 - Greenery&quot;);
idToCaption.set(&quot;vid-2&quot;, &quot;Video 2 - Island&quot;);

for (const [id, caption] of idToCaption.entries()) {
  const p = document.createElement(&quot;p&quot;);
  p.textContent = caption;
  
  const video = document.getElementById(id);
  
  // Assign caption as label
  p.id = `${id}-label`;
  video.setAttribute(&quot;aria-labelledby&quot;, p.id);
  
  video.parentElement.insertBefore(p, video);
}

<!-- language: lang-html -->

&lt;div id=&quot;vids&quot;&gt;
  &lt;video id=&quot;vid-1&quot; src=&quot;vid1.mp4&quot;&gt;&lt;/video&gt;
  &lt;video id=&quot;vid-2&quot; src=&quot;vid2.mp4&quot;&gt;&lt;/video&gt;
&lt;/div&gt;

<!-- 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 &lt;figcaption&gt; 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(&quot;vid-1&quot;, &quot;Video 1 - Greenery&quot;);
idToCaption.set(&quot;vid-2&quot;, &quot;Video 2 - Island&quot;);

for (const [id, caption] of idToCaption.entries()) {
  const p = document.createElement(&quot;p&quot;);
  p.textContent = caption;
  
  const video = document.getElementById(id);
  
  p.id = `${id}-label`;
  video.setAttribute(&quot;aria-labelledby&quot;, p.id);
  
  // New code starts here
  const wrapper = document.createElement(&quot;span&quot;);
  wrapper.classList.add(&quot;wrapper&quot;);
  
  p.classList.add(&quot;caption&quot;);
  
  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 &lt;video&gt;,
   * 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 -->

&lt;div id=&quot;vids&quot;&gt;
  &lt;video id=&quot;vid-1&quot; src=&quot;vid1.mp4&quot;&gt;&lt;/video&gt;
  &lt;video id=&quot;vid-2&quot; src=&quot;vid2.mp4&quot;&gt;&lt;/video&gt;
&lt;/div&gt;

<!-- end snippet -->

There already exist elements for captions and the wrapper: &lt;figcaption&gt; and &lt;figure&gt;. 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(&quot;vid-1&quot;, &quot;Video 1 - Greenery&quot;);
idToCaption.set(&quot;vid-2&quot;, &quot;Video 2 - Island&quot;);

for (const [id, caption] of idToCaption.entries()) {
  const figcaption = document.createElement(&quot;figcaption&quot;);
  figcaption.textContent = caption;
  
  const video = document.getElementById(id);
  
  /* Notice that &lt;figcaption&gt; automatically applies to its
   * &lt;figure&gt;&#39;s other content. No &quot;aria-labelledby&quot; required anymore! */
  
  const figure = document.createElement(&quot;figure&quot;);
  
  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 -->

&lt;div id=&quot;vids&quot;&gt;
  &lt;video id=&quot;vid-1&quot; src=&quot;vid1.mp4&quot;&gt;&lt;/video&gt;
  &lt;video id=&quot;vid-2&quot; src=&quot;vid2.mp4&quot;&gt;&lt;/video&gt;
&lt;/div&gt;

<!-- end snippet -->

Note: The &lt;figure&gt; element is display: block whereas &lt;video&gt; is display: inline by default. The stylesheet should fix this inconsistency.

huangapple
  • 本文由 发表于 2023年2月18日 13:59:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75491494.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定