React&Taro仿抖音小程序&H5(一)

本文介绍了使用Reacthooks和Taro3框架开发仿抖音H5和小程序的过程,实现了视频上下滑动、播放暂停控制、进度条显示等功能。核心代码包括Swiper组件的使用、视频上下文管理和自动播放逻辑。项目已发布在GitHub,并将持续更新。
摘要由CSDN通过智能技术生成

仿抖音 h5 & 小程序

React hooks + Taro 3 + Taro UI

目前还在开发中,暂时实现了一部分逻辑,源码已发布github在文章最下边
h5端效果预览,在线预览地址:https://lionelsun.github.io/taroTictok
用到的测试视频资源来自@MK965
在这里插入图片描述

1.实现功能

  1. ✅基础布局
  2. ✅视频上下滑动
  3. ✅停止上条视频并重置进度
  4. ✅单击暂停播放 (禁用自带控制)
  5. 🔛双击暂停播放 (实现中)
  6. ✅播放进度条 (实时监听当前视频进度并显示)
  7. ✅视频上下滑动 (停止上条视频并重置进度)
  8. ✅视频自动播放 (分别实现h5&小程序的功能)
  9. 🔛评论 (实现中)
  10. 🔛跳转&切换应用暂停播放 (实现中)
  11. 🔛其余功能完善中…

2.核心代码

dom结构

return (
    <View>
      <Swiper //swiper容器实现视频上下滑动
        className='videoMain'
        disableTouch
        current={current}
        vertical={datas.vertical}
        circular={datas.circular}
        indicatorDots={datas.indicatorDots}
        onChange={swiperChange}	
        key={props.dataScore.length.toLocaleString()}
      >
      	//props.dataScore为视频数组
        {props.dataScore.map((item: any, index: number) => (
          <SwiperItem
            key={item.id}
            className='SwiperItem'
            id={`swi_${item.id}`}
            onClick={touchv}	//单双击方法
          >
            <View className='videoCtrl'>	//视频上层内容 头像,昵称,title,爱心图标等
              <View className='info'>
                <Text className='userName'>@ {item.title}</Text>
                <Text className='videoTitle'>{item.desc}</Text>
              </View>
              <AtProgress
                percent={parseFloat(progress)}
                isHidePercent
                className='TimeUp'
              />
            </View>
            //仅渲染视频前后一条,防止同时请求过多视频卡顿
            {current === index ||
            current - index === 1 ||
            current - index === -1 ? (
              //视频
              <Video
                src={item.vUrl}
                poster={`${item.vUrl}?vframe/jpg/offset/1`}
                showCenterPlayBtn={false}
                showPlayBtn={false}
                showFullscreenBtn={false}
                showProgress={false}
                objectFit='cover'
                controls
                loop
                onTimeUpdate={onProgress}
                x5-video-player-type='h5-page'
                webkit-playsinline='true'
                x5-playsinline='true'
                x5-video-orientation='portraint'
                className='video'
                id={`id${index}`}
              ></Video>
            ) : (
              ""
            )}
          </SwiperItem>
        ))}
      </Swiper>
      <View>
        <AtCurtain
          isOpened={curtain}
          onClose={() => {
            setCurtain(false);
            touchv();
          }}
        ></AtCurtain>
      </View>
    </View>
  );

用到的参数及作用

const VideoScroll = memo((props: propType) => {
  const [current, setCurrent] = useState<number>(0);                  //视频下标
  const [curtain, setCurtain] = useState<boolean>(false);             //显示幕帘
  const [paused, setPaused] = useState<boolean>(true);                //当前视频播放状态
  const [progress, setProgress] = useState<string>("0%");             //当前视频进度跳
  ...
 }

swiper切换时控制 暂停以及自动播放

/**
   * 视频切换
   * @param event
   * 停止上一个视频播放
   * 播放当前视频
   */
  const swiperChange = (e: any) => {
    let vCurrent = 0;
    if (e.detail) vCurrent = e.detail.current;
    props.onChange(vCurrent);
    let videoContext = getVideoContext(vCurrent, 1); //当前视频上下文
    //暂停上一条
    // if (vCurrent !== 0) {
      let videoContextPrev = getVideoContext(current, 2); //上一个视频上下文
      //停止上一条视频播放/加载
      console.log(vCurrent , current);
      if (vCurrent != current) {
        if (process.env.TARO_ENV === "h5") {
          videoContextPrev.pause();
        } else {
          videoContextPrev.stop();
        }
      }
    // }
    //播放
    if (process.env.TARO_ENV === "h5") {
      h5VideoAutoPlay(videoContext);
    } else {
      videoContext.play();
    }
    setProgress("0%")
    setCurrent(vCurrent)
    setPaused(true)
  };

获取小程序&h5的视频上下文

 /**
   * 获取视频上下文
   * @param vdom 当前视频index
   * @param vstate 视频播放状态 2停止 1播放
   * @returns
   */
  const getVideoContext = (vdom, vstate) => {
    let videoContext;
    if (process.env.TARO_ENV === "h5") {
      videoContext = document
        .getElementById("id" + vdom)
        ?.getElementsByTagName("video")[0];
      //播放前添加属性(防止安卓微信h5环境下,视频脱离文档流)x5-video-player-type='h5-page'
      // videoContext.setAttribute('x5-video-player-type', 'h5-page');
    } else {
      videoContext = createVideoContext("id" + vdom);
    }
    if (vstate === 2) {
      videoContext.currentTime = 0;
    }
    return videoContext;
  };

  /**
   * h5环境自动播放
   */
  const h5VideoAutoPlay = (videoContext) => {
    let user = navigator.userAgent.toLowerCase();
    //判断微信环境
    if (user.match(/MicroMessenger/i)?.toLocaleString() == "micromessenger") {
      if (window.WeixinJSBridge) {
        WeixinJSBridge.invoke(
          "getNetworkType",
          {},
          function () {
            videoContext.play();
          },
          false
        );
      } else {
        document.addEventListener(
          "WeixinJSBridgeReady",
          function () {
            WeixinJSBridge.invoke("getNetworkType", {}, function () {
              videoContext.play();
            });
          },
          false
        );
      }
    }
    videoContext.play();
    if (videoContext.paused) {
      setCurtain(true);
      setPaused(false)
    }
    //安卓正常情况下无法主动触发播放,应弹出幕帘关闭事件加入点击播放
    setTimeout(() => {}, 300);
  };

还在开发中哦,会持续更新文章以及github,目前上述功能双端编译运行正常。喜欢记得评论&点赞&收藏哦♥♥♥

=> github仓库地址

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值