前景知识

要实现小程序类似抖音上下滑动预览视频,就我了解的,方案可以分为两种
1、利用原生组件swiper(据说很卡,我也试过,好像是有点不流畅)
2、自己实现一个上下滑动效果(只需要监听一组事件,判断上拉还是下拉,接着就是移动dom)

这里就采用第二种方案自己实现 ps: (本案例基于字节小程序,由于字节已经实现原生组件同层渲染,所以这里不考虑组件层级问题,如果是其他平台,可能需要结合实际解决同层渲染问题,思路应该是一致的)

先看效果:

布局

笔者准备在视频列表外嵌套一个大盒子,这个大盒子就用于监听触摸事件(由于是自己实现上下滑动画,所以这个盒子高度应该是内容区域高度,且设置 overflow: hidden 避免出现盒子自己的滚动条);内层就是需要添加动画的盒子+视频列表

<!-- 大盒子 -->
<view class="video-box" bindtouchstart="onTouchStart" bindtouchmove="onTouchMove"bindtouchend="onTouchEnd"><!-- 上滑滑动 动画盒子 --><view class="ani-box" animation="{{animationData}}"><!-- 视频列表 --><view tt:for="{{videoList}}" :key="{{item.id}}" class="item-{{item.id}} item"  ><videoid="video-{{index}}"src="{{item.src}}"autoplay="{{false}}"loop="{{true}}"object-fit="fill"show-fullscreen-btn="{{false}}"vslide-gesture-in-fullscreen="{{false}}"/></view></view></view>

所以由上布局可以确定思路:在 video-box 上监听触摸事件,用 ani-box 控制上下滑动

触摸事件

原理就是记录下触摸开始位置+结束位置,两者y坐标差值,即可得知是上拉还是下拉(通常会有一个缓冲距离,这里设置为30,30以内不触发)

// 触摸开始onTouchStart({ touches }) {const { pageY } = touches[0]this.setData({startPage: pageY})// console.log('按下',pageY)},// 触摸移动onTouchMove({ touches }) {// const { pageY } = touches[0]// console.log('移动',pageY)},// 触摸结束onTouchEnd({ changedTouches }) {const { pageY } = changedTouches[0]const diff = pageY - this.data.startPageif(Math.abs(diff) <= 30) {console.log('不触发')return}if(diff > 0) {this.setAni(1)}else if( diff == 0) {this.setAni(0)}else{this.setAni(-1)}},

动画

上面知道了是上拉还是下拉,接下来就是滚动整个列表。其实滚动高度始终是 内容区域高度的整数倍(这里暂时不做像swiper那样,边触摸边移动的效果,而直接滑动后,直接滚动到下一个视频,所以是整数倍)

  // 获取内容高度高度getViewHeight() {return new Promise((resolve) => {const query = tt.createSelectorQuery()// 也可以直接获取可视区域高度,结合实际情况query.select(".item-1").boundingClientRect()query.exec(function (res) {if(res.length && res[0]) {viewHeight = res[0].heightresolve(viewHeight)}})})},// 动画实现moveY = -1 * nowIndex * viewHeightanimation.translateY(moveY).step()this.getVideoCtx(nowIndex)this.setData({animationData: animation.export()})

如果对小程序动画api不熟悉的,可以去看下createAnimation。这里主要思路是:滚动总高度 = 内容高度 * 滚动到第几个 ;假设当是第一个视频,要滚动到第二个视频,则滚动高度 = 1 x 内容高度,要滚动到第三个视频则滚动高度 = 2 x 内容高度

完整js

let animation = null
let viewHeight = 0Page({data: {videoList: [{id: 1,src: 'xxx',},{id: 2,src: 'xxx',},{id: 3,src: 'xxxx',}],oldId: -1,startPage: 0,animationData: {},viewIndex: 0},onLoad: function () {this.getViewHeight()this.getVideoCtx(0)},getVideoCtx(id) {// 有上一个if(this.data.oldId > -1) {tt.createVideoContext(`video-${this.data.oldId}`).pause()}const ctx = tt.createVideoContext(`video-${id}`)// console.log(ctx)ctx.play()this.setData({oldId: id})},// 触摸开始onTouchStart({ touches }) {const { pageY } = touches[0]this.setData({startPage: pageY})// console.log('按下',pageY)},// 触摸移动onTouchMove({ touches }) {// const { pageY } = touches[0]// console.log('移动',pageY)},// 触摸结束onTouchEnd({ changedTouches }) {const { pageY } = changedTouches[0]const diff = pageY - this.data.startPageif(Math.abs(diff) <= 30) {console.log('不触发')return}if(diff > 0) {this.setAni(1)}else if( diff == 0) {this.setAni(0)}else{this.setAni(-1)}},// 滑动动画 0 不移动 -1 上拉 1 下拉async setAni(status) {if(status == 0) return falseif(!animation) {animation = tt.createAnimation({duration: 500,timingFunction: 'ease'});}if(!viewHeight) {await this.getViewHeight()}// 计算位移let moveY = 0let nowIndex = this.data.viewIndexstatus > 0 ? nowIndex-- : nowIndex++if(nowIndex < 0) {tt.showToast({title: '到顶部了'})return}if(nowIndex == this.data.videoList.length) {tt.showToast({title: '到底了哦'})return}moveY = -1 * nowIndex * viewHeightanimation.translateY(moveY).step()this.getVideoCtx(nowIndex)this.setData({animationData: animation.export(),viewIndex: nowIndex})},// 获取dom高度getViewHeight() {return new Promise((resolve) => {const query = tt.createSelectorQuery()query.select(".item-1").boundingClientRect()query.exec(function (res) {if(res.length && res[0]) {viewHeight = res[0].heightresolve(viewHeight)}})})},
})

添加一下css

ps:这是后面补充的(仅供参考)

.video-box{height: 100vh;overflow: hidden;position: relative;
}
.item{width: 100%;height: 100vh;
}
video{width: 100%;height: 100%;
}
.ani-box{position: absolute;top: 0;bottom: 0;left: 0;right: 0;transform: translateY(0px);z-index: -1;
}

补充

动画:在做时踩了一个坑,添加动画的盒子需要设置初始css状态translateY = 0,导致一直没反应,这一点其实跟css过渡是一样的,整个动画应该是 0 --1 的过程,而不是 无 – 有 (好比 display none — block 添加过渡是无效的)
个人感觉 video标签 可以考虑始终使用一个,滑动只切换视频地址,或许这样性能会更好点(但是这样会导致滑动后,每一个视频都会重新加载,不会是上一次加载位置)

小程序模仿抖音上下滑动视频相关推荐

  1. 微信小程序仿抖音上下滑动整屏切换视频

    微信小程序仿抖音上下滑动整屏切换视频 使用官网上面的扩展组件 官方使用的方式: 可结合自己业务修改: 使用官网上面的扩展组件 https://developers.weixin.qq.com/mini ...

  2. 17_微信小程序之抖音微视无限滑动视频列表自定义组件编写

    微信小程序之抖音微视无限滑动视频列表自定义组件编写 一.先上效果图 看到上面,你可能首先会想到,使用swiper然后将swiper的circular设置为true,那么,想象一下,假如视频很多的情况下 ...

  3. 微信小程序实现抖音切换视频效果

    微信小程序实现抖音切换视频效果 思路: 使用微信小程序的swiper组件,使其竖向滑动 分页加载,每次加载3个视频,当滑动到只剩1个视频时加载下一页 问题: 加载多个视频时,多个视频会同时播放 效果图 ...

  4. 微信小程序仿抖音视频

    微信小程序仿抖音视频 使用轮播图实现视频滑动效果. wxml 部分 <view class="video-contain"><!-- 自定义头部 -->&l ...

  5. 微信小程序和抖音小程序的区别?如何选择?

    随着5G的到来,电商向多元化新型电商的转型也已成时代必然.2020年,当我们的Vlog.自媒体行业风生水起时,依托第三方的电商平台销售模式已经逐渐难以满足新型电商的应用场景,例如微信的私域流量.抖音对 ...

  6. WordPress微信小程序,WordPress百度小程序,WordPressQQ小程序,WordPress今日头条小程序,WordPress抖音小程序,WordPress多端小程序

    WordPress微信小程序,WordPress百度小程序,WordPressQQ小程序,WordPress今日头条小程序,WordPress抖音小程序,WordPress多端小程序. WordPre ...

  7. 从微信小程序到抖音小程序:转换指南

    抖音小程序是一种新兴的小程序平台,与微信小程序类似,都是基于小程序框架的开发,不过两者的开发环境和API有所不同.如果你已经开发了一款微信小程序,想要将其转换为抖音小程序,可以按照以下步骤进行: 1. ...

  8. 微信小程序与抖音小程序的区别

    1. 前缀区别:tt 与 wx 2. 调用前一个页面的方法时 微信小程序 let pages = getCurrentPages(); let prePage = pages[pages.length ...

  9. 微信小程序实现 短视频无限播放效果(类似快手小程序,抖音app的短视频滑动)

    实现原理 利用小程序内置组件 swiper+video 来制定逻辑的方向 实现方式 设定swiepr-item数量为4,也就是在swiper里面同时展示4个video,避免过多导致页面卡顿例: (假设 ...

最新文章

  1. 机会的度量:概率和分布
  2. javascript操作对象的方法
  3. [密码学基础][信息安全][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第一篇]不同类型的处理器
  4. Redis整合Springboot实现单机配置
  5. cp210x驱动怎么安装_电脑声卡驱动怎么安装,教你三步搞定声卡驱动
  6. MongoDB Documents
  7. C基础(36——40)
  8. 拓端tecdat|R语言深度学习不同模型对比分析案例
  9. 【技术】H5网页调用手机摄像头扫码
  10. 计算机检索的主要方法,计算机检索主要途径和方法
  11. python和html和css什么关系什么区_Python 【第七章】:Html 和 CSS
  12. C++复习1:一些概念
  13. mysql的填充因子_SQL Server表索引:调整填充因子
  14. 上市公司环境投资数据(2009-2020年 )
  15. ios描述文件的申请
  16. python 通达信公式函数_通达信zig函数的python实现
  17. android各种文件夹路径
  18. 菜鸟网络布局智慧物流 物流大数据走热
  19. 通过NASA卫星,带你看真实的亚马逊火灾
  20. 魅族mx4 android5.0,魅族MX4 Pro长测(2):安卓5.0 Flyme体验

热门文章

  1. qq机器人更新一个点歌的插件
  2. This system supports the C.UTF-8 locale which is recommended. You might be able to resolve your issu
  3. AAAI 2021:一种跨城市迁移的新冠肺炎高危社区发现框架
  4. 第四届蓝桥杯真题解析【JavaC组】
  5. Java数据结构3_单链表 Linked List
  6. (转)IsNull和IsEmpty的区别
  7. Python之re模块讲解及其案例举例
  8. 10年10倍的公募基金经理 “一次把10年的话都说了”
  9. 冀教版五年级计算机教学计划,冀教版五年级英语下册教学计划范文
  10. Android EditText输入限制及字符编码