热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何利用HTML5制作一个好看的视频播放器

这篇文章将为大家详细讲解有关如何利用HTML5制作一个好看的视频播放器,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后

这篇文章将为大家详细讲解有关如何利用HTML5制作一个好看的视频播放器,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一、视频的格式

目前比较主流和使用比较的的视频格式主要有:avi、rmvb、wmv、mpeg4、ogg、webm。这些视频都是由视频、音频、编码格式三部分组成的。在HTML5中,根据浏览器的不同,目前拥有多套不同的编码器:

H.264(个人不看好):这个编码器是苹果系统包括苹果手机中的编码器,拥有专利的视频编码器。在编码及传输过程中的任何部分都可能需要收取专利费。因此Safari(苹果的浏览器)和Intenet Explorer支持该编码器,但是在开源已经成为大势的当下,还在浏览器中收取专利费,个人实在是不看好啊。

Theora:这是一个不受专利限制的编码格式,并且对所有等级的编码、传输以及回放免费的视频编码器。Chrome、Firefox以及Opera支持该编码器。

VP8:该视频编码器与Theora相似,但是其拥有者是Google公司,Google公司已经开源,因此不需要专利费。Chrome、Firefox以及Opera支持该编码器。

AAC:音频编码器,与H.264相同,该音频编码器拥有专利限制,Safari、Chrome和Internet Explorer支持该音频编码器。

MP3:也是一个专利技术,Safari、Chrome和Internet Explorer支持该音频编码器。

PCM:存储由模拟数字转换器编码的完整数据,在音频CD上存储数据的一种格式。是以中国无损编码器,它的文件大小一般是AAC和MP3文件的几倍,Safari、Firefox和Internet Explorer支持该音频编码器。

Vorbis:文件扩展名为.ogg,有时候也被称为Ogg Vorbis,该音频编码器不受专利保护,因此版权免费。支持的浏览器包括Chrome、Firefox和Opera.

主流浏览器和设备支持的视频和音频

如何利用HTML5制作一个好看的视频播放器

二、HTML5中的属性

在html5中可以使用

video标签中有很多属性,例如controls属性可以控制是否有控制台。

  
    浏览器不支持HTML5的视频播放功能  

从上面的视频格式中我们可以看到不同的浏览器支持不同的视频格式,这样我们可以采用标签指定多种格式的视频,默认情况下浏览器会自动启动下载文件来确定其类型。

  
      
      

三、制作视频播放器

index.html

  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
    

Custom HTML5 Video Controls with jQuery

           BACK TO ARTICLE »           Visit inWebson.com »       

       

                             

Demo 1

       

Custom HTML5 Video Controls

                                                        

Your browser does not support the video tag.

              This is HTML5 video with custom controls

                                                                                         

                                   /                                    

           

                                     

               

               Speed: 

               x1

               x3

               

               

                                                 

               

           

                  

       

  

                            
                   DEMO 1               
  • DEMO 2
  •            
           

                      
       © 2011 inWebson.com.      Design by Kenny Ooi.      Powered by HTML5 and      jQuery.  
     

style.css

/* video container */  
.videoContainer{  
    width:600px;  
    height:350px;  
    position:relative;  
    overflow:hidden;  
    background:#000;  
    color:#ccc;  
}  
  
/* video caption css */  
.caption{  
    display:none;  
    position:absolute;  
    top:0;  
    left:0;  
    width:100%;  
    padding:10px;  
    color:#ccc;  
    font-size:20px;  
    font-weight:bold;  
    box-sizing: border-box;  
    -ms-box-sizing: border-box;  
    -webkit-box-sizing: border-box;  
    -moz-box-sizing: border-box;  
    background: #1F1F1F; /* fallback */  
    background:-moz-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);  
    background:-webkit-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);  
    background:-o-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);  
}  
  
/*** VIDEO CONTROLS CSS ***/  
/* control holder */  
.control{  
    background:#333;  
    color:#ccc;  
    position:absolute;  
    bottom:0;  
    left:0;  
    width:100%;  
    z-index:5;  
    display:none;  
}  
/* control top part */  
.topControl{  
    height:11px;  
    border-bottom:1px solid #404040;  
    padding:1px 5px;  
    background:#1F1F1F; /* fallback */  
    background:-moz-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);  
    background:-webkit-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);  
    background:-o-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);  
}  
/* control bottom part */  
.btmControl{  
    clear:both;  
    background: #1F1F1F; /* fallback */  
    background:-moz-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);  
    background:-webkit-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);  
    background:-o-linear-gradient(top,#242424 50%,#1F1F1F 50%,#171717 100%);  
}  
.control p.btn {  
    float:left;  
    width:34px;  
    height:30px;  
    padding:0 5px;  
    border-right:1px solid #404040;  
    cursor:pointer;  
}  
.control p.text{  
    font-size:12px;  
    font-weight:bold;  
    line-height:30px;  
    text-align:center;  
    font-family:verdana;  
    width:20px;  
    border:none;  
    color:#777;  
}  
.control p.btnPlay{  
    background:url(control.png) no-repeat 0 0;  
    border-left:1px solid #404040;  
}  
.control p.paused{  
    background:url(control.png) no-repeat 0 -30px;  
}  
.control p.btnStop{  
    background:url(control.png) no-repeat 0 -60px;  
}  
.control p.spdText{  
    border:none;  
    font-size:14px;  
    line-height:30px;  
    font-style:italic;  
}  
.control p.selected{  
    font-size:15px;  
    color:#ccc;  
}  
.control p.sound{  
    background:url(control.png) no-repeat -88px -30px;  
    border:none;  
    float:right;  
}  
.control p.sound2{  
    background:url(control.png) no-repeat -88px -60px !important;  
}  
.control p.muted{  
    background:url(control.png) no-repeat -88px 0 !important;  
}  
.control p.btnFS{  
    background:url(control.png) no-repeat -44px 0;  
    float:right;  
}  
.control p.btnLight{  
    background:url(control.png) no-repeat -44px -60px;  
    border-left:1px solid #404040;  
    float:right;  
}  
.control p.lighton{  
    background:url(control.png) no-repeat -44px -30px !important;  
}  
  
/* PROGRESS BAR CSS */  
/* Progress bar */  
.progress {  
    width:85%;  
    height:10px;  
    position:relative;  
    float:left;  
    cursor:pointer;  
    background: #444; /* fallback */  
    background:-moz-linear-gradient(top,#666,#333);  
    background:-webkit-linear-gradient(top,#666,#333);  
    background:-o-linear-gradient(top,#666,#333);  
    box-shadow:0 2px 3px #333 inset;  
    -moz-box-shadow:0 2px 3px #333 inset;  
    -webkit-box-shadow:0 2px 3px #333 inset;  
    border-radius:10px;  
    -moz-border-radius:10px;  
    -webkit-border-radius:10px;  
}  
.progress span {  
    height:100%;  
    position:absolute;  
    top:0;  
    left:0;  
    display:block;  
    border-radius:10px;  
    -moz-border-radius:10px;  
    -webkit-border-radius:10px;  
}  
.timeBar{  
    z-index:10;  
    width:0;  
    background: #3FB7FC; /* fallback */  
    background:-moz-linear-gradient(top,#A0DCFF 50%,#3FB7FC 50%,#16A9FF 100%);  
    background:-webkit-linear-gradient(top,#A0DCFF 50%,#3FB7FC 50%,#16A9FF 100%);  
    background:-o-linear-gradient(top,#A0DCFF 50%,#3FB7FC 50%,#16A9FF 100%);  
    box-shadow:0 0 1px #fff;  
    -moz-box-shadow:0 0 1px #fff;  
    -webkit-box-shadow:0 0 1px #fff;  
}  
.bufferBar{  
    z-index:5;  
    width:0;  
    background: #777;  
    background:-moz-linear-gradient(top,#999,#666);  
    background:-webkit-linear-gradient(top,#999,#666);  
    background:-o-linear-gradient(top,#999,#666);  
    box-shadow:2px 0 5px #333;  
    -moz-box-shadow:2px 0 5px #333;  
    -webkit-box-shadow:2px 0 5px #333;  
}  
/* time and duration */  
.time{  
    width:15%;  
    float:right;  
    text-align:center;  
    font-size:11px;  
    line-height:12px;  
}  
  
/* VOLUME BAR CSS */  
/* volume bar */  
.volume{  
    position:relative;  
    cursor:pointer;  
    width:70px;  
    height:10px;  
    float:right;  
    margin-top:10px;  
    margin-right:10px;  
}  
.volumeBar{  
    display:block;  
    height:100%;  
    position:absolute;  
    top:0;  
    left:0;  
    background-color:#eee;  
    z-index:10;  
}  
  
/* OTHERS CSS */  
/* video screen cover */  
.loading, #init{  
    position:absolute;  
    top:0;  
    left:0;  
    width:100%;  
    height:100%;  
    background:url(loading.gif) no-repeat 50% 50%;  
    z-index:2;  
    display:none;  
}  
#init{  
    background:url(bigplay.png) no-repeat 50% 50% !important;  
    cursor:pointer;  
}

video.js

$(document).ready(function(){  
    //INITIALIZE  
    var video = $('#myVideo');  
      
    //remove default control when JS loaded  
    video[0].removeAttribute("controls");  
    $('.control').show().css({'bottom':-45});  
    $('.loading').fadeIn(500);  
    $('.caption').fadeIn(500);  
   
    //before everything get started  
    video.on('loadedmetadata', function() {  
        $('.caption').animate({'top':-45},300);  
              
        //set video properties  
        $('.current').text(timeFormat(0));  
        $('.duration').text(timeFormat(video[0].duration));  
        updateVolume(0, 0.7);  
              
        //start to get video buffering data   
        setTimeout(startBuffer, 150);  
              
        //bind video events  
        $('.videoContainer')  
        .append('

&#39;)           .hover(function() {               $(&#39;.control&#39;).stop().animate({&#39;bottom&#39;:0}, 500);               $(&#39;.caption&#39;).stop().animate({&#39;top&#39;:0}, 500);           }, function() {               if(!volumeDrag && !timeDrag){                   $(&#39;.control&#39;).stop().animate({&#39;bottom&#39;:-45}, 500);                   $(&#39;.caption&#39;).stop().animate({&#39;top&#39;:-45}, 500);               }           })           .on(&#39;click&#39;, function() {               $(&#39;#init&#39;).remove();               $(&#39;.btnPlay&#39;).addClass(&#39;paused&#39;);               $(this).unbind(&#39;click&#39;);               video[0].play();           });           $(&#39;#init&#39;).fadeIn(200);       });              //display video buffering bar       var startBuffer = function() {           var currentBuffer = video[0].buffered.end(0);           var maxduration = video[0].duration;           var perc = 100 * currentBuffer / maxduration;           $(&#39;.bufferBar&#39;).css(&#39;width&#39;,perc+&#39;%&#39;);                          if(currentBuffer < maxduration) {               setTimeout(startBuffer, 500);           }       };                //display current video play time       video.on(&#39;timeupdate&#39;, function() {           var currentPos = video[0].currentTime;           var maxduration = video[0].duration;           var perc = 100 * currentPos / maxduration;           $(&#39;.timeBar&#39;).css(&#39;width&#39;,perc+&#39;%&#39;);               $(&#39;.current&#39;).text(timeFormat(currentPos));        });              //CONTROLS EVENTS       //video screen and play button clicked       video.on(&#39;click&#39;, function() { playpause(); } );       $(&#39;.btnPlay&#39;).on(&#39;click&#39;, function() { playpause(); } );       var playpause = function() {           if(video[0].paused || video[0].ended) {               $(&#39;.btnPlay&#39;).addClass(&#39;paused&#39;);               video[0].play();           }           else {               $(&#39;.btnPlay&#39;).removeClass(&#39;paused&#39;);               video[0].pause();           }       };              //speed text clicked       $(&#39;.btnx1&#39;).on(&#39;click&#39;, function() { fastfowrd(this, 1); });       $(&#39;.btnx3&#39;).on(&#39;click&#39;, function() { fastfowrd(this, 3); });       var fastfowrd = function(obj, spd) {           $(&#39;.text&#39;).removeClass(&#39;selected&#39;);           $(obj).addClass(&#39;selected&#39;);           video[0].playbackRate = spd;           video[0].play();       };              //stop button clicked       $(&#39;.btnStop&#39;).on(&#39;click&#39;, function() {           $(&#39;.btnPlay&#39;).removeClass(&#39;paused&#39;);           updatebar($(&#39;.progress&#39;).offset().left);           video[0].pause();       });              //fullscreen button clicked       $(&#39;.btnFS&#39;).on(&#39;click&#39;, function() {           if($.isFunction(video[0].webkitEnterFullscreen)) {               video[0].webkitEnterFullscreen();           }              else if ($.isFunction(video[0].mozRequestFullScreen)) {               video[0].mozRequestFullScreen();           }           else {               alert(&#39;Your browsers doesn\&#39;t support fullscreen&#39;);           }       });              //light bulb button clicked       $(&#39;.btnLight&#39;).click(function() {           $(this).toggleClass(&#39;lighton&#39;);                      //if lightoff, create an overlay           if(!$(this).hasClass(&#39;lighton&#39;)) {               $(&#39;body&#39;).append(&#39;

&#39;);               $(&#39;.overlay&#39;).css({                   &#39;position&#39;:&#39;absolute&#39;,                   &#39;width&#39;:100+&#39;%&#39;,                   &#39;height&#39;:$(document).height(),                   &#39;background&#39;:&#39;#000&#39;,                   &#39;opacity&#39;:0.9,                   &#39;top&#39;:0,                   &#39;left&#39;:0,                   &#39;z-index&#39;:999               });               $(&#39;.videoContainer&#39;).css({                   &#39;z-index&#39;:1000               });           }           //if lighton, remove overlay           else {               $(&#39;.overlay&#39;).remove();           }       });              //sound button clicked       $(&#39;.sound&#39;).click(function() {           video[0].muted = !video[0].muted;           $(this).toggleClass(&#39;muted&#39;);           if(video[0].muted) {               $(&#39;.volumeBar&#39;).css(&#39;width&#39;,0);           }           else{               $(&#39;.volumeBar&#39;).css(&#39;width&#39;, video[0].volume*100+&#39;%&#39;);           }       });              //VIDEO EVENTS       //video canplay event       video.on(&#39;canplay&#39;, function() {           $(&#39;.loading&#39;).fadeOut(100);       });              //video canplaythrough event       //solve Chrome cache issue       var completeloaded = false;       video.on(&#39;canplaythrough&#39;, function() {           completeloaded = true;       });              //video ended event       video.on(&#39;ended&#39;, function() {           $(&#39;.btnPlay&#39;).removeClass(&#39;paused&#39;);           video[0].pause();       });          //video seeking event       video.on(&#39;seeking&#39;, function() {           //if video fully loaded, ignore loading screen           if(!completeloaded) {                $(&#39;.loading&#39;).fadeIn(200);           }          });              //video seeked event       video.on(&#39;seeked&#39;, function() { });              //video waiting for more data event       video.on(&#39;waiting&#39;, function() {           $(&#39;.loading&#39;).fadeIn(200);       });              //VIDEO PROGRESS BAR       //when video timebar clicked       var timeDrag = false;   /* check for drag event */       $(&#39;.progress&#39;).on(&#39;mousedown&#39;, function(e) {           timeDrag = true;           updatebar(e.pageX);       });       $(document).on(&#39;mouseup&#39;, function(e) {           if(timeDrag) {               timeDrag = false;               updatebar(e.pageX);           }       });       $(document).on(&#39;mousemove&#39;, function(e) {           if(timeDrag) {               updatebar(e.pageX);           }       });       var updatebar = function(x) {           var progress = $(&#39;.progress&#39;);                      //calculate drag position           //and update video currenttime           //as well as progress bar           var maxduration = video[0].duration;           var position = x - progress.offset().left;           var percentage = 100 * position / progress.width();           if(percentage > 100) {               percentage = 100;           }           if(percentage < 0) {               percentage = 0;           }           $(&#39;.timeBar&#39;).css(&#39;width&#39;,percentage+&#39;%&#39;);             video[0].currentTime = maxduration * percentage / 100;       };          //VOLUME BAR       //volume bar event       var volumeDrag = false;       $(&#39;.volume&#39;).on(&#39;mousedown&#39;, function(e) {           volumeDrag = true;           video[0].muted = false;           $(&#39;.sound&#39;).removeClass(&#39;muted&#39;);           updateVolume(e.pageX);       });       $(document).on(&#39;mouseup&#39;, function(e) {           if(volumeDrag) {               volumeDrag = false;               updateVolume(e.pageX);           }       });       $(document).on(&#39;mousemove&#39;, function(e) {           if(volumeDrag) {               updateVolume(e.pageX);           }       });       var updateVolume = function(x, vol) {           var volume = $(&#39;.volume&#39;);           var percentage;           //if only volume have specificed           //then direct update volume           if(vol) {               percentage = vol * 100;           }           else {               var position = x - volume.offset().left;               percentage = 100 * position / volume.width();           }                      if(percentage > 100) {               percentage = 100;           }           if(percentage < 0) {               percentage = 0;           }                      //update volume bar and video volume           $(&#39;.volumeBar&#39;).css(&#39;width&#39;,percentage+&#39;%&#39;);               video[0].volume = percentage / 100;                      //change sound icon based on volume           if(video[0].volume == 0){               $(&#39;.sound&#39;).removeClass(&#39;sound2&#39;).addClass(&#39;muted&#39;);           }           else if(video[0].volume > 0.5){               $(&#39;.sound&#39;).removeClass(&#39;muted&#39;).addClass(&#39;sound2&#39;);           }           else{               $(&#39;.sound&#39;).removeClass(&#39;muted&#39;).removeClass(&#39;sound2&#39;);           }                  };          //Time format converter - 00:00       var timeFormat = function(seconds){           var m = Math.floor(seconds/60)<10 ? "0"+Math.floor(seconds/60) : Math.floor(seconds/60);       var s = Math.floor(seconds-(m*60))<10 ? "0"+Math.floor(seconds-(m*60)) :Math.floor(seconds-(m*60));           return m+":"+s;       };   });

关于“如何利用HTML5制作一个好看的视频播放器”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。


推荐阅读
  • 本文整理了常用的CSS属性及用法,包括背景属性、边框属性、尺寸属性、可伸缩框属性、字体属性和文本属性等,方便开发者查阅和使用。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • 本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ... [详细]
  • 本文介绍了响应式页面的概念和实现方式,包括针对不同终端制作特定页面和制作一个页面适应不同终端的显示。分析了两种实现方式的优缺点,提出了选择方案的建议。同时,对于响应式页面的需求和背景进行了讨论,解释了为什么需要响应式页面。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • JavaScript简介及语言特点
    本文介绍了JavaScript的起源和发展历程,以及其在前端验证和服务器端开发中的应用。同时,还介绍了ECMAScript标准、DOM对象和BOM对象的作用及特点。最后,对JavaScript作为解释型语言和编译型语言的区别进行了说明。 ... [详细]
  • 本文介绍了网页播放视频的三种实现方式,分别是使用html5的video标签、使用flash来播放以及使用object标签。其中,推荐使用html5的video标签来简单播放视频,但有些老的浏览器不支持html5。另外,还可以使用flash来播放视频,需要使用object标签。 ... [详细]
  • 如何压缩网站页面以减少页面加载时间
    本文介绍了影响网站打开时间的两个因素,即网页加载速度和网站页面大小。重点讲解了如何通过压缩网站页面来减少页面加载时间。具体包括图片压缩、Javascript压缩、CSS压缩和HTML压缩等方法,并推荐了相应的压缩工具。此外,还提到了一款Google Chrome插件——网页加载速度分析工具Speed Tracer。 ... [详细]
author-avatar
拍友2502868875
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有