目录
视频播放器实例
html代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" type="text/css" href="css/index.css"/>
</head>
<body>
<div id="wrap">
<video src="giphy.mp4"></video>
<div class="control">
<div class="btns">
<span class="start"></span>
<span class="stop"></span>
</div>
<div class="progress">
<div class="wrap">
<div class="inner"></div>
</div>
<div class="skyblue"></div>
</div>
<div class="others">
<div class="time">
<span class="now">00:00:00</span>/<span class="all">00:00:00</span>
</div>
<div class="sound">
<div class="switch">
<span></span>
</div>
<div class="progress">
<div class="wrap">
<div class="inner"></div>
</div>
<div class="skyblue"></div>
</div>
</div>
<div class="full-screen">
<span></span>
</div>
</div>
</div>
</div>
</body>
<script src="js/drag.js"></script>
<script type="text/javascript">
window.onload=function(){
var video = document.querySelector("#wrap > video");
var control = document.querySelector("#wrap > .control");
var progress = document.querySelector("#wrap > .control > .progress ")
var inner = document.querySelector("#wrap > .control > .progress > .wrap > .inner ");
var skyblue = document.querySelector("#wrap > .control > .progress > .skyblue ");
var start = document.querySelector("#wrap .btns .start");
var stop = document.querySelector("#wrap .btns .stop");
var allSpan = document.querySelector("#wrap > .control >.others .all");
var nowSpan = document.querySelector("#wrap > .control >.others .now");
var switchNode = document.querySelector("#wrap > .control >.others >.sound .switch");
var switchSpan = document.querySelector("#wrap > .control >.others >.sound .switch > span");
var progress2 = document.querySelector("#wrap > .control >.others .progress ")
var inner2 = document.querySelector("#wrap > .control >.others .progress > .wrap > .inner ");
var skyblue2 = document.querySelector("#wrap > .control >.others .progress > .skyblue ");
var fullScreen = document.querySelector("#wrap > .control >.others .full-screen ");
var fullScreenSpan = document.querySelector("#wrap > .control >.others .full-screen > span");
video.width= document.documentElement.clientWidth;
video.height=document.documentElement.clientHeight - control.offsetHeight;
window.onresize=function(){
if(document.documentElement.clientWidth>=600){
video.width= document.documentElement.clientWidth;
video.height=document.documentElement.clientHeight - control.offsetHeight;
}
}
//功能
var timer = 0;
//同步音量
var flag = 0;
//全屏标志
var isFullScreen = false;
player();
function player(){
//双击视频事件
var flag=0;
video.ondblclick=function(){
if(flag==0){
addClass(start,"active");
video.play();
timer=setInterval(move,100)
flag=1;
}
else{
removeClass(start,"active");
video.pause();
clearInterval(timer);
flag=0;
}
}
//全屏
fullScreen.onclick=function(){
if(isFullScreen) {
// 全屏 ---> 不是全屏 --> remove
removeClass(fullScreenSpan,"active")
isFullScreen = false
if (document.exitFullscreen) {
document.exitFullscreen();
}
else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
}
else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
addClass(fullScreenSpan,"active")
isFullScreen = true
var docElm = document.documentElement;
//W3C
if (docElm.requestFullscreen) {
docElm.requestFullscreen();
}
//FireFox
else if (docElm.mozRequestFullScreen) {
docElm.mozRequestFullScreen();
}
//Chrome等
else if (docElm.webkitRequestFullScreen) {
docElm.webkitRequestFullScreen();
}
//IE11
else if (docElm.msRequestFullscreen) {
docElm.msRequestFullscreen();
}
}
}
//音量的控制
inner2.style.left = skyblue2.style.width = progress2.clientWidth - inner2.offsetWidth+"px";
switchNode.onclick=function(){
if(video.muted){
//静音 ---> 不静音 ---> 没有x的那个
video.muted=false;
video.volume =1;
removeClass(switchSpan,"active")
flag = flag==0?1:flag;
inner2.style.left = skyblue2.style.width = (progress2.clientWidth - inner2.offsetWidth)*flag+"px";
}else{
video.muted=true;
video.volume =0;
addClass(switchSpan,"active")
inner2.style.left = skyblue2.style.width=0+"px";
}
}
//时间显示
video.addEventListener("loadeddata",function(){
allSpan.innerHTML = changeTime(video.duration);
})
//进度条
progress.onclick=function(ev){
ev=ev||event;
addClass(start,"active");
video.play();
timer=setInterval(move,100);
video.currentTime = video.duration*((ev.clientX-this.offsetLeft)/(progress.clientWidth - inner.offsetWidth))
}
//按钮排
stop.onclick=function(){
removeClass(start,"active");
video.pause();
clearInterval(timer);
inner.style.left = skyblue.style.width=0+"px";
video.currentTime=0;
}
start.onclick=function(){
if(video.paused){
//暂停 ---> 播放 ---> 显示暂停按钮
addClass(this,"active");
video.play();
timer=setInterval(move,100)
}else{
removeClass(this,"active");
video.pause();
clearInterval(timer);
}
}
function move(){
inner.style.left = skyblue.style.width =(video.currentTime/video.duration)*(progress.clientWidth - inner.offsetWidth)+"px";
nowSpan.innerHTML=changeTime(video.currentTime);
}
}
//进度条小滑块拖拽时的逻辑
var callback={
move:function(){
skyblue.style.width = this.offsetLeft+"px";
var scale = this.offsetLeft/(progress.clientWidth - inner.offsetWidth);
video.currentTime = video.duration*scale;
nowSpan.innerHTML=changeTime(video.currentTime);
}
}
//音量条小滑块拖拽时的逻辑
var callback2={
move:function(){
skyblue2.style.width = this.offsetLeft+"px";
var scale = this.offsetLeft/(progress2.clientWidth - inner2.offsetWidth);
flag = scale;
video.volume = scale;
if(video.volume == 0){
video.muted=true;
addClass(switchSpan,"active")
}else{
removeClass(switchSpan,"active")
video.muted=false;
}
}
}
$.drag(inner,callback);
$.drag(inner2,callback2);
//工具类
function changeTime(time){
time = parseInt(time);
var h = toZero(Math.floor(time/3600));
var m = toZero(Math.floor(time%3600/60));
var s = toZero(Math.round(time%3600));
return h+":"+m+":"+s;
}
function toZero(num){
var val="";
if(num<10){
val="0"+num;
}else{
val = val+num;
}
return val;
}
function addClass(node,className){
var reg=new RegExp("\\b"+className+"\\b");
if(!reg.test(node.className)){
node.className +=(" "+className);
}
}
function removeClass(node,className){
if(node.className){
var reg=new RegExp("\\b"+className+"\\b");
var classes = node.className;
node.className=classes.replace(reg,"");
if(/^\s*$/g.test(node.className)){
node.removeAttribute("class");
}
}else{
node.removeAttribute("class");
}
}
}
</script>
</html>
less代码
@import "reset.less";
.progress-mixin(){
position: relative;
&>.wrap{
position: absolute;
width: 100%;
height: 3px;
margin-top: 11px;
background: #737373;
.inner{
position: absolute;
width: 9px;
height: 7px;
background: white;
border-radius:2px ;
margin-top: -2px;
}
}
&>.skyblue{
position: absolute;
left: 0;
top: 0;
width: 0;
height: 3px;
margin-top: 11px;
background: skyblue;
}
}
#wrap{
height: 100%;
overflow-x: auto;
overflow-y: hidden;
background: #383838;
font-size: 0;
.control{
min-width: 600px;
position: relative;
height: 25px;
background: #2A2A2A;
.btns{
position: absolute;
left: 0;
top: 0;
width: 55px;
height: 25px;
text-align: center;
&>span{
display: inline-block;
width: 9px;
height: 11px;
background: url(../img/icon.png) no-repeat;
margin-top:7px;
&:nth-child(1){
background-position: 0px -23px;
margin-right: 10px;
&.active{
background-position: 0px -11px;
}
}
&:nth-child(2){
background-position: 0px 0px;
}
}
};
& >.progress{
margin: 0 230px 0 55px;
height: 25px;
.progress-mixin()
};
.others{
position: absolute;
right: 0;
bottom: 0;
width: 230px;
height: 25px;
&>div{
height: 25px;
float: left;
}
.time{
width: 120px;
font-size: 12px;
color: white;
line-height: 25px;
text-align: center;
}
.sound{
width: 80px;
&>div{
height: 25px;
float: left;
}
.switch{
width: 20px;
text-align: center;
&>span{
display: inline-block;
margin: 7px auto;
width: 12px;
height: 12px;
background: url(../img/icon.png) no-repeat;
background-position:0 -34px;
&.active{
background-position:0 -46px;
}
}
}
.progress{
width: 60px;
.progress-mixin();
}
}
.full-screen{
width: 30px;
height: 25px;
text-align: center;
&>span{
display: inline-block;
margin: 7px auto;
width: 11px;
height: 11px;
background: url(../img/icon.png) no-repeat;
background-position: 0 -58px;
&.active{
background-position: 0 -71px;
}
}
}
}
}
}
该实例中我在原先的基础上添加了一个双击视频来暂停开始的功能。
这个实例对我来说工作量挺大的,还是基础不够扎实,在实现的过程中出现很多低级错误。
状态标签
meter
该标签用来显示已知范围的标量值或分数值
- value:当前的数值
- min:值域的最小边界值。如果设置了,它必须比最大值要小。如果没设置,默认为0
- max:值域的上限边界值。如果设置了,它必须比最小值要大。如果没设置,默认为1
- low:定义了低值区间的上限值,如果设置了,它必须比最小值属性大,并且不能超过high值和最大值。未设置活着比最小值还要小时,其值即为最小值
- high:定义了高值区间的下限值。如果设置了,它必须小于最大值,同时必须大于low值和最小值。如果没有设置,或者比最大值还大,其值即为最大值
- optimum:这个属性用来指示最优 / 最佳取值
progress
该标签用来显示一项任务的完成进度
- max:该属性描述了这个progress元素所表示的任务一共需要完成多少工作
- value:该属性用来指定该进度条已完成的工作量。如果没有value属性,则该进度条的进度为”不确定“,也就是说,进度条不会显示任何进度,无法估计当前的工作会在何时完成
列表标签
datalist
该标签会包含一组option元素,这些元素表示其表单控件的可选值。其id必须要和input中的list一致
details
一个ui小部件,用户可以从其中检索附加信息
open属性用来控制附加信息的默认显示与隐藏
summary
该标签用作一个<details>元素的一个内容摘要(标题)
注释标签
ruby
<rt></rt>:展示文字注音或字符注释
标记标签
mark
该标签表示为引用或符号目的而标记或突出显示的文本,这是由于标记的段落在封闭上下文中的相关性或重要性造成的
新增表单控件
- type:email:电子邮件地址类型。当格式不符合email格式时,提交是不会成功的,会出现提示;只有当格式正确时,提交才会通过。在移动端获焦时会切换到英文键盘
- type:tel:电话类型。在移动端获焦时会切换到数字键盘
- type:url:url类型。当格式不正确时,提交是不会成功的,会出现提示;只有当格式正确时,提交才会通过
- type:search:搜索类型。有清空文本的按钮
- type:range:特定范围内的数值选择器。属性有min、max、step
- type:number:只能包含数字的输入框
- type:color:颜色选择器
- type:datetime:显示完整日期(移动端浏览器支持)
- type:datetime-local:显示完整日期(不含时区)
- type:time:显示时间(不含时区)
- type:date:显示日期
- type:week:显示周
- type:month:显示月
新增表单属性
- placeholder:输入框提示信息。使用于form,以及type是text、search、url、tel、email、password类型的input
- autofocus:指定表单自动获取输入焦点
- required:此项必填,不能为空
- pattern:正则验证,例如:pattern="\d{1,5}"
- formaction:在submit里定义提交地址
- list和datalist:为输入框构造一个选择列表。list值为datalist标签的id
表单验证
validity对象
通过下面的valid可以查看验证是否通过,如果八种验证都通过则返回true,一种验证失败返回false
node.addEventListener("invalid",function(){},false);
- valueMissing:输入值为空时返回true
- typeMismatch:控件值与预期类型不匹配返回true
- patternMismatch:输入值不满足pattern正则返回true
- customError:不符合自定义验证返回true(setCustomValidity())