Video.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. Namespace.register("U.MD.UI.video"); //注册命名空间
  2. /**
  3. * 创建视频
  4. * @param src 资源地址
  5. * @param width 视频宽度
  6. * @param height 视频高度
  7. * @param autoplay 是否自动播放
  8. * @param parent 生成在哪个元素
  9. */
  10. U.MD.UI.video = function (src, width, height, autoplay, parent) {
  11. var _autoplay = autoplay || false; //检测自动播放
  12. var _intervalTemp = null; //用于记录interval的值
  13. var _volumeTemp = null; //用于记录临时音量(静音与取消静音用)
  14. var _moving = false; //记录是否有移动
  15. var _tempHeight = ""; //全屏恢复的临时高度
  16. var _tempWidth = ""; //全屏恢复的临时宽度
  17. var _fullscreen = false; //记录是否处于全屏状态
  18. /*生成元素*/
  19. var _els = U.MD.UI.video.appendEle(src, width, height, _autoplay, parent);
  20. /*添加事件*/
  21. U.MD.UI.video.addEvent(_els, _intervalTemp, _volumeTemp, _moving, height, width, _fullscreen);
  22. return _els;
  23. };
  24. /**
  25. * 生成元素
  26. * @param src 视频资源地址
  27. * @param width 视频宽度
  28. * @param height 视频高度
  29. * @param autoplay 是否自动播放
  30. * @param parent 父元素
  31. */
  32. U.MD.UI.video.appendEle = function (src, width, height, autoplay, parent) {
  33. var els = {};
  34. //包括视频和控制器的大div
  35. els.videoDiv = $$("div", { "className": "U_MD_UI_video_VideoDiv", "style": { "width": width + "px", "height": height + "px"} }, parent);
  36. //视频主体
  37. els.video = $$("video", {
  38. "src": src, //视频资源地址
  39. "className": "U_MD_UI_video_VideoMain", //视频class
  40. "autoplay": autoplay, //是否自动播放
  41. "preload": "auto"//是否预加载(默认自动)
  42. }, els.videoDiv);
  43. //控制器主体
  44. els.controls = $$("div", { "className": "U_MD_UI_video_VideoControls" }, els.videoDiv);
  45. //暂停/播放按钮
  46. els.playPauseBtn = $$("div", { "className": "U_MD_UI_video_PlayPauseButton U_MD_UI_video_PlayIcon" }, els.controls);
  47. //显示当前时间的div
  48. els.currentTimeDiv = $$("div", { "className": "U_MD_UI_video_Time", "innerHTML": "00:00" }, els.controls);
  49. //进度条
  50. els.progress = $$("div", { "className": "U_MD_UI_video_Progress" }, els.controls);
  51. //进度条实际进度
  52. els.progressCurrentTime = $$("div", { "className": "U_MD_UI_video_ProgressCurrentTime" }, els.progress);
  53. //进度条上的圆点
  54. els.progressCircle = $$("div", { "className": "U_MD_UI_video_ProgressCircle" }, els.progressCurrentTime);
  55. //显示实际时间的div
  56. els.DurationDiv = $$("div", {
  57. "className": "U_MD_UI_video_Time", //设置class
  58. "innerHTML": "00:00", //设置默认值
  59. "onselectstart": "return false;"//禁止选择
  60. }, els.controls);
  61. //音量按钮
  62. els.soundControls = $$("div", { "className": "U_MD_UI_video_SoundControls" }, els.controls);
  63. //音量
  64. els.soundProgress = $$("div", { "className": "U_MD_UI_video_SoundProgress" }, els.controls);
  65. //真实音量
  66. els.soundProgressCurrent = $$("div", { "className": "U_MD_UI_video_SoundProgressCurrent", "style": { "width": "100%"} }, els.soundProgress); //设置class
  67. //全屏按钮
  68. els.fullScreenBtn = $$("div", { "className": "U_MD_UI_video_FullScreen" }, els.controls);
  69. return els;
  70. };
  71. /**
  72. * 给元素添加事件
  73. * @param els 传入所有元素
  74. * @param intervalTemp 传入intervalTemp
  75. * @param volumeTemp 传入volumeTemp
  76. * @param moving 传入moving
  77. * @param tempHeight 传入tempHeight
  78. * @param tempWidth 传入tempWidth
  79. * @param fullscreen 传入fullscreen
  80. */
  81. U.MD.UI.video.addEvent = function (els, intervalTemp, volumeTemp, moving, tempHeight, tempWidth, fullscreen) {
  82. //给暂停/播放按钮添加事件
  83. els.playPauseBtn.onclick = function (event) {
  84. U.MD.UI.playPauseBtnClick(event, els);
  85. };
  86. if (els.videoDiv.onwebkitfullscreenchange !== undefined) {//设置全屏状态事件(webkit)
  87. els.videoDiv.onwebkitfullscreenchange = function () {
  88. var rtn = U.MD.UI.video.fullscreenChange(fullscreen, tempHeight, tempWidth, els);
  89. fullscreen = rtn[0];
  90. tempHeight = rtn[1];
  91. tempWidth = rtn[2];
  92. }
  93. }
  94. else if (els.videoDiv.onfullscreenchange !== undefined) {//设置全屏状态事件(w3)
  95. els.videoDiv.onfullscreenchange = function () {
  96. var rtn = U.MD.UI.video.fullscreenChange(fullscreen, tempHeight, tempWidth, els); //设置全屏状态事件(w3)
  97. fullscreen = rtn[0];
  98. tempHeight = rtn[1];
  99. tempWidth = rtn[2];
  100. }
  101. } else if (els.videoDiv.onmozfullscreenchange !== undefined) {//设置全屏状态事件(moz)
  102. els.videoDiv.onmozfullscreenchange = function () {
  103. var rtn = U.MD.UI.video.fullscreenChange(fullscreen, tempHeight, tempWidth, els);
  104. fullscreen = rtn[0];
  105. tempHeight = rtn[1];
  106. tempWidth = rtn[2];
  107. }
  108. }
  109. /**
  110. * 全屏按钮单击事件
  111. */
  112. els.fullScreenBtn.onclick = function () {
  113. U.MD.UI.video.fullscreenClick(fullscreen, els);
  114. };
  115. /**
  116. * 进度条圆点按下事件
  117. * @param event 按下事件
  118. */
  119. els.progressCircle.onmousedown = function (event) {
  120. U.MD.UI.video.circleMove(event, moving, els);
  121. };
  122. /**
  123. * 音量条鼠标按下事件
  124. * @param event 事件
  125. */
  126. els.soundProgress.onmousedown = function (event) {
  127. U.MD.UI.video.soundProgressMove(event, els, moving); //执行soundProgressMove函数
  128. };
  129. /**
  130. * 进度条鼠标按下事件
  131. * @param event 事件
  132. */
  133. els.progress.onmousedown = function (event) {
  134. U.MD.UI.video.progressMove(event, els, moving); //进度条按下移动函数(点击进度条除圆点以外的地方)
  135. };
  136. /**
  137. * 视频暂停事件,用于设置暂停按钮与停止刷新
  138. */
  139. els.video.onpause = function () {
  140. els.playPauseBtn.className = "U_MD_UI_video_PlayPauseButton U_MD_UI_video_PlayIcon"; //设置暂停按钮的icon(修改class)
  141. clearInterval(intervalTemp); //清除刷新的interval
  142. };
  143. /**
  144. * 视频播放事件,用于设置播放按钮与启动刷新
  145. */
  146. els.video.onplay = function () {
  147. els.playPauseBtn.className = "U_MD_UI_video_PlayPauseButton U_MD_UI_video_PauseIcon"; //设置开始按钮的icon(修改class)
  148. intervalTemp = U.MD.UI.video.setInterval(moving, els); //启动刷新
  149. };
  150. /**
  151. * 视频可以播放,刷新数据
  152. */
  153. els.video.oncanplay = function () {
  154. U.MD.UI.video.flushInfo(moving, els.currentTimeDiv, els.DurationDiv, els.progressCurrentTime, els.soundProgressCurrent, els.video); //刷新信息
  155. };
  156. /**
  157. * 静音按钮事件函数
  158. */
  159. els.soundControls.onclick = function () {
  160. volumeTemp = U.MD.UI.video.muteClick(els, volumeTemp, moving);
  161. };
  162. /**
  163. * 控制栏显示/隐藏控制
  164. */
  165. els.videoDiv.onclick = function () {
  166. //U.MD.UI.video.displayControls(event, els);
  167. };
  168. };
  169. /**
  170. * 让控制栏可以隐藏
  171. * @param event 视频点击事件
  172. * @param els 元素集合
  173. */
  174. U.MD.UI.video.displayControls = function (event, els) {
  175. var _target = event.target; //获取目标
  176. if (_target === els.video || _target === els.videoDiv) {//判断目标点击后是否可以隐藏/显示
  177. if (els.controls.style.display === "none") {//如果已设置隐藏状态则显示
  178. els.controls.style.display = "block";
  179. } else {//否则隐藏控制栏
  180. els.controls.style.display = "none";
  181. }
  182. }
  183. };
  184. U.MD.UI.playPauseBtnClick = function (event, els) {
  185. var _el = event.target; //获取到按钮本身
  186. if (_el.className === "U_MD_UI_video_PlayPauseButton U_MD_UI_video_PlayIcon") {//暂停状态
  187. els.video.play(); //开始播放
  188. }
  189. else {//播放状态
  190. els.video.pause(); //暂停播放
  191. }
  192. };
  193. /**
  194. * 静音按钮
  195. * @param els 元素集合
  196. * @param volumeTemp 临时记录音量
  197. * @param moving 记录是否正在移动(刷新数据用)
  198. * @returns {*} 返回volumeTemp
  199. */
  200. U.MD.UI.video.muteClick = function (els, volumeTemp, moving) {
  201. if (els.video.volume !== 0) {//音量非零,静音
  202. volumeTemp = els.video.volume; //记录当前音量
  203. els.video.volume = 0; //静音
  204. U.MD.UI.video.flushInfo(moving, els.currentTimeDiv, els.DurationDiv, els.progressCurrentTime, els.soundProgressCurrent, els.video); //刷新信息
  205. } else if (els.video.volume === 0 && volumeTemp !== null) {//如果音量等于0(即静音),且用户没有按过静音键
  206. els.video.volume = volumeTemp; //设置音量
  207. volumeTemp = null; //将变量值重置
  208. U.MD.UI.video.flushInfo(moving, els.currentTimeDiv, els.DurationDiv, els.progressCurrentTime, els.soundProgressCurrent, els.video); //刷新信息
  209. }
  210. return volumeTemp; //返回volumeTemp
  211. };
  212. /**
  213. * 全屏按钮点击事件
  214. * @param fullscreen 是否全屏
  215. * @param els 元素集合
  216. */
  217. U.MD.UI.video.fullscreenClick = function (fullscreen, els) {
  218. if (!fullscreen) {//如果没全屏
  219. if (els.videoDiv.requestFullScreen) {//请求全屏(w3)
  220. els.videoDiv.requestFullScreen(); //请求全屏(w3)
  221. }
  222. else if (els.videoDiv.webkitRequestFullScreen) {//请求全屏(webkit)
  223. els.videoDiv.webkitRequestFullScreen(); //请求全屏(webkit)
  224. }
  225. else if (els.videoDiv.mozRequestFullScreen) {//请求全屏(moz)
  226. els.videoDiv.mozRequestFullScreen(); //请求全屏(moz)
  227. }
  228. } else {//如果已全屏
  229. if (document.exitFullScreen) {//取消全屏(w3)
  230. document.exitFullScreen(); //取消全屏(w3)
  231. }
  232. else if (document.webkitCancelFullScreen) {//取消全屏(webkit)
  233. document.webkitCancelFullScreen(); //取消全屏(webkit)
  234. }
  235. else if (document.webkitExitFullscreen) {//取消全屏(webkit)
  236. document.webkitExitFullscreen(); //取消全屏(webkit)
  237. }
  238. else if (document.mozExitFullScreen) {//取消全屏(moz)
  239. document.mozExitFullScreen(); //取消全屏(moz)
  240. }
  241. }
  242. };
  243. /**
  244. * 全屏状态改变事件
  245. * @param fullscreen 记录是否全屏
  246. * @param tempHeight 临时高度
  247. * @param tempWidth 临时宽度
  248. * @param els 元素集合
  249. * @returns {*[]} 返回部分改变后的变量
  250. */
  251. U.MD.UI.video.fullscreenChange = function (fullscreen, tempHeight, tempWidth, els) {
  252. if (!fullscreen) {//如果没全屏,则进行全屏准备操作
  253. //tempHeight = els.videoDiv.offsetHeight + "px";//备份视频div高度
  254. //tempWidth = els.videoDiv.offsetWidth + "px";//备份视频div宽度
  255. els.videoDiv.style.height = "100vh"; //100vh为覆盖整个页面
  256. els.videoDiv.style.width = "100vw"; //100vw为覆盖整个页面
  257. els.videoDiv.style.position = "absolute"; //将视频设置绝对定位
  258. els.videoDiv.style.top = "0"; //移动到最上
  259. els.videoDiv.style.left = "0"; //移动到最左
  260. els.videoDiv.style.zIndex = "999"; //设置zIndex最高
  261. } else {//退出全屏
  262. els.videoDiv.style.height = tempHeight + "px"; //恢复高度
  263. els.videoDiv.style.width = tempWidth + "px"; //恢复宽度
  264. els.videoDiv.style.position = ""; //清除绝对定位
  265. els.videoDiv.style.top = ""; //清除top属性
  266. els.videoDiv.style.left = ""; //清除left属性
  267. els.videoDiv.style.zIndex = ""; //清除zIndex属性
  268. }
  269. fullscreen = !fullscreen; //设置全屏状态
  270. return [fullscreen, tempHeight, tempWidth];
  271. };
  272. /**
  273. * 时间格式化(数字秒转换成00:00的格式)
  274. * @param time 待转换的时间(秒) 例:30
  275. * @returns {string} 返回的时间 例:00:30
  276. */
  277. U.MD.UI.video.timeFormat = function (time) {
  278. var _sec = parseInt(time % 60); //计算秒
  279. var _min = parseInt(parseInt(time) / 60); //计算分钟
  280. (_sec < 10) ? _sec = "0" + _sec : _sec; //秒补零
  281. (_min < 10) ? _min = "0" + _min : _min; //分钟补零
  282. return _min + ":" + _sec; //返回生成的时间
  283. };
  284. /**
  285. * 刷新数据
  286. * @param moving 是否正在移动(用于判断要不要刷新)
  287. * @param currentTimeDiv 当前时间元素
  288. * @param DurationDiv 视频总长度元素
  289. * @param progressCurrentTime 进度条当前长度
  290. * @param soundProgressCurrent 音量当前长度
  291. * @param video 视频元素
  292. */
  293. U.MD.UI.video.flushInfo = function (moving, currentTimeDiv, DurationDiv, progressCurrentTime, soundProgressCurrent, video) {
  294. if (moving) return; //如果在拖动则不刷新
  295. currentTimeDiv.innerHTML = U.MD.UI.video.timeFormat(video.currentTime); //当前时间刷新
  296. DurationDiv.innerHTML = U.MD.UI.video.timeFormat(video.duration); //视频总长度刷新
  297. progressCurrentTime.style.width = video.currentTime / video.duration * 100 + "%"; //进度条刷新
  298. soundProgressCurrent.style.width = video.volume * 100 + "%"; //音量刷新
  299. };
  300. /**
  301. * 获取当前元素左边到屏幕最左边的距离
  302. * @param el 元素
  303. * @returns {number} 返回距离(不包括单位)
  304. */
  305. U.MD.UI.video.getScreenLeft = function (el) {
  306. var _rtnLeft = el.offsetLeft; //定义一个左边长度
  307. var _parent = el.offsetParent; //定义这个元素的父元素
  308. while (_parent != null) {//如果父元素不为空,则进入循环
  309. _rtnLeft += _parent.offsetLeft; //记录左边距离
  310. _parent = _parent.offsetParent; //重新定义父元素
  311. }
  312. return _rtnLeft; //返回距离
  313. };
  314. /**
  315. * 循环刷新信息
  316. * @param _moving 是否正在移动
  317. * @param _els 元素
  318. * @returns {number} interval
  319. */
  320. U.MD.UI.video.setInterval = function (_moving, _els) {
  321. return setInterval(function () {//设置定时器
  322. U.MD.UI.video.flushInfo(_moving, _els.currentTimeDiv, _els.DurationDiv, _els.progressCurrentTime, _els.soundProgressCurrent, _els.video); //刷新信息
  323. }, 500); //每半秒刷新一次
  324. };
  325. /**
  326. * 进度条(圆点)移动事件函数
  327. * @param event 鼠标按下事件
  328. * @param moving 是否正在移动
  329. * @param els 元素
  330. */
  331. U.MD.UI.video.circleMove = function (event, moving, els) {//进度条移动函数(圆点)
  332. moving = true; //设置移动状态
  333. var _e = event; //读取event
  334. var _content = event.currentTarget; //获取目标
  335. var _startX = _e.pageX; //设置一个开始的x点
  336. var _currentProgress = _content.parentElement; //获取当前进度条元素
  337. var _progress = _currentProgress.parentElement; //获取进度条元素
  338. els.videoDiv.onmousemove = function (e) {
  339. if (e.pageX - U.MD.UI.video.getScreenLeft(_progress) < 0 || e.pageX - U.MD.UI.video.getScreenLeft(_progress) > _progress.offsetWidth) {//如果鼠标位置不在有效范围内则不继续
  340. return;
  341. }
  342. var _iL = e.pageX - _startX; //移动的距离
  343. //根据实际进度与进度条长度对比进行判断
  344. if (!(_currentProgress.offsetWidth + _iL > _progress.offsetWidth || _currentProgress.offsetWidth + _iL < 0) && (e.currentTarget.children[0].offsetWidth <= e.currentTarget.children[0].offsetWidth)) {
  345. //设置进度条位置
  346. _currentProgress.style.width = (_currentProgress.offsetWidth + _iL) / _progress.offsetWidth * 100 + "%";
  347. //设置视频位置
  348. els.video.currentTime = (_currentProgress.offsetWidth + _iL) / _progress.offsetWidth * els.video.duration;
  349. }
  350. _startX = e.pageX; //重置开始的x点
  351. };
  352. els.videoDiv.onmouseup = function () {//清除事件
  353. moving = false; //恢复移动状态
  354. els.videoDiv.onmousemove = function () {//清除移动事件
  355. };
  356. els.videoDiv.onmouseup = function () {//清除mouseup事件
  357. };
  358. };
  359. };
  360. /**
  361. * 声音进度条拖动函数
  362. * @param event 事件
  363. * @param els 元素集合
  364. * @param moving 是否正在移动
  365. */
  366. U.MD.UI.video.soundProgressMove = function (event, els, moving) {//注释见move函数
  367. event.preventDefault(); //取消事件的默认动作
  368. var _e = event; //声明event
  369. var _content = event.currentTarget; //获取soundprogress
  370. var _startX = _e.pageX; //设置一个开始的x点
  371. var _currentSound = els.soundProgressCurrent; //当前的音量条元素
  372. var _x = event.offsetX; //获取现在鼠标相对于音量条的x点
  373. var _length = _content.offsetWidth; //获取音量条的长度
  374. els.video.volume = _x / _length; //设置视频音量
  375. U.MD.UI.video.flushInfo(moving, els.currentTimeDiv, els.DurationDiv, els.progressCurrentTime, els.soundProgressCurrent, els.video); //刷新信息
  376. /**
  377. * mousemove函数
  378. * @param e 事件
  379. */
  380. els.videoDiv.onmousemove = function (e) {
  381. if (e.pageX - U.MD.UI.video.getScreenLeft(els.soundProgress) < 0 || e.pageX - U.MD.UI.video.getScreenLeft(els.soundProgress) > els.soundProgress.offsetWidth) {//如果鼠标位置不在有效范围内则不继续
  382. return; //返回
  383. }
  384. var _iL = e.pageX - _startX; //移动的长度
  385. if (!(_currentSound.offsetWidth + _iL > _content.offsetWidth || _currentSound.offsetWidth + _iL < 0)) {//判断是否应该移动
  386. _currentSound.style.width = (_currentSound.offsetWidth + _iL) / _content.offsetWidth * 100 + "%"; //设置样式(进度条长度)
  387. els.video.volume = _currentSound.offsetWidth / _content.offsetWidth; //设置音量
  388. }
  389. _startX = e.pageX; //重置开始的x点
  390. };
  391. els.videoDiv.onmouseup = function (e) {
  392. els.videoDiv.onmousemove = function () {//清除mousemove事件
  393. };
  394. els.videoDiv.onmouseup = function () {//清除mouseup事件
  395. };
  396. };
  397. };
  398. /**
  399. * 进度条拖动函数
  400. * @param event 事件
  401. * @param els 元素集合
  402. * @param moving 是否正在移动
  403. */
  404. U.MD.UI.video.progressMove = function (event, els, moving) {//部分注释见move函数
  405. event.preventDefault(); //清除默认事件
  406. if (event.target.className === "U_MD_UI_video_ProgressCircle") {//如果class是圆点的话返回
  407. return;
  408. }
  409. var _e = event; //记录event
  410. var _content = U.selectEl(".U_MD_UI_video_Progress")[0]//event.currentTarget; //获取进度条元素
  411. var _startX = _e.pageX; //定义起点
  412. var _currentProgress = els.progressCurrentTime; //定义进度条(当前)元素
  413. var _x = event.layerX || event.offsetX; //鼠标点击的点
  414. var _length = _content.offsetWidth; //进度条长度
  415. els.video.currentTime = els.video.duration * (_x / _length); //计算出百分比并设置时间
  416. U.MD.UI.video.flushInfo(moving, els.currentTimeDiv, els.DurationDiv, els.progressCurrentTime, els.soundProgressCurrent, els.video); //刷新信息
  417. /*els.videoDiv.onmousemove = function (e) {//鼠标移动事件
  418. if (e.pageX - U.MD.UI.video.getScreenLeft(els.progress) < 0 || e.pageX - U.MD.UI.video.getScreenLeft(els.progress) > els.progress.offsetWidth) {//鼠标不在范围内则不继续
  419. return;
  420. }
  421. moving = true; //设置移动状态
  422. var _iL = e.pageX - _startX; //移动的长度
  423. if (!(_currentProgress.offsetWidth + _iL > els.progress.offsetWidth || _currentProgress.offsetWidth + _iL < 0)) {//判断加上移动距离后是否合理
  424. _currentProgress.style.width = (_currentProgress.offsetWidth + _iL) / els.progress.offsetWidth * 100 + "%"; //设置当前进度条的样式(宽度)
  425. els.video.currentTime = (_currentProgress.offsetWidth + _iL) / els.progress.offsetWidth * els.video.duration; //设置视频现在播放时间
  426. }
  427. _startX = e.pageX; //重新设置开始的点
  428. };*/
  429. els.videoDiv.onmouseup = function () {//鼠标点击事件
  430. moving = false; //设置移动状态
  431. U.MD.UI.video.flushInfo(moving, els.currentTimeDiv, els.DurationDiv, els.progressCurrentTime, els.soundProgressCurrent, els.video); //刷新信息
  432. els.videoDiv.onmousemove = function () {//清除事件
  433. };
  434. els.videoDiv.onmouseup = function () {//清除事件
  435. };
  436. };
  437. };