ProgressBar.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. <template>
  2. <div class="progress-box-bar" ref="progressbar">
  3. <canvas draggable="false" id="procanvas" height="60" @contextmenu="contextMenuClick" @mousedown="mousedownFunc" @mouseup="mouseupFunc" @mousemove="mousemoveFunc" @mouseout="mouseoutFunc"></canvas>
  4. <div class="bar-container">
  5. <div class="bar1"></div>
  6. <div class="bar2"></div>
  7. <div class="bar3"></div>
  8. </div>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. name:"ProgressBar",
  14. props:["timeCell","startTime","videoData"],
  15. data(){
  16. return{
  17. canvas:"",
  18. ctx:"",
  19. canvasW:"",
  20. canvasH:"",
  21. nowTime:"",
  22. hours_per_ruler:24, //时间轴显示12小时
  23. half_time:5*60*60*1000,
  24. graduation_step:20, //刻度间最小宽度,单位px
  25. start_timestamp:new Date().getTime()- 5*60*60*1000, //开始时间、最左侧时间
  26. minutes_per_step:[1, 2, 5, 10, 15, 20, 30, 60, 120, 180, 240, 360, 720, 1440],
  27. distance_between_gtitle:80,
  28. g_isMousedown:false, //拖动mousedown标记
  29. g_isMousemove:false, //拖动mousemove标记
  30. g_mousedownCursor:null, //拖动mousedown的位置
  31. returnTime: null, //mouseup返回时间
  32. downTime:[], //下载时间
  33. downLeft:0,
  34. showDown:false,
  35. tiaoTop:40,
  36. tiaoHeight:20,
  37. }
  38. },
  39. watch:{
  40. timeCell(){
  41. if(this.timeCell.length>0){
  42. this.nowTime = this.changeTime(new Date(this.timeCell[0].beginTime).getTime());
  43. this.start_timestamp = new Date(this.timeCell[0].beginTime).getTime()- this.half_time;
  44. this.clearCanvas();
  45. this.initCanvas();
  46. }
  47. },
  48. startTime(){
  49. if(!this.g_isMousedown){
  50. this.nowTime = this.changeTime(this.startTime+this.half_time);
  51. this.start_timestamp = this.startTime;
  52. this.clearCanvas();
  53. this.initCanvas();
  54. }
  55. }
  56. },
  57. mounted() {
  58. this.canvas = document.getElementById("procanvas");
  59. this.ctx = this.canvas.getContext('2d');
  60. this.canvas.width = this.$refs.progressbar.offsetWidth;
  61. this.canvasW = this.canvas.width;
  62. this.canvasH = this.canvas.height;
  63. this.nowTime = this.changeTime(new Date().getTime());
  64. this.initCanvas();
  65. },
  66. methods:{
  67. // 初始化canvas
  68. initCanvas:function(){
  69. this.drawCellBg();
  70. //this.add_cells(this.timeCell);
  71. this.add_graduations(this.start_timestamp);
  72. //this.draw_down(this.downTime);
  73. //this.drawTimeTriangle();
  74. },
  75. // // 绘制三角 时间
  76. drawTimeTriangle(){
  77. // this.ctx.beginPath();
  78. // let x = this.canvasW/2;
  79. // let x1 = this.canvasW/2-7;
  80. // let x2 = this.canvasW/2+7;
  81. // this.ctx.moveTo(x1,25);
  82. // this.ctx.lineTo(x2,25);
  83. // this.ctx.lineTo(x,36);
  84. // this.ctx.fillStyle = "#318ed4";
  85. // this.ctx.closePath();
  86. // this.ctx.fill();
  87. // this.ctx.fillStyle = "#fff";
  88. // this.ctx.font = "14px Arial";
  89. // this.ctx.fillText(this.nowTime,x-60,20);
  90. },
  91. // 画背景色
  92. drawCellBg:function(){
  93. this.ctx.fillStyle = "#eaeaea";
  94. this.ctx.fillRect(0, this.tiaoTop, this.canvasW, this.tiaoHeight);
  95. },
  96. // 添加刻度
  97. add_graduations:function(start_timestamp){
  98. var _this = this;
  99. var px_per_min = _this.canvasW / (_this.hours_per_ruler * 60); // px/min
  100. var px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
  101. var px_per_step = _this.graduation_step; // px/格 默认最小值20px
  102. var min_per_step = px_per_step / px_per_min; // min/格
  103. for(let i = 0; i < _this.minutes_per_step.length;i++){
  104. if(min_per_step <= _this.minutes_per_step[i]){ //让每格时间在minutes_per_step规定的范围内
  105. min_per_step = _this.minutes_per_step[i];
  106. px_per_step = px_per_min * min_per_step;
  107. break
  108. }
  109. }
  110. var medium_step = 30;
  111. for (let i = 0; i < _this.minutes_per_step.length; i++) {
  112. if (_this.distance_between_gtitle / px_per_min <= _this.minutes_per_step[i]) {
  113. medium_step = _this.minutes_per_step[i];
  114. break;
  115. }
  116. }
  117. var num_steps = _this.canvasW / px_per_step; //总格数
  118. var graduation_left;
  119. var graduation_time;
  120. var ms_offset = _this.ms_to_next_step(start_timestamp,min_per_step*60*1000);//开始的偏移时间 ms
  121. var px_offset = ms_offset * px_per_ms; //开始的偏移距离 px
  122. var ms_per_step = px_per_step / px_per_ms; // ms/step
  123. for(var i = 0; i < num_steps; i++){
  124. graduation_left = px_offset + i * px_per_step; // 距离=开始的偏移距离+格数*px/格
  125. graduation_time = start_timestamp + ms_offset + i * ms_per_step; //时间=左侧开始时间+偏移时间+格数*ms/格
  126. var date = new Date(graduation_time);
  127. if (graduation_time / (60 * 1000) % medium_step == 0) {
  128. var middle_date = _this.graduation_title(date);
  129. _this.ctx.fillStyle = "#318ed4";
  130. _this.ctx.font = "14px Arial";
  131. _this.ctx.fillText(middle_date,graduation_left-17,35);
  132. _this.drawLine(graduation_left,50,graduation_left,60,"#318ed4",1);
  133. }else{
  134. _this.drawLine(graduation_left,55,graduation_left,60,"rgba(49,142,212,0.7)",1);
  135. }
  136. }
  137. },
  138. // 画刻度线
  139. drawLine:function(beginX,beginY,endX,endY,color,width){
  140. this.ctx.beginPath();
  141. this.ctx.moveTo(beginX,beginY);
  142. this.ctx.lineTo(endX,endY);
  143. this.ctx.strokeStyle = color;
  144. this.ctx.lineWidth = width;
  145. this.ctx.stroke();
  146. },
  147. // 添加录像块
  148. // add_cells:function(cells){
  149. // var _this = this;
  150. // cells.forEach(cell => {
  151. // _this.draw_cell(cell)
  152. // });
  153. // },
  154. // 绘制录像块
  155. // draw_cell:function(cell){
  156. // var _this = this;
  157. // var px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
  158. // var beginX = (cell.beginTime - _this.start_timestamp) * px_per_ms;
  159. // var cell_width = ( cell.endTime - cell.beginTime) * px_per_ms;
  160. // _this.ctx.fillStyle = "#2d86cd";
  161. // _this.ctx.fillRect(beginX,this.tiaoTop,cell_width,this.tiaoHeight);
  162. // },
  163. // 绘制下载录像块
  164. // draw_down:function(cell){
  165. // var _this = this;
  166. // var px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
  167. // var beginX = cell[0]>cell[1]?(cell[1]- _this.start_timestamp)* px_per_ms:(cell[0]- _this.start_timestamp)* px_per_ms;
  168. // var cell_width = cell[0]>cell[1]?(cell[0]-cell[1])* px_per_ms:(cell[1]-cell[0])* px_per_ms;
  169. // _this.ctx.fillStyle = "#ff0000";
  170. // _this.ctx.fillRect(beginX,this.tiaoTop,cell_width,this.tiaoHeight);
  171. // },
  172. // 返回时间轴上刻度时间
  173. graduation_title:function(datetime){
  174. return (datetime.getHours()<10?'0'+datetime.getHours():datetime.getHours()) + ':' + ('0' + datetime.getMinutes().toString()).substr(-2);
  175. },
  176. // 开始时间 px
  177. ms_to_next_step:function(timestamp, step) {
  178. var remainder = timestamp % step;
  179. return remainder ? step - remainder : 0;
  180. },
  181. // 清除画布
  182. clearCanvas:function(){
  183. this.ctx.clearRect(0,0,this.canvasW,this.canvasH);
  184. },
  185. // 获取鼠标x位置
  186. get_cursor_x_position:function(e){
  187. var posx = 0;
  188. if (! e) {
  189. e = window.event;
  190. }
  191. if (e.pageX || e.pageY) {
  192. posx = e.pageX;
  193. }else if (e.clientX || e.clientY) {
  194. posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
  195. }
  196. return posx-455;//调整鼠标误差值
  197. },
  198. // 返回时间日期格式
  199. changeTime:function(time) {
  200. var newTime = new Date(time);
  201. var year = newTime.getFullYear();
  202. var month = newTime.getMonth() + 1;
  203. if(month < 10){
  204. var month = "0" + month;
  205. }
  206. var date = newTime.getDate();
  207. if (date < 10) {
  208. var date = "0" + date;
  209. }
  210. var hour = newTime.getHours();
  211. if (hour < 10) {
  212. var hour = "0" + hour;
  213. }
  214. var minute = newTime.getMinutes();
  215. if (minute < 10) {
  216. var minute = "0" + minute;
  217. }
  218. var second = newTime.getSeconds();
  219. if (second < 10) {
  220. var second = "0" + second;
  221. }
  222. return year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + second;
  223. },
  224. // 鼠标按下事件
  225. mousedownFunc:function(e){
  226. if(e.button == 2){
  227. }else{
  228. this.g_isMousedown = true;
  229. }
  230. this.g_mousedownCursor = this.get_cursor_x_position(e);//记住mousedown的位置
  231. },
  232. // 鼠标移动事件
  233. mousemoveFunc:function(e){
  234. let _this = this;
  235. let pos_x = _this.get_cursor_x_position(e);
  236. let px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
  237. _this.clearCanvas();
  238. if(_this.g_isMousedown){
  239. var diff_x = pos_x - _this.g_mousedownCursor;
  240. _this.start_timestamp = _this.start_timestamp - Math.round(diff_x / px_per_ms);
  241. _this.initCanvas();
  242. _this.g_isMousemove = true;
  243. _this.g_mousedownCursor = pos_x;
  244. this.nowTime = this.changeTime(_this.start_timestamp+this.half_time);
  245. }else{
  246. var time = _this.start_timestamp + pos_x/px_per_ms;
  247. _this.initCanvas();
  248. _this.drawLine(pos_x,30,pos_x,60,"rgb(49,142,212)",1);
  249. _this.ctx.fillStyle = "rgb(194, 202, 215)";
  250. _this.ctx.fillText(_this.changeTime(time),pos_x-65,35);
  251. }
  252. },
  253. //鼠标释放弹起事件
  254. mouseupFunc:function(e){
  255. if(e.button == 2){
  256. if(this.downTime.length==2){
  257. this.downLeft = this.g_mousedownCursor;
  258. this.showDown = true;
  259. }
  260. }else{
  261. this.g_isMousedown = false;
  262. this.g_isMousemove = false;
  263. let time = this.start_timestamp+this.half_time;
  264. this.$emit("setDragPlayTime",time);
  265. }
  266. },
  267. //鼠标移除隐藏时间事件
  268. mouseoutFunc:function(e){
  269. this.clearCanvas();
  270. this.initCanvas();
  271. },
  272. contextMenuClick:function(e){
  273. e.preventDefault();
  274. return;
  275. var _this = this;
  276. var pos_x = _this.get_cursor_x_position(e);
  277. var px_per_ms = _this.canvasW / (_this.hours_per_ruler * 60 * 60 * 1000); // px/ms
  278. var time = _this.start_timestamp + pos_x/px_per_ms;
  279. var flag = false;
  280. var index = 0;
  281. for(let i = 0;i<_this.timeCell.length;i++){
  282. if(time>=_this.timeCell[i].beginTime && time<=_this.timeCell[i].endTime){
  283. flag = true;
  284. index = i;
  285. }
  286. }
  287. if(flag){
  288. if(_this.downTime.length<2){
  289. _this.downTime.push(time);
  290. if(_this.downTime.length==2){
  291. _this.clearCanvas();
  292. _this.initCanvas();
  293. }
  294. }else if(_this.downTime.length==2){
  295. // console.log(_this.downTime);
  296. }
  297. }
  298. },
  299. downCLickBack(){
  300. if(this.downTime.length == 2){
  301. this.downTime.sort(function(a,b){
  302. return a-b
  303. })
  304. var userData = this.$store.getters.replayDownVideo.length+1;
  305. var startTime1 = this.downTime[0]<this.downTime[1]?this.downTime[0]:this.downTime[1];
  306. var startTime = this.changeTime(startTime1);
  307. var endTime1 = this.downTime[0]>=this.downTime[1]?this.downTime[0]:this.downTime[1];
  308. var endTime = this.changeTime(endTime1);
  309. var fileName = new Date().getTime()+".mp4";
  310. var server = this.$store.getters.serverConfig;
  311. var alltime = Math.ceil((endTime1-startTime1)/1000);
  312. var obj = {
  313. fileName:fileName,startTime:startTime,endTime:endTime,allTime:alltime,progress:"0%",userDate:userData,downType:0
  314. };
  315. var s_index = 0,e_index = 0;
  316. for(var i = 0;i<this.timeCell.length;i++){
  317. if(this.downTime[0]>=this.timeCell[i].beginTime&&this.downTime[0]<=this.timeCell[i].endTime){
  318. s_index = i;
  319. }
  320. if(this.downTime[1]>=this.timeCell[i].beginTime&&this.downTime[1]<=this.timeCell[i].endTime){
  321. e_index = i;
  322. }
  323. }
  324. var fileArr = new Array();
  325. for(var j=s_index;j<=e_index;j++){
  326. fileArr.push(this.videoData.videoList[j]);
  327. }
  328. var filesJson = JSON.stringify(fileArr);
  329. this.downTime.splice(0,this.downTime.length);
  330. var ss = document.getElementById("videoOcx").StartDownloadVodFile(server.ServerIP,server.ServerPort,filesJson,fileName,startTime,endTime,userData);
  331. this.$store.commit("addDownLoadVideo",obj);
  332. this.showDown = false;
  333. }
  334. },
  335. cancelDownClick(){
  336. this.downTime.splice(0,this.downTime.length);
  337. this.showDown = false;
  338. }
  339. }
  340. }
  341. </script>
  342. <style lang="scss" scoped>
  343. .progress-box-bar{
  344. position: relative;
  345. width:100%;
  346. height: 100%;
  347. }
  348. .progress-box-bar canvas{
  349. width: 100%;
  350. cursor: pointer;
  351. }
  352. .progress-box-bar .downVideo{
  353. position: absolute;
  354. z-index: 10;
  355. top: 0;
  356. left: 300px;
  357. }
  358. .progress-box-bar .downVideo ul{
  359. background-color: #fff;
  360. }
  361. .progress-box-bar .downVideo ul li{
  362. line-height: 20px;
  363. font-size: 12px;
  364. cursor: pointer;
  365. }
  366. .progress-box-bar .downVideo ul li:hover{
  367. background-color: #318ed4;
  368. }
  369. .bar-container{
  370. width: 100%;
  371. height: 20px;
  372. background-color: #eaeaea;
  373. position: relative;
  374. .bar1{
  375. width: 80%;
  376. height: 100%;
  377. position: absolute;
  378. top:0;
  379. left: 0;
  380. background: green;
  381. z-index:2;
  382. }
  383. .bar2{
  384. width: 93%;
  385. height: 100%;
  386. position: absolute;
  387. top:0;
  388. left: 0;
  389. background: rgb(0, 178, 255);
  390. z-index:1;
  391. }
  392. .bar3{
  393. width: 10%;
  394. height: 100%;
  395. position: absolute;
  396. top:0;
  397. left: 30%;
  398. background: red;
  399. z-index:3;
  400. }
  401. }
  402. </style>