当前位置:网站首页>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 .
版权声明
本文为[:::::::]所创,转载请带上原文链接,感谢
边栏推荐
猜你喜欢
随机推荐
Cos start source code and creator
【快速因數分解】Pollard's Rho 演算法
Troubleshooting and summary of JVM Metaspace memory overflow
Top 10 best big data analysis tools in 2020
简直骚操作,ThreadLocal还能当缓存用
Examples of unconventional aggregation
Every day we say we need to do performance optimization. What are we optimizing?
Calculation script for time series data
从海外进军中国,Rancher要执容器云市场牛耳 | 爱分析调研
人工智能学什么课程?它将替代人类工作?
The difference between Es5 class and ES6 class
你的财务报告该换个高级的套路了——财务分析驾驶舱
Character string and memory operation function in C language
Subordination judgment in structured data
50 + open source projects are officially assembled, and millions of developers are voting
Skywalking series blog 5-apm-customize-enhance-plugin
EOS创始人BM: UE,UBI,URI有什么区别?
In depth understanding of the construction of Intelligent Recommendation System
Real time data synchronization scheme based on Flink SQL CDC
Menu permission control configuration of hub plug-in for azure Devops extension