仿抖音 h5 & 小程序
React hooks + Taro 3 + Taro UI
目前还在开发中,暂时实现了一部分逻辑,源码已发布github在文章最下边 h5端效果预览,在线预览地址:https://lionelsun.github.io/taroTictok 用到的测试视频资源来自@MK965 
1.实现功能
- ?基础布局
- ?视频上下滑动
- ?停止上条视频并重置进度
- ?单击暂停播放 (禁用自带控制)
- 🔛双击暂停播放 (实现中)
- ?播放进度条 (实时监听当前视频进度并显示)
- ?视频上下滑动 (停止上条视频并重置进度)
- ?视频自动播放 (分别实现h5&小程序的功能)
- 🔛评论 (实现中)
- 🔛跳转&切换应用暂停播放 (实现中)
- 🔛其余功能完善中…
2.核心代码
dom结构
return (
<View>
<Swiper
className='videoMain'
disableTouch
current={current}
vertical={datas.vertical}
circular={datas.circular}
indicatorDots={datas.indicatorDots}
onChange={swiperChange}
key={props.dataScore.length.toLocaleString()}
>
{props.dataScore.map((item: any, index: number) => (
<SwiperItem
key={item.id}
className='SwiperItem'
id={`swi_${item.id}`}
onClick={touchv}
>
<View className='videoCtrl'>
<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切换时控制 暂停以及自动播放
const swiperChange = (e: any) => {
let vCurrent = 0;
if (e.detail) vCurrent = e.detail.current;
props.onChange(vCurrent);
let videoContext = getVideoContext(vCurrent, 1);
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的视频上下文
const getVideoContext = (vdom, vstate) => {
let videoContext;
if (process.env.TARO_ENV === "h5") {
videoContext = document
.getElementById("id" + vdom)
?.getElementsByTagName("video")[0];
} else {
videoContext = createVideoContext("id" + vdom);
}
if (vstate === 2) {
videoContext.currentTime = 0;
}
return videoContext;
};
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仓库地址
|