当前位置:网站首页>H5 makes its own video player (JS Part 2)
H5 makes its own video player (JS Part 2)
2020-11-06 01:17:00 【:::::::】
review
Forget it. No review
Start directly , open JS1 Written in bvd.js
Play the video
- Play button hidden
- The video starts playing When you click the play button , The play button will be hidden , Play the video , This is not hard to , stay JS1 We've already achieved . But let's change our thinking , Add a click to the video tap event , Make the video play , Then trigger the playback event , So that the play button is hidden pro.initEvent = function(){ var that = this; // Add events to the play button image this.vimg.addEventListener('tap',function(){ that.video.play(); }) // Video Click to pause or play events this.video.addEventListener('tap',function(){ if(this.paused || this.ended) { // When you pause, click to play if(this.ended) {// If it's over , It starts all over again this.currentTime = 0; } this.play(); } else { // Click to pause while playing this.pause(); } }) // Video playback Events this.video.addEventListener('play',function(){ that.vimg.style.display = 'none'; }) // Get metadata this.video.addEventListener('loadedmetadata',function(){ that.vC.querySelector('.duration').innerHTML = stom(this.duration); }); }
- The lower control bar is gradually hidden Hiding is not the difficulty , The important thing is to gradually hide , Here we have several solutions :
- Timer
- css3 Animation frames
Here we are 2 To use in combination
First, let's define a set of animations
@keyframes vhide {0% {opacity: 1;}100% {opacity: 0;}} @-webkit-keyframes vhide {0% {opacity: 1;}100% {opacity: 0;}} .vhidden { animation: vhide 3.5s ease-in; -webkit-animation: vhide 3.5s ease-in; }
Its role is transparency 3.5 Seconds 1=>0,ease-in Namely From slow to fast Over effect of . Do you understand css Animation can ask Du Niang And then we give the video, when it starts playing events, to Control bar add to vhidden Style class
// Video playback Events this.video.addEventListener('play',function(){ that.vC.classList.add('vhidden'); })
The test results , Sure enough 3.5s Inside , Control bar Slowly transparent , The problem is 3.5s after , Transparency is back to 1, Here I'll explain , Because the animation frame is rebound by default , We can add a style
.vhidden { animation: vhide 3.5s ease-in; -webkit-animation: vhide 3.5s ease-in; animation-fill-mode:forwards; -webkit-animation-fill-mode: forwards; }
CSS3 attribute animation-fill-mode Used to define what an element looks like after the animation .
animation-fill-mode The default value of is none, That is, after the end of the animation, no changes will be made , If you put animation-fill-mode Change to forwards After the animation, the style of the element will become the style specified by the last key frame of the animation .
After adding this pattern , Sure enough 3.5s after , Animation doesn't bounce back anymore , But pay attention here , The control bar is not no longer there, but transparent , If we have a click time to write the control bar , Then click on the control bar , Or trigger events , So , We can also write a paragraph setTimeout Come on , Let the control bar 3.5s Hide behind , You can make your own choice
// Video playback Events this.video.addEventListener('play',function(){ that.vimg.style.display = 'none'; that.vC.classList.add('vhidden'); that.vCt = setTimeout(function(){ that.vC.style.visibility = 'hidden'; },3400); })
Why is the animation process 3.5s, However js Yes 3.4s After execution , It's just not written here animation-fill-mode:forwards In the case of insurance
It's playing
Hey , The video can be played ! So now we should think about what we have to do on the air ?
1. The control bar, the progress bar, grows slowly
We need to add a piece to the video timeupdate The event when the audio and video playback position changes
Let's start with the video metadata event , Take down the length of the video
// Get metadata this.video.addEventListener('loadedmetadata',function(){ that.vDuration = this.duration; that.vC.querySelector('.duration').innerHTML = stom(that.vDuration); });
Then calculate the ratio from the video playback progress update event , Set the width of the progress bar
// Events in video playback this.video.addEventListener('timeupdate', function() { var currentPos = this.currentTime;// Gets the current playback location // Update progress bar var percentage = 100 * currentPos / that.vDuration; // Set width that.vC.querySelector('.timeBar').style.width = percentage + '%'; });
We can see that our progress bar is getting bigger and bigger .
2. Current playback time changes
meanwhile , Our current playback time is also displayed in timeupdate Set in the event
// Events in video playback this.video.addEventListener('timeupdate', function() { var currentPos = this.currentTime;// Gets the current playback location // Update progress bar var percentage = 100 * currentPos / that.vDuration; that.vC.querySelector('.timeBar').style.width = percentage + '%'; // Update current playback time that.vC.querySelector('.current').innerHTML = stom(currentPos); });
Pause or stop it
When we click on the video , If it's a pause , Let's start playing , And trigger the playback event , On the contrary, the video is playing , Click on the video and it will pause , And trigger a pause event .
0. Time frame
La la la , Pause play ,timeupdate Naturally, events don't trigger , The current progress and time will not change .
1. The play button shows
During the pause , Just show the button
// Pause or stop it this.video.addEventListener('pause',function(){ that.vimg.style.display = 'block'; });
2. The lower control bar shows
The control bar shows , Just get rid of that vhidden Just the style class
// Pause or stop it this.video.addEventListener('pause',function(){ that.vimg.style.display = 'block'; that.vC.classList.remove('vhidden'); that.vC.style.visibility = 'visible'; });
It seems that there is nothing wrong with this writing , however , If you've written before when you've hidden the control bar setTimeout Words , It's time to get rid of it .
// Pause or stop it this.video.addEventListener('pause',function(){ that.vimg.style.display = 'block'; that.vC.classList.remove('vhidden'); that.vC.style.visibility = 'visible'; that.vCt && clearTimeout(that.vCt); });
Fast forward, fast backward
How can a small video player with its mouth in its mouth be less, can it be advanced, retractable and flexible ?
Come on , Let's start with video Add left slide right slide event
// Video gesture right slide event this.video.addEventListener('swiperight',function(e){ this.currentTime += 5; }); // Video gesture left slide event this.video.addEventListener('swipeleft',function(e){ this.currentTime -= 5; });
Maybe debugging on the computer will change the progress directly 0, At first, I was wondering , It turns out that on the mobile phone webview It seems to be feasible .
About Drag the progress bar to change the video progress I'm not going to write , Because I haven't written yet .
Play full screen
Maybe you will pay more attention to this :
ios End : Remove video label webkit-playsinline Attribute is enough , because ios Yes h5 Of video Tag support is still quite good
// Call native mode Play full screen pro.nativeMax = function(){ if(!window.plus){ // Not html5+ Environmental Science return; } if($.os.ios){ console.log('ios') this.video.removeAttribute('webkit-playsinline'); }else if($.os.android){ console.log('android'); var url = this.video.querySelector('source').src; var Intent = plus.android.importClass("android.content.Intent"); var Uri = plus.android.importClass("android.net.Uri"); var main = plus.android.runtimeMainActivity(); var intent = new Intent(Intent.ACTION_VIEW); var uri = Uri.parse(url); intent.setDataAndType(uri, "video/*"); main.startActivity(intent); } }
stay initEvent Add click on Full screen event
this.vC.querySelector('.fill').addEventListener('tap',function(){ that.nativeMax(); });
It's a little chicken ribs , You can't have a little generic ?
It's true that I've been thinking about this all night , Decided to bring some more dry goods .
Give me a state first , The default is mini Play
var bvd = function(dom) { var that = this; $.ready(function() { // Get video elements that.video = document.querySelector(dom || 'video'); // Get video parent element that.vRoom = that.video.parentNode; // Element initialization that.initEm(); // Event initialization that.initEvent(); // Record information that.initInfo(); // Current playback mode false by mini Play that.isMax = false; }) } // Record information pro.initInfo = function() { var that = this; // stay onload State, ,offsetHeight To get the correct value window.onload = function(){ that.miniInfo = {//mini The pattern of state width: that.video.offsetWidth + 'px', height: that.video.offsetHeight + 'px', position: that.vRoom.style.position, transform: 'translate(0,0) rotate(0deg)' } var info = [ document.documentElement.clientWidth || document.body.clientWidth, document.documentElement.clientHeight || document.body.clientHeigth ], w = info[0], h = info[1], cha = Math.abs(h - w) / 2; that.maxInfo = {//max The pattern of state width: h + 'px', height: w + 'px', position: 'fixed', transform: 'translate(-' + cha + 'px,' + cha + 'px) rotate(90deg)' } } } // Full screen mini Switch between the two modes pro.switch = function() { var vR = this.vRoom; // Get the style information that needs to be transformed var info = this.isMax ? this.miniInfo : this.maxInfo; for(var i in info) { vR.style[i] = info[i]; } this.isMax = !this.isMax; } // Full screen button this.vC.querySelector('.fill').addEventListener('tap', function() { //that.nativeMax(); that.switch(); });
Take a look , Take a look at it
It looks like it feels good , utilize css3 The displacement and rotation of , Let the video full screen in front of the screen , But the problem comes with
- Play button as well as Control bar In full screen It seems to be hiding , It's actually video The tag is over the parent element , We adjust accordingly
css
.bad-video { position: relative; /*overflow: hidden;*/ background-color: #CCCCCC; }
js max In the configuration , Set up zIndex value
that.maxInfo = {//max The pattern of state zIndex:99, width: h + 'px', height: w + 'px', position: 'fixed', transform: 'translate(-' + cha + 'px,' + cha + 'px) rotate(90deg)' }
- Horizontal full screen , Left and right slip events do not change with direction
// Video gesture right slide event this.video.addEventListener('swiperight', function(e) { console.log('right'); this.currentTime += 5; }); // Video gesture left slide event this.video.addEventListener('swipeleft', function(e) { console.log('left'); this.currentTime -= 5; });
this TM It's embarrassing , Can't I have a full screen , Mobile phone horizontal , Go up and down, fast forward, fast backward ?
What do you do then , Don't party
Gesture slide Events
Let's give it first video Register an event list
var events = {}; // increase Or delete the event pro.eve = function(ename, callback, isF) { if(callback && typeof(callback) == 'function') { isF && arguments.callee(ename); events[ename] = callback; this.video.addEventListener(ename, events[ename]); console.log(' Add event :' + ename); return; } var fun = events[ename] || function(){}; this.video.removeEventListener(ename, fun); console.log(' Delete event :' + ename); return fun; }
to video Event add a proxy to delete the add event ,isF Whether to delete the same event before adding this event , Because if you use anonymous functions to add events , It can't be deleted , In this way, a proxy can be set up to record dynamically added events in events Inside , Easy to operate
At this time, we add the function of modifying the current playback progress and volume
// Jump to video progress Company second pro.setCurrentTime = function(t){ this.video.currentTime += t; } // Set the volume Company percentage Such as 0.1 pro.setVolume = function(v){ this.video.volume+= v; }
Then through the agency to video Add events that slide left and right up and down
// Video gesture right slide event this.eve('swiperight',function(){ that.setCurrentTime(5); }); // Video gesture left slide event this.eve('swipeleft', function(e) { that.setCurrentTime(-5); }); // Slide events on video gestures this.eve('swipeup',function(){ that.setVolume(0.2); }); // Video gesture slide event this.eve('swipedown', function(e) { that.setCurrentTime(-0.2); });
ok, Sliding events in four directions have been added , But this is mini Mode playback Events , In full screen , Events in four directions did not follow video The direction of the elements changes , This requires the most stupid way to determine whether the full screen triggers the event
// Video gesture right slide event this.eve('swiperight',function(){ if(that.isMax){ return that.setVolume(0.2); } that.setCurrentTime(5); }); // Video gesture left slide event this.eve('swipeleft', function() { if(that.isMax){ return that.setVolume(-0.2); } that.setCurrentTime(-5); }); // Slide events on video gestures this.eve('swipeup',function(){ if(that.isMax){ return that.setCurrentTime(-5); } that.setVolume(0.2); }); // Video gesture slide event this.eve('swipedown', function() { if(that.isMax){ return that.setCurrentTime(5); } that.setVolume(-0.2); });
What about? , Although it looks a little bit stupid, But it's very practical
5+ Client full screen solution
Although in 5+ client ,android You can call the native way to play , But it's not good enough , We can look at another set of solutions
On initialization , Record mini Style of time , In full screen , By modifying the video width to the screen height , Change video height to video width , recycling 5+ The screen rotates , Set full screen , hide the status bar
0) Remove gesture event judgment
Because it's time to change the direction of mobile devices , therefore , The direction of the gesture changes with the direction of the device
1) Remove css3 Rotation and displacement
// Record information pro.initInfo = function() { var that = this; // stay onload State, ,offsetHeight To get the correct value window.onload = function() { that.miniInfo = { //mini The pattern of state zIndex: 1, width: that.video.offsetWidth + 'px', height: that.video.offsetHeight + 'px', position: that.vRoom.style.position } that.maxInfo = { //max The pattern of state zIndex: 99, width: '100%', height: that.sw + 'px', position: 'fixed' } } }
2) This use 5+ Set full screen and hide status bar
// Full screen mini Switch between the two modes pro.switch = function() { var vR = this.vRoom; // Get the style information that needs to be transformed var info = this.isMax ? this.miniInfo : this.maxInfo; for(var i in info) { vR.style[i] = info[i]; } this.isMax = !this.isMax; plus.navigator.setFullscreen(this.isMax); if(this.isMax) { // Horizontal screen plus.screen.lockOrientation("landscape-primary"); } else { // Vertical screen plus.screen.lockOrientation("portrait-primary"); } }
3) In full screen mode ,android End return key , Trigger to exit full screen
pro.initEvent = function() { //....... Omit other code this.oback = $.back; // Listen to Android return key $.back = function() { if(that.isMax) { that.switch(); return; } that.oback(); } }
design sketch
5+ Gravity switch full screen
Hey , How can a player be less mobile Automatic switch Horizontal and vertical screens ? How to manually switch full screen , Next, gravity sensor switches the horizontal screen , Need to use 5+ Of API Accelerometer Acceleration sensing
In short : Gravitational acceleration can be thought of as a ball in a coordinate system Acceleration in three directions . Always follow the screen of your mobile phone
What is acceleration ? forehead , It's from the physics book
The mobile phone is placed horizontally upward y Positive axis To the right is x Positive axis , Outward is z Positive axis
What is xyz Axis ? forehead , It's from high mathematics books
Oh dear , You put your mobile phone upright on the ground , You just walk up there , Now you're standing on the screen of your phone , And then your right hand opens and straightens , This is it. x Axis , You're looking ahead , This is it. y Axis , It's on top of your head z Axis . That's clear. No , But it's not really about stepping on your cell phone ,23333
You can also choose to view other explanations :Android- Sensor development - Direction judgment
- x,y Axis change : When the mobile phone screen is placed horizontally upward : (x,y,z) = (0, 0, -9.81) When the top of the phone is raised : y Reduce , And it's negative When the bottom of the phone is raised : y increase , And it's positive When the right side of the phone is raised : x Reduce , And it's negative When the left side of the phone is raised : x increase , And it's positive
- z Change of axis : When the mobile phone screen is placed horizontally upward ,z= -9.81 When the phone screen is placed vertically , z= 0 When the mobile phone screen is placed horizontally down ,z= 9.81
- Screen vertical and horizontal switching conditions y<=-5 when , Switch to vertical x<=-5 when , Change to horizontal
ok, We added 2 A way , Used to turn on and off device monitoring
// Turn on direction sensing pro.startWatchAcc = function(){ var that = this; this.watchAccFun = plus.accelerometer.watchAcceleration(function(a) { if(that.getIsMax()){ // The current state is full screen // Determine whether the vertical screen is satisfied Mini state a.yAxis>=5 && that.setIsMax(false); }else{ // At present, it is Mini state // Judge whether it satisfies the full screen Max state Math.abs(a.xAxis) >=5 && that.setIsMax(true); } }, function(e) { // It's a big deal to make a mistake It doesn't rotate automatically Let it be manual Switch console.log("Acceleration error: " + e.message); that.clearWatchAcc(); },{ frequency:1200 }); } // Turn off directional sensing pro.clearWatchAcc = function(){ this.watchAccFun && plus.accelerometer.clearWatch(this.watchAccFun); }
Then, the direction monitoring is turned on by default during initialization
var bvd = function(dom) { var that = this; $.ready(function() { //... }) $.plusReady(function() { that.startWatchAcc(); }) }
Then change the horizontal full screen to , Can be two-way horizontal screen
Real machine debugging to see
Hey , Let's add a lock button for full screen playback , Let the device not monitor Gravity induction , Also does not respond to the video click play pause event
Make a lock button first
Of course , Lock picture , The address was changed to use base64, It's better to use js Dynamically generate tags
Set its basic style , Keep right , Vertical center up and down , Hide by default
.lock { padding: .3rem; width: 3rem; height: 3rem; position: absolute; right: .5rem; top: 50%; transform: translateY(-50%); -webkit-transform: translateY(-50%); visibility: hidden; }
good , Let's sort out the logic ,
1) Default in mini When the play ,lock hide 2) When playing full screen ,lock Show , But it also follows the control bar stay 4s Hide inside right 3) When full screen pauses ,lock With the control bar Always show 4) Click on lock When locked , The prompt is locked , The control bar is hidden immediately ,lock4s Hide inside right , Video click events are replaced by display lock Icon ,android The return key event is changed to do nothing , Turn off gravity monitoring 5) Click on lock When the unlock , The prompt is unlocked ,android The return key is changed to Switch to a mini state , Turn on gravity monitoring
I wipe , In fact, it's quite depressing to do it , The main reason is that logic processing is painful
0) Add an animation that moves right ,3s After the delay 1s Inside After executing the animation
@keyframes lockhide {0% {transform: translate(0%,-50%);}100% {transform: translate(120%,-50%);}} webkit-keyframes lockhide {0% {transform: translate(0%,-50%);}100% {transform: translate(120%,-50%);}} .lockhidden { animation: lockhide 1s 3s linear; -webkit-animation: lockhide 1s 3s linear; animation-fill-mode:forwards; -webkit-animation-fill-mode: forwards; }
1) Show... In full screen lock
pro.switch = function() { //... // In full screen According to lock Icon this.vlock.style.visibility = this.isMax ? 'visible' : 'hidden'; }
2) When playing full screen ,lock Show , But it also follows the control bar stay 4s Hide inside right We add lock The hidden animation of ,
3) When full screen pauses ,lock With the control bar Always show
4) Click on lock When locked , The prompt is locked , The control bar is hidden immediately ,lock4s Hide inside right , Video click events are replaced by display lock Icon ,android The return key event is changed to do nothing , Turn off gravity monitoring 5) Click on lock When the unlock , The prompt is unlocked ,android The return key is changed to Switch to a mini state , Turn on gravity monitoring
// Lock screen pro.lockScreen = function() { $.toast(' Lock screen '); var that = this; // Replace video Click the event as Show lock Icon , And save video Previous events this.videoTapFn = this.eve('tap', function() { that.lockT = setTimeout(function(){ that.vlock.classList.add('lockhidden'); },500); // Restart playing styles that.vlock.classList.remove('lockhidden'); that.vlock.style.visibility = 'visible'; }, true); // Hide the control bar this.vC.style.visibility = 'hidden'; // to Lock Icon added Hidden style class this.vlock.classList.add('lockhidden'); // When you lock the screen , Don't monitor gravity sensing this.clearWatchAcc(); // Identifies the currently changed Lock state this.isLock = true; } // Unlock screen pro.unlockScreen = function() { $.toast(' Unlock screen '); // Replace with video Previous click events this.eve('tap', this.videoTapFn, true); // to Lock The icon is clear Hidden style class this.vlock.classList.remove('lockhidden'); // When you don't lock the screen , Monitoring gravity sensing this.startWatchAcc(); // Identifies the currently changed Lock state this.isLock = false; }
666) Finally, to our dear lock Add a touch event to the icon , as well as android Return key event change
// Full screen when Lock click events this.vlock.addEventListener('tap', function() { if(that.isLock) { that.unlockScreen(); return; } that.lockScreen(); }); this.oback = $.back; // Listen to Android return key $.back = function(){ if(that.isMax){ if(!that.isLock){ // In full screen mode Press the back key when ,1s It doesn't monitor gravity , Prevent return Mini State time and gravimetry are concurrent events setTimeout(function(){ that.startWatchAcc(); },1000); that.clearWatchAcc(); that.switch(); } return; } that.oback(); } }
Okay ! this paper 5+ Full screen demo Source code address
It's not easy to blog , But that kind of sharing mood is very good , It's another kind of review and progress ?
Thank you .
This article related article :H5 Build your own video player special column
Participation of this paper Tencent cloud media sharing plan , You are welcome to join us , share .
版权声明
本文为[:::::::]所创,转载请带上原文链接,感谢
边栏推荐
- Serilog原始碼解析——使用方法
- 給萌新HTML5 入門指南(二)
- Didi elasticsearch cluster cross version upgrade and platform reconfiguration
- Asp.Net Core學習筆記:入門篇
- 如何将数据变成资产?吸引数据科学家
- Azure Data Factory(三)整合 Azure Devops 實現CI/CD
- 简直骚操作,ThreadLocal还能当缓存用
- 在大规模 Kubernetes 集群上实现高 SLO 的方法
- Swagger 3.0 天天刷屏,真的香嗎?
- Listening to silent words: hand in hand teaching you sign language recognition with modelarts
猜你喜欢
制造和新的自动化技术是什么?
自然语言处理之命名实体识别-tanfordcorenlp-NER(一)
中小微企业选择共享办公室怎么样?
2018中国云厂商TOP5:阿里云、腾讯云、AWS、电信、联通 ...
恕我直言,我也是才知道ElasticSearch条件更新是这么玩的
Aprelu: cross border application, adaptive relu | IEEE tie 2020 for machine fault detection
Examples of unconventional aggregation
EOS创始人BM: UE,UBI,URI有什么区别?
Don't go! Here is a note: picture and text to explain AQS, let's have a look at the source code of AQS (long text)
DTU连接经常遇到的问题有哪些
随机推荐
Leetcode's ransom letter
Group count - word length
Skywalking series blog 1 - install stand-alone skywalking
OPTIMIZER_ Trace details
事半功倍:在没有机柜的情况下实现自动化
EOS创始人BM: UE,UBI,URI有什么区别?
前端模組化簡單總結
幽默:黑客式编程其实类似机器学习!
CCR炒币机器人:“比特币”数字货币的大佬,你不得不了解的知识
10 easy to use automated testing tools
条码生成软件如何隐藏部分条码文字
Subordination judgment in structured data
分布式ID生成服务,真的有必要搞一个
Swagger 3.0 天天刷屏,真的香嗎?
100元扫货阿里云是怎样的体验?
基於MVC的RESTFul風格API實戰
如何将数据变成资产?吸引数据科学家
Flink on paasta: yelp's new stream processing platform running on kubernetes
制造和新的自动化技术是什么?
加速「全民直播」洪流,如何攻克延时、卡顿、高并发难题?