|
|
|
@ -0,0 +1,200 @@ |
|
|
|
|
import React, {FC, useEffect, useRef, useState, useImperativeHandle} from "react"; |
|
|
|
|
import {Image, Text, Video, View} from "@tarojs/components"; |
|
|
|
|
import "./index.module.scss" |
|
|
|
|
import Icon from "@/components/icon"; |
|
|
|
|
import {AtSlider} from "taro-ui"; |
|
|
|
|
import Taro from "@tarojs/taro"; |
|
|
|
|
import full from "@/static/img/fullscreen.png" |
|
|
|
|
import unfull from "@/static/img/exitFullscreen.png" |
|
|
|
|
|
|
|
|
|
type Props = { |
|
|
|
|
src: string |
|
|
|
|
onRef: any |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const VideoPro:FC<Props> = ({src,onRef}) => { |
|
|
|
|
const globalData = Taro.getApp().globalData |
|
|
|
|
//用useImperativeHandle暴露一些外部ref能访问的属性
|
|
|
|
|
useImperativeHandle(onRef, () => { |
|
|
|
|
return { |
|
|
|
|
func: pause, |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// 视频ui控制需要的响应式数据
|
|
|
|
|
const videoContext = useRef<any>() |
|
|
|
|
const [isPlay, setIsPlay] = useState(false) |
|
|
|
|
const [duration,setDuration] = useState(0) // 视频长度 单位秒
|
|
|
|
|
const updateState = useRef(false) |
|
|
|
|
const [sliderValue,setSlidervalue] = useState(0) |
|
|
|
|
const [process_duration, set_process_duration] = useState('00:00') |
|
|
|
|
const [total_duration, set_total_duration] = useState('00:00') |
|
|
|
|
const [showMenu,setShowMenu] = useState(true) |
|
|
|
|
const [isFull,setIsFull] = useState(false) |
|
|
|
|
const time = useRef<any>() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
console.log('组件加载') |
|
|
|
|
videoContext.current = Taro.createVideoContext('video') |
|
|
|
|
updateState.current = true |
|
|
|
|
}, []); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function onTouchStart(){ |
|
|
|
|
if(!showMenu) { |
|
|
|
|
setShowMenu(true) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function onTouchEnd(){ |
|
|
|
|
if(time.current) { |
|
|
|
|
clearTimeout(time.current) |
|
|
|
|
time.current = null |
|
|
|
|
} |
|
|
|
|
time.current = setTimeout(() => { |
|
|
|
|
setShowMenu(false) |
|
|
|
|
},5000) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function bindTimeupdateFun(e) { |
|
|
|
|
if (updateState.current) { |
|
|
|
|
let sliderValue = e.detail.currentTime / e.detail.duration * 100; |
|
|
|
|
setSlidervalue(sliderValue) |
|
|
|
|
setDuration(e.detail.duration) |
|
|
|
|
set_total_duration(formatSeconds(e.detail.duration)) |
|
|
|
|
set_process_duration(formatSeconds(e.detail.currentTime)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function addZero(i){ |
|
|
|
|
i = typeof i === 'string' ? Number(i) : i; |
|
|
|
|
return i < 10 ? "0" + i : "" + i; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function formatSeconds(value){ |
|
|
|
|
if (value == undefined) { |
|
|
|
|
value = 0; |
|
|
|
|
} |
|
|
|
|
let second = parseInt(value); |
|
|
|
|
let min = 0; |
|
|
|
|
let secondStr = '' |
|
|
|
|
let minStr = '' |
|
|
|
|
let result = '' |
|
|
|
|
if (second > 60) { |
|
|
|
|
min = parseInt(String(second / 60)); |
|
|
|
|
second = parseInt(String(second % 60)); |
|
|
|
|
if (min > 60) { |
|
|
|
|
// hour = parseInt(String(min / 60));
|
|
|
|
|
min = parseInt(String(min % 60)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (min > 0) { |
|
|
|
|
minStr = addZero(parseInt(String(min))); |
|
|
|
|
result = minStr + ":"; |
|
|
|
|
}else{ |
|
|
|
|
result = "00:"; |
|
|
|
|
} |
|
|
|
|
if(second > 0){ |
|
|
|
|
secondStr = addZero(parseInt(String(second))); |
|
|
|
|
result = result + secondStr; |
|
|
|
|
}else{ |
|
|
|
|
result = result + '00'; |
|
|
|
|
} |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function bindEnded(){ |
|
|
|
|
setIsPlay(false) |
|
|
|
|
if(!showMenu){ |
|
|
|
|
setShowMenu(true) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function onFullScreenChange(e){ |
|
|
|
|
console.log(e.detail.fullScreen) |
|
|
|
|
if(e.detail.fullScreen){ |
|
|
|
|
setIsFull(true) |
|
|
|
|
}else{ |
|
|
|
|
setIsFull(false) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function play(e){ |
|
|
|
|
e.stopPropagation(); |
|
|
|
|
videoContext.current.play() |
|
|
|
|
setIsPlay(true) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function pause(){ |
|
|
|
|
setIsPlay(false) |
|
|
|
|
videoContext.current.pause() |
|
|
|
|
} |
|
|
|
|
function sliderOnChange(e){ |
|
|
|
|
if (duration) { |
|
|
|
|
// 视频跳转到指定位置
|
|
|
|
|
videoContext.current.seek(e / 100 * duration); |
|
|
|
|
updateState.current = true |
|
|
|
|
setSlidervalue(e) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
function sliderOnChanging(){ |
|
|
|
|
updateState.current = false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<View className="container"> |
|
|
|
|
<Video |
|
|
|
|
style={{width: '750rpx', height: '600rpx'}} |
|
|
|
|
id='video' |
|
|
|
|
// src={brandInfo?.introductory_video_resource?.url}
|
|
|
|
|
src={src} |
|
|
|
|
controls={false} |
|
|
|
|
showPlayBtn={false} |
|
|
|
|
showCenterPlayBtn={false} |
|
|
|
|
showProgress={false} |
|
|
|
|
showFullscreenBtn={false} |
|
|
|
|
enableProgressGesture={false} |
|
|
|
|
onTimeUpdate={bindTimeupdateFun} |
|
|
|
|
onEnded={bindEnded} |
|
|
|
|
onFullScreenChange={onFullScreenChange} |
|
|
|
|
> |
|
|
|
|
<View onTouchStart={onTouchStart} onTouchEnd={onTouchEnd} style={{width:isFull?`${globalData.screenHeight}px`:'750rpx',height:isFull?'750rpx':'600rpx',display:'flex',flexDirection:'column',boxSizing:'border-box',paddingLeft:isFull?`${globalData.statusBarHeight}px`:'0',paddingRight:isFull?`${globalData.statusBarHeight}px`:'0'}}> |
|
|
|
|
<View onClick={pause} className="justify-center align-center flex pt-5" style={{flex:'1',boxSizing:'border-box'}}> |
|
|
|
|
{ !isPlay && showMenu && |
|
|
|
|
<View className="flex justify-center align-center rounded-50 pl-1" style={{width:'50px',height:'50px',backgroundColor:'rgba(0,0,0,0.5)',boxSizing:'border-box'}}> |
|
|
|
|
<Icon onClick={play} name="play" color="#fff" size="35px"></Icon> |
|
|
|
|
</View> |
|
|
|
|
} |
|
|
|
|
</View> |
|
|
|
|
<View className="flex align-center px-3" style={{height:'40px',boxSizing:'border-box'}}> |
|
|
|
|
{ duration && showMenu && |
|
|
|
|
<> |
|
|
|
|
{ |
|
|
|
|
isPlay ? |
|
|
|
|
<Icon name="pause" color="#fff" size="23px" onClick={() => {videoContext.current.pause();setIsPlay(false)}} /> : |
|
|
|
|
<Icon name="play" color="#fff" size="23px" onClick={() => {videoContext.current.play();setIsPlay(true)}} /> |
|
|
|
|
} |
|
|
|
|
<Text className="text-white pl-1 font-26">{process_duration}</Text> |
|
|
|
|
<View style={{flex:'1'}}> |
|
|
|
|
<AtSlider onChange={sliderOnChange} onChanging={sliderOnChanging} step={1} value={sliderValue} activeColor='#fff' backgroundColor='#BDBDBD' blockColor='#fff' blockSize={10}></AtSlider> |
|
|
|
|
</View> |
|
|
|
|
<Text onClick={() => { |
|
|
|
|
isFull?videoContext.current.exitFullScreen():videoContext.current.requestFullScreen({direction:90}) |
|
|
|
|
}} className="text-white font-26 pr-1">{total_duration}</Text> |
|
|
|
|
{ |
|
|
|
|
isFull? <Image style={{width:'25px',height:'25px'}} onClick={() => {videoContext.current.exitFullScreen()}} src={unfull} /> |
|
|
|
|
: <Image style={{width:'23px',height:'23px'}} src={full} onClick={() => {videoContext.current.requestFullScreen({direction:90})}} /> |
|
|
|
|
} |
|
|
|
|
</> |
|
|
|
|
} |
|
|
|
|
</View> |
|
|
|
|
</View> |
|
|
|
|
</Video> |
|
|
|
|
</View> |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
export default VideoPro |