H5 criar seu próprio player de vídeo (JS Parte 2)

revisão

Bem não revisado diretamente huh JS1, aberta por escrito bvd.jsclipboard.png

Play video

  1. botão Play escondidos

  2. Vídeo começa a tocar
    quando clicar no botão play, um botão de reprodução será escondido, reproduzir o vídeo, isso não é difícil, em JS1 temos conseguido. Mas nós temos uma mudança de pensamento, toque para adicionar um vídeo clique evento, os jogadores de vídeo, e depois jogar evento é accionado, de modo que o botão play escondida

    pro.initEvent = function(){
        var that = this;
    
        //给播放按钮图片添加事件
        this.vimg.addEventListener('tap',function(){
            that.video.play();
        })
    
        //视频点击暂停或播放事件
        this.video.addEventListener('tap',function(){
            if(this.paused || this.ended) {
                //暂停时点击就播放
                if(this.ended) {//如果播放完毕,就重头开始播放
                    this.currentTime = 0;
                }
                this.play();
            } else {
                //播放时点击就暂停
                this.pause();
            }
        })
        
        //视频播放事件
        this.video.addEventListener('play',function(){
            that.vimg.style.display = 'none';
        })
        
        
        //获取到元数据
        this.video.addEventListener('loadedmetadata',function(){
            that.vC.querySelector('.duration').innerHTML = stom(this.duration);
        });
    }
  3. Escondido abaixo da barra de controle gradualmente
    ocultando não é a dificuldade, é importante escondido gradualmente, então aqui temos várias soluções:

    1. cronômetro

    2. quadros de animação CSS3

Aqui temos dois tipos de combinaçãoclipboard.png

Primeiro, vamos definir um bom conjunto de animação

@keyframes vhide {0% {opacity: 1;}100% {opacity: 0;}}

@-webkit-keyframes vhide {0% {opacity: 1;}100% {opacity: 0;}}

.vhidden {
    animation: vhide 3.5s ease-in;
    -webkit-animation: vhide 3.5s ease-in;
}

O seu papel é a transparência 1 => 0, facilidade-in efeito é excessivamente rápido de lenta para 3,5 segundos. animações CSS não entendem que você pode pedir de sua mãe oh
e então começar a jogar o vídeo quando o evento para a barra de controle adicionado classe de estilo vhidden

//视频播放事件
this.video.addEventListener('play',function(){
    that.vC.classList.add('vhidden');
})

Os resultados dos testes, e com certeza dentro de 3.5s, barra de controle lentamente claro, o problema é depois de 3.5s, a transparência de volta para o 1, e aqui eu explicar, porque os quadros de animação por padrão é rebote, podemos adicionar estilo

.vhidden {
    animation: vhide 3.5s ease-in;
    -webkit-animation: vhide 3.5s ease-in;
    animation-fill-mode:forwards;
    -webkit-animation-fill-mode: forwards;
}

CSS3 atributo, enchimento e modo de animação é utilizado para definir elementos como depois da animação.

O valor padrão de preenchimento-modo de animação é nenhum, isto é, sem quaisquer alterações após o final da animação, se após o fim dos-fill-mode animação para a frente para os elementos de estilo de animação vai se tornar a animação último quadro chave especificada estilo.

Depois de adicionar este estilo, e com certeza depois de 3.5s, a animação não vai se recuperar, mas aqui para olhar, mas barra de controle transparente não se foi, e se tivermos de escrever, em seguida, clique na barra do controle de tempo, assim no controle clique na posição bar, ou irá desencadear eventos, por isso, podemos escrever para um setTimeout para permitir que a barra de controle para esconder depois de 3.5s, isso podemos escolher o seu próprio

//视频播放事件
this.video.addEventListener('play',function(){
    that.vimg.style.display = 'none';
    that.vC.classList.add('vhidden');
    that.vCt = setTimeout(function(){
        that.vC.style.visibility = 'hidden';
    },3400);
})

Por processo de animação é 3.5s, mas a implementação é js após 3.4s, não apenas aqui para a animação-fill-mode de gravação: encaminha o caso para ser segurado

clipboard.png

jogando em

Ei, você pode reproduzir vídeo! Portanto, agora que pensar em jogar as coisas para fazer?

1. Controle bar barra de progresso crescem lentamente

Nós precisamos adicionar um vídeo timeupdate áudio evento e posição de reprodução de vídeo é alterada

Vamos começar os metadados do vídeo, no caso, a duração do vídeo para ganhar

//获取到元数据
this.video.addEventListener('loadedmetadata',function(){
    that.vDuration = this.duration;
    that.vC.querySelector('.duration').innerHTML = stom(that.vDuration);
});

Em seguida, calcular a razão, definir a barra de progresso do evento de atualização progresso da reprodução de vídeo de largura

//视频播放中事件
this.video.addEventListener('timeupdate', function() {
    var currentPos = this.currentTime;//获取当前播放的位置
    //更新进度条
    var percentage = 100 * currentPos / that.vDuration; 
    //设置宽度
    that.vC.querySelector('.timeBar').style.width = percentage + '%';
});

clipboard.png

Podemos ver a barra de progresso junho cada vez mais inflado.

2. O tempo de reprodução atual

Ao mesmo tempo, nós também mostrar o tempo jogando atualmente timeupdate conjunto de eventos

//视频播放中事件
this.video.addEventListener('timeupdate', function() {
    var currentPos = this.currentTime;//获取当前播放的位置
    //更新进度条
    var percentage = 100 * currentPos / that.vDuration; 
    that.vC.querySelector('.timeBar').style.width = percentage + '%';
    //更新当前播放时间
    that.vC.querySelector('.current').innerHTML = stom(currentPos);
});

clipboard.png

Pausar ou parar

Quando clicar no vídeo, se é para fazer uma pausa, em seguida, começar a jogar, e jogar o evento de disparo, enquanto que em reprodução de vídeo, clique no vídeo fará uma pausa, e evento de pausa gatilho.

0. prazos

La la la, a reprodução pausa, timeupdate eventos naturalmente não provocá-lo, de modo que a barra de progresso e o tempo de reprodução atual não vai se tornar amigos.

1. botão Play

Na pausa quando o botão show para Venha

//暂停or停止
this.video.addEventListener('pause',function(){
    that.vimg.style.display = 'block';
});

2 abaixo do visor barra de controle

exibição da barra de controle, remoção direta da classe estilo vhidden Jiuhaola

//暂停or停止
this.video.addEventListener('pause',function(){
    that.vimg.style.display = 'block';
    that.vC.classList.remove('vhidden');
    that.vC.style.visibility = 'visible';
});

Escrevê-lo parece ser verdade, mas se você ocultar a barra de controle antes que o tempo para escrever um setTimeout, então este tempo, devemos limpar oh.

//暂停or停止
this.video.addEventListener('pause',function(){
    that.vimg.style.display = 'block';
    that.vC.classList.remove('vhidden');
    that.vC.style.visibility = 'visible'; 
    that.vCt && clearTimeout(that.vCt);
});

Avançar e retroceder

Diao Diao barulho de como um pequeno player de vídeo pode ser menos de um retiro para ele resistente?

Venha, vamos adicionar o slide esquerda de slides direito evento de vídeo

//视频手势右滑动事件
this.video.addEventListener('swiperight',function(e){
    this.currentTime += 5;
});
//视频手势左滑动事件
this.video.addEventListener('swipeleft',function(e){
    this.currentTime -= 5;
});

Depuração pode progredir diretamente no computador se torna 0, no início Gostaria também de saber o que, mais tarde webview no telefone parece ser viável.

Sobre a barra de progresso e arraste para alterar o andamento de vídeo não tenho a intenção de escrever, porque eu não escrevi.clipboard.png

reprodução em tela cheia

Talvez estejamos mais preocupados com este direito:

ios final: a remoção da propriedade tag de vídeo webkit-playsinline pode ser, porque de ios h5 suportam a tag de vídeo é muito bom

//调用原生方式 全屏播放
pro.nativeMax = function(){
    if(!window.plus){
        //非html5+环境
        return;
    }
    if($.os.ios){
        console.log('ios')
        this.video.removeAttribute('webkit-playsinline');
    }else if($.os.android){
        console.log('android');
        var url = this.video.querySelector('source').src;
        var Intent = plus.android.importClass("android.content.Intent");
        var Uri = plus.android.importClass("android.net.Uri");
        var main = plus.android.runtimeMainActivity();
        var intent = new Intent(Intent.ACTION_VIEW);
        var uri = Uri.parse(url);
        intent.setDataAndType(uri, "video/*");
        main.startActivity(intent);
    }
}

Clique para adicionar eventos de tela cheia em initEvent

this.vC.querySelector('.fill').addEventListener('tap',function(){
    that.nativeMax();
});

Fazendo um ah mau gosto pouco, você não pode apontar para um comum?

A pergunta que eu realmente quero uma noite e decidiu trazer um pouco seco.

Dê estados o padrão para o mini player

var bvd = function(dom) {
    var that = this;
    $.ready(function() {
        //获取视频元素
        that.video = document.querySelector(dom || 'video');
        //获取视频父元素
        that.vRoom = that.video.parentNode;
        //元素初始化
        that.initEm();
        //事件初始化
        that.initEvent();
        //记录信息
        that.initInfo();
        //当前播放模式 false 为 mini播放
        that.isMax = false;
    })
}

//记录信息
pro.initInfo = function() {
    var that = this;
    //在onload状态下,offsetHeight才会获取到正确的值
    window.onload = function(){
        that.miniInfo = {//mini状态时的样式
            width: that.video.offsetWidth + 'px',
            height: that.video.offsetHeight + 'px',
            position: that.vRoom.style.position,
            transform: 'translate(0,0) rotate(0deg)'
        }

        var info = [
                document.documentElement.clientWidth || document.body.clientWidth,
                document.documentElement.clientHeight || document.body.clientHeigth
            ],
            w = info[0],
            h = info[1],
            cha = Math.abs(h - w) / 2;
            
        that.maxInfo = {//max状态时的样式
            width: h + 'px',
            height: w + 'px',
            position: 'fixed',
            transform: 'translate(-' + cha + 'px,' + cha + 'px) rotate(90deg)'
        }
    }
    
    
}

//全屏 mini 两种模式切换
pro.switch = function() {
    var vR = this.vRoom;
    //获取需要转换的样式信息
    var info = this.isMax ? this.miniInfo : this.maxInfo;
    for(var i in info) {
        vR.style[i] = info[i];
    }
    this.isMax = !this.isMax;
}

//全屏按钮
this.vC.querySelector('.fill').addEventListener('tap', function() {
    //that.nativeMax();
    that.switch();
});

Cara puxar, puxar um olhar

clipboard.png

Olha e se sente muito boa, usando o deslocamento e rotação CSS3, para que vídeo em tela cheia na frente da tela, mas o problema surgiu

  • Jogar botão e uma barra de controle em tela cheia parece esconder o fato de que os rótulos de vídeo cobrir a parte superior do elemento pai, nós temos que fazer ajustes correspondentes

css

.bad-video {
    position: relative;
    /*overflow: hidden;*/
    background-color: #CCCCCC;
}

JS
máximo entre o valor de ajuste de configuração zIndex

            that.maxInfo = {//max状态时的样式
                zIndex:99,
                width: h + 'px',
                height: w + 'px',
                position: 'fixed',
                transform: 'translate(-' + cha + 'px,' + cha + 'px) rotate(90deg)'
            }

clipboard.png

  • Após a completa horizontal, deslizando em torno dos eventos não acompanhou a mudança de direção

        //视频手势右滑动事件
        this.video.addEventListener('swiperight', function(e) {
            console.log('right');
            this.currentTime += 5;
        });
        //视频手势左滑动事件
        this.video.addEventListener('swipeleft', function(e) {
            console.log('left');
            this.currentTime -= 5;

        });

clipboard.png

TM Isto é muito embaraçoso, eu faço de tela cheia, o telefone na horizontal, também caiu avançar e retroceder?

Desta vez, como fazê-lo, não é quadrado

eventos gesto de deslizamento

Nós damos uma lista de eventos vídeo cadastrado

    var events = {};
    
    //增加 或者删除事件
    pro.eve = function(ename, callback, isF) {
        if(callback && typeof(callback) == 'function') {
            isF && arguments.callee(ename);
            events[ename] = callback;
            this.video.addEventListener(ename, events[ename]);
            console.log('添加事件:' + ename);
            return;
        }
        var fun = events[ename] || function(){};
        this.video.removeEventListener(ename, fun);
        console.log('删除事件:' + ename);
        return fun;
    }

Para o evento de vídeo para adicionar um agente para apagar adicionar um evento, ISF que é novo este mesmo evento antes do evento é excluído, uma vez que a adição de um evento com uma função anônima, ele não pode ser excluído, então configurar um proxy você pode dinamicamente adicionar eventos registrados no interior evento, fácil de operar

Então nós fazer progressos sobre como modificar as funções de reprodução e volume atual

    //跳转视频进度 单位 秒
    pro.setCurrentTime = function(t){
        this.video.currentTime += t;
    }
    //设置音量大小 单位 百分比 如 0.1
    pro.setVolume = function(v){
        this.video.volume+= v;
    }

Adicionar desliza para cima e para baixo sobre o evento através de um proxy para o vídeo

        //视频手势右滑动事件
        this.eve('swiperight',function(){
            that.setCurrentTime(5);
        });
        
        //视频手势左滑动事件
        this.eve('swipeleft', function(e) {
            that.setCurrentTime(-5);
        });
        
        //视频手势上滑动事件
        this.eve('swipeup',function(){
            that.setVolume(0.2);
        });
        
        //视频手势下滑动事件
        this.eve('swipedown', function(e) {
            that.setCurrentTime(-0.2);
        });

ok, as quatro direções dos eventos de deslizamento foram adicionados mais tarde, mas este é um evento quando o modo mini player, na reprodução em tela cheia, as quatro direções eventos não se alterou com elementos de vídeo e a direção da mudança, que precisam passar sob as mais a maneira mais estúpida para determinar se o evento para acionar a tela cheia

        //视频手势右滑动事件
        this.eve('swiperight',function(){
            if(that.isMax){
                return that.setVolume(0.2);
            }
            that.setCurrentTime(5);
        });
        
        //视频手势左滑动事件
        this.eve('swipeleft', function() {
            if(that.isMax){
                return that.setVolume(-0.2);
            }
            that.setCurrentTime(-5);
        });
        
        //视频手势上滑动事件
        this.eve('swipeup',function(){
            if(that.isMax){
                return that.setCurrentTime(-5);    
            }
            that.setVolume(0.2);
        });
        
        //视频手势下滑动事件
        this.eve('swipedown', function() {
            if(that.isMax){
                return that.setCurrentTime(5);    
            }
            that.setVolume(-0.2);
        });

Como, embora parece um pouco estúpido, mas é muito prático

5+ soluções cliente fullscreen

Embora o cliente 5+, android pode chamar a maneira nativa para jogar, mas ainda longe de ser satisfatória, podemos olhar para uma solução

Durante a inicialização, o tempo de gravação de mini-teste padrão, tela cheia, o vídeo, modificando a largura da altura da tela, a altura do vídeo é um vídeo largura modificar, reutilização 5+ rotação da tela, fornecida tela cheia, esconder a barra de estado

0) para remover evento de gesto determinar

因为现在是准备改变移动设备的方向,所以,手势方向会跟着设备方向改变

clipboard.png

1) a remoção de rotação e deslocamento css3


    //记录信息
    pro.initInfo = function() {
        var that = this;
        //在onload状态下,offsetHeight才会获取到正确的值
        window.onload = function() {
            that.miniInfo = { //mini状态时的样式
                zIndex: 1,
                width: that.video.offsetWidth + 'px',
                height: that.video.offsetHeight + 'px',
                position: that.vRoom.style.position
            }

            that.maxInfo = { //max状态时的样式
                zIndex: 99,
                width: '100%',
                height: that.sw + 'px',
                position: 'fixed'
            }

        }

    }

2) Ajuste a tela cheia com 5+ e ocultar a barra de status

    //全屏 mini 两种模式切换
    pro.switch = function() {
        var vR = this.vRoom;
        //获取需要转换的样式信息
        var info = this.isMax ? this.miniInfo : this.maxInfo;

        for(var i in info) {
            vR.style[i] = info[i];
        }
        this.isMax = !this.isMax;

        plus.navigator.setFullscreen(this.isMax);
        if(this.isMax) {
            //横屏
            plus.screen.lockOrientation("landscape-primary");
        } else {
            //竖屏
            plus.screen.lockOrientation("portrait-primary");
        }

    }

3) o modo de ecrã cheio, android final da tecla de retorno, o gatilho para sair do ecrã completo

pro.initEvent = function() {
    //.......省略其他代码
    
    this.oback = $.back;
        //监听安卓返回键
        $.back = function() {
            if(that.isMax) {
                that.switch();
                return;
            }
            that.oback();
        }
}

renderings
1.gif

5+ gravidade interruptor de detecção de tela cheia

Ei, como pode um pouco tinha alternar automaticamente a qualquer forma de tela no fim do jogador de movê-lo?
Em uma pequena parte deles contou sobre como manualmente alternar tela cheia, interruptor de sensor de gravidade próxima tela horizontal, a necessidade de usar a API 5+ acelerómetro sensor de aceleração

简单说:重力加速度感应可以想象成一个小球在坐标系中
三个方向上的加速度。永远以手机屏幕为准

Qual é a aceleração? A quantidade, é o livro físico em

手机水平放置向上是y轴正向
向右是x轴正向,向外是z轴正向

O que é XYZ? A quantidade é sobre o elevado número de livros

Oh, você coloca os retos retrato telefone no chão, você que andam na retidão subiu, e agora você está parado na tela do seu telefone, então você abrir a mão direita em linha reta, que é o eixo-x, agora você está olhando para a frente, o que é o eixo y, z-eixo é a sua cabeça. Essa conversa não entende, mas não realmente deseja etapa em seu telefone, 23333

Você também pode optar por ver uma explicação adicional: Android-Sensor Desenvolvimento - determinar a direção

  1. x, eixo-y alterações:

    Quando o ecrã do telefone é colocado horizontalmente se: (x, y, z) = (0, 0, -9,81)
    quando a parte superior do elevador telefone: y é reduzida, e é negativo
    quando o fundo quando se levanta o telefone: y aumenta, e é positiva
    quando o telefone elevador direito: x é reduzido, e um valor negativo
    quando o telefone deixou de elevador: x aumenta, e positiva

  2. Mudanças no eixo z:
    ecrã do telefone é para cima horizontalmente, z = -9,81
    quando o ecrã do telefone verticalmente, z = 0
    , quando o telefone é colocado horizontalmente para baixo da tela, Z = 9,81

  3. tela vertical estado de comutação
    y <= - 5, a comutação da vertical
    x <= - 5, o transdutor é um laterais

ok, adicionamos dois métodos para a abertura e fecho do dispositivo de monitorização

    //开启方向感应
    pro.startWatchAcc = function(){
        var that = this;
        this.watchAccFun = plus.accelerometer.watchAcceleration(function(a) {
                if(that.getIsMax()){
                    //当前为全屏状态
                    //判断是否满足竖屏Mini状态
                    a.yAxis>=5 && that.setIsMax(false);
                }else{
                    //当前为Mini状态
                    //判断是否满足全屏Max状态
                    Math.abs(a.xAxis) >=5 && that.setIsMax(true); 
                }
            }, function(e) {
                //出错了大不了 不自动旋转呗  让它手动 切换
                console.log("Acceleration error: " + e.message);
                that.clearWatchAcc();
            },{
                frequency:1200
            });
    }
    //关闭方向感应
    pro.clearWatchAcc = function(){
        this.watchAccFun && plus.accelerometer.clearWatch(this.watchAccFun);
    }

Em seguida, ativado por padrão durante o monitoramento direção inicialização

    var bvd = function(dom) {
        var that = this;
        $.ready(function() {
            //...
        })

        $.plusReady(function() {
            that.startWatchAcc();
        })

    }

Depois mudou para horizontal de duas vias tela cruz completa,

clipboard.png

Dê uma olhada na depuração máquina real

ziong.gif

Hey, nós adicionamos um bloqueio para dar botão de reprodução de tela cheia, sensor de gravidade para que o dispositivo não monitora nem pausa resposta do evento Clique para reproduzir vídeo

Faça um botão de bloqueio

clipboard.png

Claro, lock imagens, endereço também mudou com base64, na melhor das hipóteses js etiquetas geradas dinamicamente

clipboard.png

Definir seu estilo básico, direita, para cima e para baixo verticalmente centrado, oculta por padrão

        .lock {
            padding: .3rem;
            width: 3rem;
            height: 3rem;
            position: absolute;
            right: .5rem;
            top: 50%;
            transform: translateY(-50%);
            -webkit-transform: translateY(-50%);
            visibility: hidden;
        }

clipboard.png

Bem, vamos resolver a lógica,

1) por padrão quando jogar mini, bloqueio hide
2) reprodução em tela cheia, bloquear a exibição, mas seguirá a barra de controle para a direita no 4S
3) tela cheia para pausa, controle de bloqueio seguidos são sempre exibidos
4) Clique quando o bloqueio está bloqueado, Dica bloqueado, ocultar a barra de controle imediatamente, escondido dentro de certas lock4s, substituir o vídeo ícone de bloqueio de exibição de eventos click, android evento chave de retorno, sem qualquer alteração, perto monitoramento de gravidade
5) quando você clica bloqueio desbloqueado, desbloqueado solicitação, digite retorno android em vez disso comutado para a mini-estado, monitorização gravidade aberto

Eu esfregar, é realmente muito deprimente, principalmente processamento de lógica mais dolorosa

0) Adicionar uma animação em movimento logo após 3s atrasar dentro de 1s após a execução de animação

@keyframes lockhide {0% {transform: translate(0%,-50%);}100% {transform: translate(120%,-50%);}}

webkit-keyframes lockhide {0% {transform: translate(0%,-50%);}100% {transform: translate(120%,-50%);}}

.lockhidden {
    animation: lockhide 1s 3s linear;
    -webkit-animation: lockhide 1s 3s linear;
    animation-fill-mode:forwards;
    -webkit-animation-fill-mode: forwards;
}

1) bloqueio tela cheia

    pro.switch = function() {
        //...
        //全屏时 显示锁定 图标
        this.vlock.style.visibility = this.isMax ? 'visible' : 'hidden';

    }

2) reprodução em tela cheia, bloquear a exibição, mas seguirá a barra de controle para a direita nas 4s
animações escondidas somarmos bloqueio quando jogar,

clipboard.png

3) pausa de ecrã cheio, os controlos de bloqueio são sempre apresentadas seguido

clipboard.png

4) Clique no cadeado para fechamento, fechado rápida, imediata barra de controle ocultos, escondidos lock4s dentro certas, substituir o ícone de cadeado exibição de vídeo de eventos click, android evento chave de retorno, sem qualquer alteração, perto monitoramento de gravidade
5) Clique no cadeado desbloqueado, Dica desbloqueado, chave de retorno android vez mudar para mini-estado, abra o monitoramento gravidade

    //锁定屏幕
    pro.lockScreen = function() {
        $.toast('锁定屏幕');
        var that = this;
        //更换video点击事件为 显示 lock图标,并保存 video之前的事件 
        this.videoTapFn = this.eve('tap', function() {
            that.lockT = setTimeout(function(){
                that.vlock.classList.add('lockhidden');
            },500);
                //重新开始播放样式
            that.vlock.classList.remove('lockhidden');
            that.vlock.style.visibility = 'visible';
        }, true);
        //隐藏控制条
        this.vC.style.visibility = 'hidden';
        //给Lock图标增加 隐藏样式类
        this.vlock.classList.add('lockhidden');
        //锁定屏幕时,不监控重力感应
        this.clearWatchAcc();
        //标识当前更改的Lock状态
        this.isLock = true;

    }

    //解锁屏幕
    pro.unlockScreen = function() {
        $.toast('解锁屏幕');
        //替换回video之前的点击事件
        this.eve('tap', this.videoTapFn, true);
        //给Lock图标清楚 隐藏样式类
        this.vlock.classList.remove('lockhidden');
        //不锁定屏幕时,监控重力感应
        this.startWatchAcc();
        //标识当前更改的Lock状态
        this.isLock = false;
    }

666) Finalmente, para o nosso ícone de cadeado querido aumentar um evento de toque, eo evento android retornar principais mudanças

        //全屏 时 锁定点击事件
        this.vlock.addEventListener('tap', function() {
            if(that.isLock) {
                that.unlockScreen();
                return;
            }
            that.lockScreen();
        });

        this.oback = $.back;
        //监听安卓返回键
        $.back = function(){
            if(that.isMax){
                if(!that.isLock){
                    //全屏状态下 按下返回键 时,1s内不监控重力,防止返回Mini状态时和重力感应并发事件
                    setTimeout(function(){
                        that.startWatchAcc();
                    },1000);
                    that.clearWatchAcc();
                    that.switch();
                }
                return;
            }
            that.oback();
        }
    }

Bem! Esta demo artigo 5+ fullscreen endereço de origem

Escrever blog não é fácil, mas que compartilham o clima é muito bom, não é outra revisão e progresso?

Obrigado.

Este artigo Artigos relacionados: H5 criar sua própria coluna player de vídeo

Acho que você gosta

Origin www.cnblogs.com/10manongit/p/12616555.html
Recomendado
Clasificación