заменить <image>видео - PullRequest
       7

заменить <image>видео

0 голосов
/ 18 марта 2019

У меня есть SVG, который имеет упрощенную структуру, подобную этой:

 <svg viewbox="0 0 1000 2000">
   <image width="1024" height="2048" transform="<matrix A>" … />
 </svg>

И я хочу заменить изображение на элемент html5 <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>

Поэтому у меня есть этот код:

 [...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);
 });

Пока все в основном работает нормально, но я не могу заставить <video> отображаться в том же месте, что и изображение.В спецификации сказано:

(I)

[…] Включенный иностранный графический контент подвергается SVG-преобразованиям, фильтрам, отсечке, маскировке и компоновке […]

(II)

Синтаксический анализатор HTML обрабатывает элементы внутри 'foreignObject', эквивалентные элементам внутри фрагмента документа HTML.[…]

Принимая во внимание (I) : заменив изображение на <g>, в котором все преобразования скопированы с изображения, видео должно »житьв координатном пространстве «чем.

Принимая во внимание (II) , <video> должен стать корневым узлом нового фрагмента документа и вписаться в данную область.

Но результат выглядит так:

enter image description here

При этом: черная область представляет весь SVG, белая область - весь HTML-документ,который включает в себя SVG.Обе зеленые области обозначают / seam как видео, при этом большая часть - это та, которую я хотел бы получить.

Почему это / Чего мне не хватает?

ОБНОВЛЕНИЕ

Поскольку это зашло слишком далеко, я создал этот простой svg:

<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>

Что прекрасно работает в Firefox, но не в Chromium.Мне удается обрезать видео, добавив style="clip-path: url(#clip)" к видео, но <text> не отображается перед видео, в хроме.

Учитывая координаты видео, это работает:

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`;

1 Ответ

0 голосов
/ 18 марта 2019

Ваш видовой экран 1000x2000, но изображение 1024x2048.Я думаю, что обрежет ваше изображение.Может быть, это часть путаницы.

Далее: изображения масштабируются более свободно, чем видео, поскольку вы обычно хотите сохранить соотношение сторон видео.Вот почему вы получаете черные границы, когда размер видео не соответствует размеру контейнера.Убедитесь, что размер видео, размер изображения и область просмотра SVG совпадают.

Я также немного скептически отношусь к тому, что браузер может применять все преобразования SVG к видео.По крайней мере, в прошлом браузеры сами не отображали видео, а резервировали прямоугольную область на странице и отправляли координаты этой области в средство визуализации видео (которое может быть в другом процессе с использованием наложенного окна).Если вы не можете заставить это работать, попробуйте заменить весь SVG на видео.

Кроме того, вместо того, чтобы делать это в JavaScript, создайте небольшой локальный HTML-файл, который можно быстро настроить, пока видео не будет выглядетьправильный.Когда это сработает, начните с кода, который может трансформироваться между ними.В противном случае вы открываете слишком много банок с червями.

[Обновление 1]

Добро пожаловать в ад.Подождите немного ...

Вы можете попытаться использовать инструменты разработчика, чтобы узнать, что делает Chromium в этом случае.Возможно, создайте второй локальный тестовый пример, в котором вы попытаетесь поместить <div> с текстом поверх видео.Если это не сработает, тогда Chromium использует внешний рендерер для этого типа видео.

Это выглядит так же на экране, но за кадром, Chromium просит другой процесс расположить другое окно на экране таким образом, чтобы оно выглядело, как если бы оно было частью страницы.Если у вас есть инструмент, который может показывать вам координаты всех окон приложения на экране, вы можете видеть, что есть инструмент, который остается поверх окна вашего браузера.Клики переходят в это окно, Chromium не может их видеть и не может ничего визуализировать перед этим окном, потому что это окно кого-то другого (точно так же, как вы не хотели бы, чтобы Chromium отображал поверх текстового редактора, который оказываетсяоткрыть в окне браузера).

Параметры:

  1. Преобразовать в формат, который Chromium может отображать самостоятельно.См. https://www.chromium.org/audio-video для списка.Это, вероятно, только VP8, VP9 и Theora (= любой "открытый" формат видео).H.264 и MPEG-4 могут не работать, потому что киностудии паникуют из-за того, что вы можете украсть их драгоценные.
  2. Используйте наложение текста там, где оно работает, и перемещайте текст под видео там, где его нет.
  3. Используйте процесс на сервере, обслуживающий видеофайлы, чтобы вставить текст в видео перед его передачей в браузер.Некоторые форматы видео поддерживают субтитры, которые могут быть использованы для этого, если вам не нужно ничего необычного.Это избавит от необходимости перекодировать видео.
  4. Вывести текст и попросить посетителей установить браузер там, где он работает.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...