Arhn - архитектура программирования

Событие Click не запускается через youtube iframe в мобильном сафари

Я хотел бы разместить элементы управления взаимодействием над видео iframe на YouTube, и у меня все получилось, просто добавив wmode=opaque в качестве аргументов, а затем расположив элементы абсолютно над iframe.

Моя проблема в том, что в мобильном сафари - элементы управления сначала работают нормально, но когда я возвращаюсь из полноэкранного видео, они все отключены. Хотя на десктопе работает нормально.

HTML в основном:

<iframe src="http://www.youtube.com/embed/[ID]?wmode=opaque"></iframe>
<button id="btn">Click me</button>

И тогда кнопка расположена абсолютно над iframe.

Для демонстрации посетите эту скрипту, используя мобильное сафари: http://jsfiddle.net/SwGH5/embedded/result/

Вы увидите, что кнопка выдает предупреждение при нажатии. Теперь воспроизведите видео и нажмите «Готово». Затем попробуйте нажать кнопку еще раз...

Если бы фильм был встроен с использованием тега <video>, я мог бы прослушать событие завершения полноэкранного режима и что-то сделать, но теперь я застрял...

Вот скрипт: http://jsfiddle.net/SwGH5


  • Я далеко от своего компьютера для разработчиков, но у меня есть идея. Я сталкивался с подобными проблемами раньше (абсолютное положение, iFrames и т. д. на iOS). Самым странным решением, которое мы нашли, было добавление CSS-перехода к кликабельному элементу (кнопка для вас). Мы добавили переход, который ничего не делал (например, поворот 0). Однако мы не делали этого через iFrame YouTube. Если я вернусь к своей машине разработки, и она все еще открыта, я посмотрю на нее. 23.10.2013
  • Я бы не сказал, что они инвалиды. Они просто больше не стреляют. Если вы осмотрите кнопку, вы увидите, что событие прикреплено, а кнопка не отключена. Похоже на баг iOS. 23.10.2013
  • Я столкнулся с подобной проблемой в прошлом. Похоже, что, поскольку все видео в мобильном сафари обрабатываются изначально, нативное наложение имеет досадное последствие «поедания» сенсорных событий вместо того, чтобы передавать их в DOM ниже. Мне еще предстоит найти обходной путь. 24.10.2013
  • Только что попробовал на своем айфоне, та же проблема. Мне любопытно, если кто-нибудь знает решение. 26.10.2013
  • Я уверен, что вы уже пытались изменить z-index на iframe. Что если использовать старый код для встраивания YouTube – <object width="420" height="315"><param name="movie" value="//www.youtube.com/v/9u_hp7zPir0?version=3&amp;hl=en_US&amp;rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="//www.youtube.com/v/9u_hp7zPir0?version=3&amp;hl=en_US&amp;rel=0" type="application/x-shockwave-flash" width="420" height="315" allowscriptaccess="always" allowfullscreen="true"></embed></object>? При удаче? 30.10.2013
  • @Dom альтернатива flash не имеет смысла в мобильном сафари... 30.10.2013
  • Кажется, эта проблема решена для IOS 8. Кто-нибудь может это подтвердить? 29.03.2015

Ответы:


1

Поэтому я немного поиграл с iframe API и нашел решение. Это немного хакерски... но не совсем. Когда пользователь нажимает на видео, чтобы воспроизвести его, document.activeElement становится iframe. Когда пользователь нажимает кнопку «Готово», файл document.activeElement === document.body. Поэтому, когда видео начинает воспроизводиться, мы периодически проверяем, возвращается ли активный элемент в тело. На тот момент единственным решением, которое я нашел, было перерисовать iframe. В этом примере я уничтожаю () видео и воссоздаю его с помощью API iframe. Я также попытался клонировать iframe и успешно заменить его (я оставил этот код там, чтобы вы могли его увидеть):

http://jsfiddle.net/ryanwheale/SwGH5/105/

Это не лучшее решение, но оно работает. Кроме того, чтобы объяснить, что [я думаю] происходит - iOS перехватывает любой видеоконтент (Safari или Chrome) и воспроизводит его с помощью собственного видеоплеера. Любая функциональность ОС, подобная этой, выполняется «поверх» браузера, если хотите, - выше, чем любой z-индекс ... полностью вне браузера. Когда пользователь нажимает «Готово», собственный проигрыватель как бы уменьшает масштаб, как будто он повторно имплантирует себя на страницу. Я думаю, что родной проигрыватель все еще висит «над» браузером... что делает все, что находится под ним, недоступным. Тот факт, что кнопка кажется сверху, просто аномалия... из-за отсутствия лучшего описания.

27.06.2014
  • Спасибо! это мне очень помогло. 23.11.2014
  • Тестирование на iPhone 4 (iOS 7.1.2).. document.activeElement.tagName, по-видимому, продолжает возвращать BODY, что заставляет мой скрипт думать, что пользователь нажал «Готово». 02.12.2014
  • ОБНОВЛЕНИЕ: Ах, разница здесь, возможно, в том, что мое видео настроено на автовоспроизведение, которое работает на iOS 7, но я думаю, что это не устанавливает фокус на iframe. Так что, может быть, я мог бы просто программно установить фокус, когда видео начинает воспроизводиться, а затем теоретически он все равно должен переключаться на ТЕЛО, когда пользователь нажимает «Готово»? попробую.. 02.12.2014

  • 2

    РЕДАКТИРОВАТЬ: решение Райана Уила является лучшим решением этой проблемы и будет работать в большинстве случаев.

    Из документации Apple:

    На устройствах под управлением iOS с небольшими экранами, таких как iPhone и iPod touch, видео всегда воспроизводится в полноэкранном режиме, поэтому холст нельзя наложить на воспроизводимое видео. На устройствах под управлением iOS с большими экранами, таких как iPad, вы можете накладывать графику на холсте при воспроизведении видео так же, как на настольном компьютере.

    То же самое относится и к воспроизводимому видео. В в этой статье четко указано, что это невозможно.

    Обходной путь:

    Вы можете отсоединить и снова прикрепить элемент iframe к webkitfullscreenchange. Но для иностранного iframe это не сработает. Браузер не позволит вам манипулировать iframe DOM bec. междоменной политики. И даже если бы это было так, вы все равно могли бы скрыть наложение видео, чтобы добраться до своей кнопки.

    Поэтому единственным решением является отслеживание состояния YT.PlayerState.ENDED через YouTube iFrame API, а затем уничтожить и заново создать проигрыватель. Но не волнуйтесь, он играет плавно.

    window.onYouTubeIframeAPIReady = function () {
        var video = {
            player: null,
            create: function () {
                // first destroy if we already have the player
                if (video.player) { video.player.destroy(); }
                // create the player
                video.player = new YT.Player('ytp', {
                    videoId: '9u_hp7zPir0',
                    width: '620',
                    height: '290',
                    events: {
                        'onStateChange': video.onStateChange
                    }
                });
            },
            onStateChange: function (event) {
                // YT.PlayerState.ENDED » exiting full screen
                if (event.data === 0) { video.create(); }
            }
        };
        video.create();
    };
    

    Вот рабочая скрипка.

    28.06.2014
  • это действительно хорошее решение, и вы также можете сохранить вторую часть видео и использовать ее при воссоздании плеера, чтобы создать ощущение паузы. 29.06.2014
  • Конечное событие срабатывает только тогда, когда заканчивается видео. Больше раз, чем нет, пользователь будет нажимать «Готово» до того, как видео закончится ... даже если они просматривают видео целиком и нажимают «Готово» за 1 секунду до того, как видео фактически закончится. Мое решение обрабатывает каждый раз, когда пользователь нажимает кнопку «Готово» (выходит из полноэкранного режима). 30.06.2014
  • Ты прав. Кроме того, я перепроверил документы, на самом деле состояние 2 — это ПАУЗА, 0 — это КОНЕЦ. Кнопка наложения работает таким образом, но затем уничтожает видео при паузе. Я думаю, что ваше решение лучше. 30.06.2014

  • 3

    Если вы не можете заставить его работать с обычным iframe, вы можете рассмотреть возможность использования mediaelement.js, который может обернуть API Youtube в оболочку HTML5 Media API. Это прекрасно работает в Safari на iOS — попробуйте пример YouTube на mediaelementjs.com.

    Все, что вам нужно сделать, это добавить mejs js/css и поместить ваше видео на YouTube в качестве источника в тег видео, вот пример разметки, взятой с mediaelementjs.com:

    <script src="jquery.js"></script>
    <script src="mediaelement-and-player.min.js"></script>
    <link rel="stylesheet" href="mediaelementplayer.css" />
    <video width="640" height="360" id="player1" preload="none">
        <source type="video/youtube" src="http://www.youtube.com/watch?v=nOEw9iiopwI" />
    </video>
    

    Затем запустите плеер так:

    jQuery(document).ready(function($) {
        $('#player1').mediaelementplayer();
    });
    

    Если вы хотите добавить свою кнопку поверх проигрывателя mejs, она будет работать нормально, просто установите достаточно высокий z-индекс. Если вам нужна обычная кнопка воспроизведения, вы также можете подумать о стилизации существующей, которая поставляется с mejs.

    26.10.2013

    4

    Судя по комментариям к ответу @CullenJ, возможно, это может быть связано с некоторой проблемой в браузеры устройств iOS не запускают событие click для элементов iframe. В этом случае вам придется перейти с:

    document.getElementById('btn').onclick = function() {
        alert('clicked');
    }
    

    Что-то вроде этого (как ответил @smnh):

    $('#btn').on('click tap touchstart', function() {
        alert('clicked');
    });
    
    24.06.2014
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..