微信小程序Video组件实践总结

[复制链接]
查看: 2481|回复: 9
  • 萌哒
    2018-11-19 14:03
  • 发表于 2019-1-31 20:31:54 | 显示全部楼层 |阅读模式

    马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    我司微店+小程序最近有需要在商品详情里面添加视频的功能,故使用了微信官方组件,在使用过程中遇到了一些问题,有些问题特别坑,我觉得有必要总结一下,分享出来供有这方面需求的同行参考,本篇文章我主要讲解最终我使用的兼容性比较好的方案,希望能帮助有需要的童鞋。

    我们要实现的布局
    102808j7vq5o6vobhtbfbm.png

    • video上面有个覆盖video的图片,在图片上有个控制播放的按钮
    • video上面有视频和图片切换按钮组合,视频播放的时候该组合按钮也必须存在
    102808j7vq5o6vobhtbfbm.png
    按照常规的写法,我们的代码结构可能如下
    <span class="hljs-tag"> <span class="hljs-tag"></span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"video/span> <span class="hljs-tag"> <span class="hljs-tag"> <span class="hljs-tag"></span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"view/span> </span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"view/span> <span class="hljs-tag"></span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"view/span></span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"view/span>复制代码然后通过图片 position:absolute 绝对定位, z-index 层叠上下文来完成布局,这种方式在ios系统下表现还好,在一些安卓机上图片和按钮就会被video组件覆盖,这是因为 video 组件是原生组件,使用上有一些限制,具体限制可以看这里微信官方文档,在这里主要影响我们的原因是,原生组件的层级是最高的,所以页面中的其他组件无论设置z-index为多少,都无法盖在原生组件上。
    幸好,微信官方提供了 cover-view 与 cover-image 组件,可以覆盖原生组件上面。通过使用,我们的方案如下:
    <span class="hljs-tag"> <span class="hljs-tag"> <span class="hljs-tag"> <span class="hljs-tag"></span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"cover-image/span> <span class="hljs-tag"></span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"cover-image/span> </span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"cover-view/span> </span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"video/span></span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"view/span>复制代码播放功能

    单个视频,点击播放

    有关video组件播放的几个配置,主要有

    • src 要播放视频的资源地址
    • autoplay 是否自动播放
    另外,微信还提功能了 const video = wx.createVideoContext() 方法可以获得一个video实例,通过video.play()方法来控制播放。
    故有几种方案:
    第一种方案,拿到视频地址后,通过 setData 方法更新video组件地址和自动播放为true,该方法优点是由组件自身控制开始播放时间,基本不会存在 黑屏或者视频加载出来不播放的情况 ,但缺点是切换到其它页面再回来,每次都需要重新加载视频,性能和体验上不是很好。
    this.setData({ src:url, autoplay:true}<span class="xml">)</span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"video/span>复制代码第二种方案,src地址通过data传入,之后无需变化,但存在的问题就是视频播放的时机,因为视频地址加载是需要时间的,如果我们在页面一渲染后就点击播放按钮,此时如果视频还未加载完,直接调用 videoContext.play() 方法可能会失效,故我们需应该等待视频加载完之后,才调用 play() 方法。这种方案可以只需加载一次视频,之后播放无需重新加载,用户体验较好,另外对于无法控制播放时机问题做了处理,基本不会出现 黑屏 的情况
    data:{ autoplay:false}const { videoContext } = this.data;this.setData({ autoplay:true},()=>{ videoContext.play()}<span class="xml">)</span class="hljs-name"style="color: rgb(51, 51, 51); font-weight: 700;"video/span>复制代码单个视频,wifi下自动播放

    微信提供判断网络环境的api,通过api判断,如果是wifi下,就主动调用 videoContext.play()方法。
    wx.getNetworkType({ success(res) { const networkType = res.networkType; if (networkType === 'wifi') { that.videoPlay(); } }, });复制代码视频不在可视范围,停止播放

    微信提供 IntersectionObserver 对象,用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见,以前判断元素是否在视图内,我们常用的是 getBoundingClientRect ,该方法在微信环境也能使用,但该方法因为需要计算元素位置,引起页面重绘,比较影响性能。而 IntersectionObserver 是原生自己判断位置,不会有相关问题,可以通过这个api来监听元素位置,从而控制是否播放。
    wx.createIntersectionObserver(that) .relativeToViewport() .observe('.video--wrap', res => { if (res && res.intersectionRatio > 0) { that.videoPlay(); } else { that.videoPause(); } });复制代码视频列表

    一开始我是用过 wx:for 列举视频播放组件,子组件播放,触发一个事件,父组件监听子组件事件,更新视频列表值,然后子组件监听属性变化来更新播放状态的,该方案在ios上表现不错,可是放在安卓上, 页面竟然不能滚动了 ,后面通过查阅资料,video列表组件不能直接像普通图片列表一样,真正的方案是需要用视频首帧图片做列表,然后点击首帧图片,跳转到一个新页面,或者一个蒙层播放视频。
    小程序左滑右滑实现

    我们需求上还有左右滑切换图片和视频显示的功能,这需要通过监听 touchstart 和 touchmove 来判断手机滑动方向,从而切换视频和图片的显示位置。
    touchstart: function(e) { this.setData({ startX: e.changedTouches[0] && e.changedTouches[0].clientX, startY: e.changedTouches[0] && e.changedTouches[0].clientY, }); },touchmove: function(e) { var that = this, startX = that.data.startX, //开始X坐标 startY = that.data.startY, //开始Y坐标 touchMoveX = e.changedTouches[0].clientX, //滑动变化坐标 touchMoveY = e.changedTouches[0].clientY, //滑动变化坐标 },//根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑动GetSlideDrection: function(startX, startY, endX, endY) { var dy = endY - startY; var dx = endX - startX; var result = 0; //如果滑动距离太短 if (Math.abs(dx) < 2 && Math.abs(dy) < 2) { return result; } var angle = this.GetSlideAngle(dx, dy); if (angle >= -45 && angle < 45) { result = 4; } else if (angle >= 45 && angle < 135) { result = 1; } else if (angle >= -135 && angle < -45) { result = 2; } else if ((angle >= 135 && angle = -180 && angle < -135)) { result = 3; } return result; },GetSlideAngle: function(dx, dy) { return (Math.atan2(dy, dx) * 180) / Math.PI;},复制代码以上方案都可以通过小程序代码片段进行查看
    点击查看方案
    调试

    开发者工具和真机表现差异很大,故在开发者工具上开发完之后,需要多在不同真机上进行调试。
    总结

    实际我在开发中碰到的问题还挺多,小程序video组件坑还是挺多的,我没有一一描述出来,如果你有碰到其它问题,欢迎留言评论,如果我曾经碰到过,或许能够提供一些意见,我写这篇文章的目的就是让更多的小程序开发者尽量少踩坑,如果刚好能够帮助到你,感谢点赞支持!
    发表于 2019-1-31 20:49:47 | 显示全部楼层
    回的人少,我来小顶一下
    回复

    使用道具 举报

    发表于 2019-2-3 12:49:45 | 显示全部楼层
    么有分,谁能送我点积分啊::>_<::
    回复

    使用道具 举报

    aki

    发表于 2019-2-3 19:12:09 | 显示全部楼层
    额,看不懂在说神马~@_@
    回复

    使用道具 举报

    发表于 2019-2-5 15:14:24 | 显示全部楼层
    啥也不说了,感谢楼主分享哇!
    回复

    使用道具 举报

    发表于 4 天前 | 显示全部楼层
    确实是难得好帖啊,顶先
    回复

    使用道具 举报

    发表于 3 天前 | 显示全部楼层
    正需要,支持楼主大人了!
    回复

    使用道具 举报

    发表于 3 天前 | 显示全部楼层
    珍惜生命,果断回帖。
    回复

    使用道具 举报

    发表于 3 天前 | 显示全部楼层
    这个帖一般般,还可以哦。
    回复

    使用道具 举报

    发表于 3 天前 | 显示全部楼层
    我只是路过打酱油的
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

     
     
    技术支持
    在线客服
    售后交流群瑞恩社区™售后</font><br><span>交流
    工作时间:
    8:00-18:00
    客服热线:
    15368564009
    微信扫一扫
    返回顶部 关注微信 下载APP 返回列表