Video.js 20 KB

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