UNPKG

ngx-video-timeline

Version:
823 lines 107 kB
import { NgStyle } from '@angular/common'; import { Component, EventEmitter, HostListener, Input, Output, ViewChild } from '@angular/core'; import { interval } from 'rxjs'; import { DateUtil } from './untils/date-util'; import * as i0 from "@angular/core"; export class NgxVideoTimelineComponent { // The height of the outer canvas canvasHeight = 50; // Canvas scale is adjusted according to outer height scale = this.canvasHeight / 4.55; // Video playback time playTime; // The video plays at twice the speed speed; // Video fast forward value forWardValue; // Start time limit: Timestamp startTimeThreshold; // End time limit: Timestamp endTimeThreshold; // relation to Css Start // color of canvas border borderColor; // color of canvas backgraound bgColor; // color of the bottomLine bottomLineColor; // color of the verticalBar verticalBarColor; // color of the playBar playBarColor; // relation to Css End // Video clips videoCells; // flag of click play button isPlayClick; // emit data when click playButton playClick; // emit data when mouseUp mouseUp; // emit data when mouseDown mouseDown; // emit data when keyUp keyUp; // emit data when keyDown keyDown; // --- canvas data start ---// // canvas box canvas; // canvas context ctx; // canvas width canvasW; // canvas height canvasH; // video clips in reality timecell; // per minute stand for step minutesPerStep; // per minite stand for px pxPerMs; // Minimum width between scales, unit px graduationStep; // The timeline shows x hours hoursPerRuler; // The leftmost timestamp that appears -- the default is the first 12 hours startTimestamp; // current timestamp currentTimestamp; // Px two hours apart distanceBetweenGtitle; // zoom of canvas zoom; // marker of drag an unreleased mouse event gIsMousedown; // marker of drag the mouse move gIsMousemove; // The position of the X-axis when the mouse is pressed gMousedownCursor = undefined; // The position of the y-axis when the mouse is pressed gMousedownCursorY = undefined; // Time flow timer setTimeMove; // The distance to the left of the play button playBarDistanceLeft; // Play the initial position of the icon playBarOffsetX; // Play the X-axis position 1 of the icon playBarOffsetX1; // Play the X-axis position 2 of the icon playBarOffsetX2; // Play the Y-axis position 1 of the icon playBarOffsetY1; // Play the Y-axis position 2 of the icon playBarOffsetY2; // --- canvas data end ---// // elements of the timeline canvasExp; constructor() { // this.startTimeThreshold = new Date().getTime() - 1 * 0.5 * 3600 * 1000; // this.endTimeThreshold = new Date().getTime() + 1 * 1 * 3600 * 1000; this.forWardValue = 5000; this.speed = 1000; this.playTime = new Date().getTime(); this.startTimeThreshold = new Date().getTime() - 1 * 12 * 3600 * 1000; this.endTimeThreshold = new Date().getTime() + 1 * 12 * 3600 * 1000; this.playClick = new EventEmitter(); this.mouseUp = new EventEmitter(); this.mouseDown = new EventEmitter(); this.keyUp = new EventEmitter(); this.keyDown = new EventEmitter(); this.isPlayClick = false; this.videoCells = [ { beginTime: new Date().getTime() - 3 * 3600 * 1000, endTime: new Date().getTime() - 1 * 3600 * 1000, style: { background: 'rgba(132, 244, 180, 0.498039)' } }, { beginTime: new Date().getTime() - 6 * 3600 * 1000, endTime: new Date().getTime() - 4 * 3600 * 1000, style: { background: 'rgba(132, 244, 180, 0.498039)' } } ]; this.verticalBarColor = 'rgba(0,0,0,1)'; this.bottomLineColor = 'rgba(0,0,0,1)'; this.borderColor = '#fff'; this.bgColor = '#fff'; this.playBarColor = '#448aff'; } /** * Browser change event */ onResize() { this.canvas.width = Math.round(this.canvas.parentNode.offsetWidth - 2); this.canvasW = this.canvas.parentNode.offsetWidth; this.init(this.startTimestamp, this.timecell, false); } /** * Keyboard press event */ onKeyDown(event) { if (Number(event.keyCode) === 37) { this.playTime = Number(this.playTime) - this.forWardValue; this.currentTimestamp = Number(this.currentTimestamp) - this.forWardValue; this.set_time_to_middle(this.playTime); } else if (Number(event.keyCode === 39)) { this.playTime = Number(this.playTime) + this.forWardValue; this.currentTimestamp = Number(this.currentTimestamp) + this.forWardValue; this.set_time_to_middle(this.playTime); } this.keyDown.emit(this.playTime); } /** * Keyboard release event */ onKeyUp(event) { if (Number(event.keyCode) === 13 || Number(event.keyCode === 32)) { this.isPlayClick ? this.onPauseClick() : this.onPlayClick(); } this.keyUp.emit(this.playTime); } ngOnInit() { // Initialize data video group event stamp to show new Date().getTime()- number of hours // Assign the Canvas DOM to the variable Canvas this.canvas = this.canvasExp.nativeElement; // Define the area of the canvas this.ctx = this.canvas.getContext('2d'); // Redefine the width of the canvas. The default canvas is 300. Assign the width of the parent element this.canvas.width = Math.round(this.canvas.parentNode.offsetWidth - 2); // Store the width and height of the canvas this.canvasW = this.canvas.width; this.canvas.height = this.canvasHeight; this.canvasH = this.canvas.height; // Assign the video array to Timecell this.timecell = this.videoCells; // Initialize the number of steps per minute this.minutesPerStep = [ 1, 2, 5, 10, 15, 20, 30, 60, 120, 180, 240, 360, 720, 1440 ]; // Initialization style // Minimum width between scales, in units of px 20px this.graduationStep = 20; // The timeline shows the time rounded up according to the time threshold this.hoursPerRuler = Math.ceil((Number(this.endTimeThreshold) - Number(this.startTimeThreshold)) / 1000 / 3600) < 24 ? Math.ceil((Number(this.endTimeThreshold) - Number(this.startTimeThreshold)) / 1000 / 3600) : 24; // The leftmost timestamp defaults to 12 hours before the current time this.startTimestamp = Number(this.startTimeThreshold); // Default distance 80 this.distanceBetweenGtitle = 80; // Default zoom 24 this.zoom = 24; // Default false this.gIsMousedown = false; this.gIsMousemove = false; this.gMousedownCursor = undefined; // px/ms this.pxPerMs = this.canvasW / (this.hoursPerRuler * 3600 * 1000); // The initial X position of the playback icon is in the middle of the scale this.playBarOffsetX = this.canvasW / 2; this.playBarDistanceLeft = this.playBarOffsetX / this.pxPerMs / 3600 / 1000 / this.hoursPerRuler; this.currentTimestamp = this.startTimestamp + this.hoursPerRuler * this.playBarDistanceLeft * 3600 * 1000; this.playBarOffsetX1 = this.playBarOffsetX - (this.scale * 0.6); this.playBarOffsetX2 = this.playBarOffsetX + (this.scale * 0.6); this.playBarOffsetY1 = (this.scale * 2.5); this.playBarOffsetY2 = ((this.scale * 3.5)); // Initialize the timeline this.init(this.startTimestamp, this.timecell, false); // Draw the play button this.drawPalyBar(); } ngOnChanges(changes) { // Refactor the playback component when the width and height change if (changes.canvasHeight) { this.canvasHeight = changes.canvasHeight.currentValue; // Assign the Canvas DOM to the variable Canvas this.canvas = this.canvasExp.nativeElement; // Define the area of the canvas this.ctx = this.canvas.getContext('2d'); // Redefine the width of the canvas. The default canvas is 300. Assign the width of the parent element this.canvas.width = Math.round(this.canvas.parentNode.offsetWidth - 2); // Store the width and height of the canvas this.canvasW = this.canvas.width; this.canvas.height = this.canvasHeight; this.canvasH = this.canvas.height; // Assign the video array to Timecell this.timecell = this.videoCells; this.minutesPerStep = [ 1, 2, 5, 10, 15, 20, 30, 60, 120, 180, 240, 360, 720, 1440 ]; // The timeline shows the time rounded up according to the time threshold this.hoursPerRuler = Math.ceil((Number(this.endTimeThreshold) - Number(this.startTimeThreshold)) / 1000 / 3600) < 24 ? Math.ceil((Number(this.endTimeThreshold) - Number(this.startTimeThreshold)) / 1000 / 3600) : 24; // The leftmost timestamp defaults to 12 hours before the current time this.startTimestamp = Number(this.startTimeThreshold); this.pxPerMs = this.canvasW / (this.hoursPerRuler * 3600 * 1000); // The initial X position of the playback icon is in the middle of the scale this.playBarOffsetX = this.canvasW / 2; this.playBarDistanceLeft = this.playBarOffsetX / this.pxPerMs / 3600 / 1000 / this.hoursPerRuler; // Current timestamp this.currentTimestamp = this.startTimestamp + this.hoursPerRuler * this.playBarDistanceLeft * 3600 * 1000; this.playBarOffsetX1 = this.playBarOffsetX - (this.scale * 0.6); this.playBarOffsetX2 = this.playBarOffsetX + (this.scale * 0.6); this.playBarOffsetY1 = (this.scale * 2.5); this.playBarOffsetY2 = ((this.scale * 3.5)); this.init(this.startTimestamp, this.timecell, false); this.drawPalyBar(); } if (changes.videoCells) { this.videoCells = changes.videoCells.currentValue; this.timecell = this.videoCells; this.add_cells(this.timecell); // this.init(this.startTimestamp, this.timecell, true); // this.drawPalyBar(); } if (changes.startTimeThreshold) { const value = changes.startTimeThreshold.currentValue; if (changes.startTimeThreshold.currentValue instanceof String) { this.startTimeThreshold = new Date(value).getTime(); } else if (value instanceof Date) { this.startTimeThreshold = value.getTime(); } else if (typeof value === 'number') { this.startTimeThreshold = Number(value); } this.hoursPerRuler = Math.ceil((Number(this.endTimeThreshold) - Number(this.startTimeThreshold)) / 1000 / 3600) < 24 ? Math.ceil((Number(this.endTimeThreshold) - Number(this.startTimeThreshold)) / 1000 / 3600) : 24; this.startTimestamp = Number(this.startTimeThreshold); // this.init(this.startTimestamp, this.timecell, false); } if (changes.endTimeThreshold) { const value = changes.endTimeThreshold.currentValue; if (changes.endTimeThreshold.currentValue instanceof String) { this.endTimeThreshold = new Date(value).getTime(); } else if (value instanceof Date) { this.endTimeThreshold = value.getTime(); } else if (typeof value === 'number') { this.endTimeThreshold = Number(value); } this.hoursPerRuler = Math.ceil((Number(this.endTimeThreshold) - Number(this.startTimeThreshold)) / 1000 / 3600) < 24 ? Math.ceil((Number(this.endTimeThreshold) - Number(this.startTimeThreshold)) / 1000 / 3600) : 24; } if (changes.playTime) { const value = changes.playTime.currentValue; if (changes.playTime.currentValue instanceof String) { this.playTime = new Date(value).getTime(); } else if (value instanceof Date) { this.playTime = value.getTime(); } else if (typeof value === 'number') { this.playTime = Number(value); } // use SetTimeOut Timer to make it asynchronous setTimeout(() => { this.set_time_to_middle(new Date(this.playTime).getTime()); }, 100); } if (changes.speed) { this.speed = Number(changes.speed.currentValue) * 1000; } if (changes.forWardValue) { this.forWardValue = Number(changes.forWardValue.currentValue) * 1000; } if (changes.isPlayClick) { if (changes.isPlayClick.currentValue) { this.onPlayClick(); } else { this.onPauseClick(); } } } /** * Initialize * @param startTimestamp Leftmost time * @param timecell Video segment array * @param redrawFlag Whether to redraw the mark */ init(startTimestamp, timecell, redrawFlag) { this.timecell = timecell; this.startTimestamp = startTimestamp; if (this.currentTimestamp >= Number(this.endTimeThreshold)) { this.startTimestamp = Number(this.endTimeThreshold) - (this.hoursPerRuler * this.playBarDistanceLeft * 1000 * 3600); this.currentTimestamp = Number(this.startTimestamp) + (this.hoursPerRuler * this.playBarDistanceLeft * 1000 * 3600); this.playTime = Number(this.startTimestamp) + (this.hoursPerRuler * this.playBarDistanceLeft * 1000 * 3600); } else if (this.currentTimestamp <= Number(this.startTimeThreshold)) { this.startTimestamp = Number(this.startTimeThreshold) - (this.hoursPerRuler * this.playBarDistanceLeft * 1000 * 3600); this.currentTimestamp = Number(this.startTimestamp) + (this.hoursPerRuler * this.playBarDistanceLeft * 1000 * 3600); this.playTime = Number(this.startTimestamp) + (this.hoursPerRuler * this.playBarDistanceLeft * 1000 * 3600); } this.drawCellBg(); this.add_graduations(startTimestamp); this.add_cells(timecell); // Draw the verticalBar this.drawLine(0, this.canvasH, this.canvasW, this.canvasH, this.bottomLineColor, 1); } /** * Draw add scale * @param startTimestamp Leftmost time */ add_graduations(startTimestamp) { // px/min const pxPerMin = this.canvasW / (this.hoursPerRuler * 60); // px/ms const pxPerMs = this.canvasW / (this.hoursPerRuler * 60 * 60 * 1000); // The default minimum value of PX/steo is 20px let pxPerStep = this.graduationStep; // Min/steo let minPerStep = pxPerStep / pxPerMin; for (const v of this.minutesPerStep) { if (minPerStep <= v) { // Keep each cell within the range specified by minutesPerStep minPerStep = v; pxPerStep = pxPerMin * minPerStep; break; } } let mediumStep = 30; for (const v of this.minutesPerStep) { if (this.distanceBetweenGtitle / pxPerMin <= v) { mediumStep = v; break; } } // The total number const numSteps = this.canvasW / pxPerStep; let graduationLeft; let graduationTime; let caretClass; let lineH; // The initial offset time (ms) const msOffset = this.ms_to_next_step(startTimestamp, minPerStep * 60 * 1000); // The initial offset is (px) const pxOffset = msOffset * pxPerMs; // ms/step const msPerStep = pxPerStep / pxPerMs; for (let i = 0; i < numSteps; i++) { // Distance = offset distance to start + steps *px/ steps graduationLeft = pxOffset + i * pxPerStep; // Time = left start time + offset time + steps *ms/ steps graduationTime = Number(startTimestamp) + Number(msOffset) + i * Number(msPerStep); const date = new Date(graduationTime); if (date.getUTCHours() === 0 && date.getUTCMinutes() === 0) { caretClass = 'big'; lineH = (this.scale * 1.25); const bigDate = DateUtil.formatDate(date, 'HH:mm:ss'); this.ctx.textAlign = 'center'; this.ctx.fillText(bigDate, graduationLeft, (this.scale * 1.5)); this.ctx.fillStyle = this.verticalBarColor; } else if ((graduationTime / (60 * 1000)) % mediumStep === 0) { caretClass = 'middle'; lineH = (this.scale * 0.75); const middleDate = DateUtil.formatDate(date, 'HH:mm:ss'); this.ctx.textAlign = 'center'; this.ctx.fillText(middleDate, graduationLeft, (this.scale * 1.5)); this.ctx.fillStyle = this.verticalBarColor; } else { lineH = (this.scale * 0.5); } // drawLine(graduationLeft,0,graduationLeft,lineH,"rgba(151,158,167,0.4)",1); this.drawLine(graduationLeft, 0, graduationLeft, lineH, this.verticalBarColor, 1); } } /** * Draw the play button */ drawPalyBar() { this.ctx.beginPath(); this.ctx.moveTo(this.playBarOffsetX, 0); this.ctx.lineTo(this.playBarOffsetX, (this.scale * 1.75)); this.ctx.strokeStyle = this.playBarColor; this.ctx.stroke(); this.ctx.moveTo(this.playBarOffsetX, (this.scale * 1.75)); this.ctx.lineTo(this.playBarOffsetX, (this.scale * 1.75)); this.ctx.lineTo(this.playBarOffsetX - (this.scale * 0.6), (this.scale * 2.5)); this.ctx.lineTo(this.playBarOffsetX - (this.scale * 0.6), (this.scale * 3.5)); this.ctx.lineTo(this.playBarOffsetX + (this.scale * 0.6), (this.scale * 3.5)); this.ctx.lineTo(this.playBarOffsetX + (this.scale * 0.6), (this.scale * 2.5)); this.ctx.lineTo(this.playBarOffsetX, (this.scale * 1.75)); this.ctx.fillStyle = this.playBarColor; this.ctx.fill(); this.ctx.closePath(); // this.init(this.startTimestamp, this.timecell, false); const time = Number(this.currentTimestamp); this.ctx.fillStyle = this.playBarColor; this.ctx.textAlign = 'center'; this.ctx.fillText(DateUtil.formatDate(new Date(time), 'YYYY-MM-DD HH:mm:ss'), this.playBarOffsetX, (this.scale * 4.25)); } /** * Draw the line * @param beginX The X-axis to start with * @param beginY The Y-axis to start with * @param endX The end of the X-axis * @param endY The end of the Y-axis * @param color color * @param width width */ drawLine(beginX, beginY, endX, endY, color, width) { this.ctx.beginPath(); this.ctx.moveTo(beginX, beginY); this.ctx.lineTo(endX, endY); this.ctx.strokeStyle = color; this.ctx.lineWidth = width; this.ctx.stroke(); } /** * Add video segment * @param cells Video array */ add_cells(cells) { cells.forEach((cell) => { this.draw_cell(cell); }); } /** * Draw video blocks * @param cell The cell includes beginTime Ms; The endTime ms; style; */ draw_cell(cell) { const pxPerMs = this.canvasW / (this.hoursPerRuler * 60 * 60 * 1000); // px/ms const beginX = (cell.beginTime - this.startTimestamp) * pxPerMs; const cellWidth = (cell.endTime - cell.beginTime) * pxPerMs; this.ctx.fillStyle = cell.style.background; this.ctx.fillRect(beginX, 0, cellWidth, (this.scale * 0.75)); } /** * Draws the background of the video block */ drawCellBg() { this.ctx.fillStyle = 'rgba(69, 72, 76, 0.5)'; this.ctx.fillRect(0, 0, this.canvasW, 0); } /** * Drag/click the Mousedown event */ mousedownFunc(e) { this.gIsMousedown = true; this.gMousedownCursor = this.get_cursor_x_position(e).posX; this.gMousedownCursorY = this.get_cursor_x_position(e).posY; } /** * Drag/mouse hover to display mousemove events */ mousemoveFunc(e) { this.clearCanvas(); const posX = this.get_cursor_x_position(e).posX; const pxPerMs = this.canvasW / (this.hoursPerRuler * 3600 * 1000); const diffX = posX - this.gMousedownCursor; if (this.gIsMousedown) { if (this.gMousedownCursor >= this.playBarOffsetX1 && this.gMousedownCursor <= this.playBarOffsetX2 && this.gMousedownCursorY >= this.playBarOffsetY1 && this.gMousedownCursorY <= this.playBarOffsetY2) { // this.playBarDistanceLeft = this.playBarOffsetX / this.pxPerMs / 3600 / 1000 / this.hoursPerRuler; // this.playBarOffsetX = posX; // this.playBarOffsetX1 = this.playBarOffsetX - (this.scale * 0.6); // this.playBarOffsetX2 = this.playBarOffsetX + (this.scale * 0.6); this.startTimestamp = this.startTimestamp + Math.round(diffX / pxPerMs); this.currentTimestamp = (this.startTimestamp + Math.round(this.playBarOffsetX / pxPerMs)); this.drawPalyBar(); this.init(this.startTimestamp, this.timecell, false); this.gIsMousemove = true; } else { this.startTimestamp = this.startTimestamp - Math.round(diffX / pxPerMs); this.currentTimestamp = this.startTimestamp + Math.round(this.playBarOffsetX / pxPerMs); this.drawPalyBar(); this.init(this.startTimestamp, this.timecell, true); this.gIsMousemove = true; this.gMousedownCursor = posX; } this.mouseUp.emit(this.currentTimestamp); } else { const time = this.startTimestamp + posX / pxPerMs; this.drawPalyBar(); this.init(this.startTimestamp, this.timecell, true); this.drawLine(posX, 0, posX, 50, 'rgb(194, 202, 215)', 1); this.ctx.fillStyle = 'rgb(194, 202, 215)'; this.ctx.textAlign = 'center'; this.ctx.fillText(DateUtil.formatDate(new Date(time), 'YYYY-MM-DD HH:mm:ss'), posX, (this.scale * 3)); } } /** * Drag/click the Mouseup event */ mouseupFunc(e) { if (this.gIsMousemove) { // Drag events this.gIsMousemove = false; this.gIsMousedown = false; this.playTime = this.startTimestamp + this.hoursPerRuler * this.playBarDistanceLeft * 3600 * 1000; } else { // Click event this.gIsMousedown = false; // Mouse distance (px) const posx = this.get_cursor_x_position(e).posX; // ms/px const msPerPx = (this.zoom * 3600 * 1000) / this.canvasW; this.playTime = this.startTimestamp + posx * msPerPx; this.set_time_to_middle(this.playTime); } this.mouseDown.emit(this.playTime); } /** * Mouseout of the hidden time mouseout event */ mouseoutFunc() { this.clearCanvas(); // px/ms const pxPerMs = this.canvasW / (this.hoursPerRuler * 3600 * 1000); this.currentTimestamp = this.startTimestamp + Math.round(this.playBarOffsetX / pxPerMs); this.drawPalyBar(); this.init(this.startTimestamp, this.timecell, true); } /** * Scroll to the center of the timeline for the mousewheel event */ mousewheelFunc(event) { if (event && event.preventDefault) { event.preventDefault(); } else { window.event.returnValue = false; return false; } const e = window.event || event; const delta = Math.max(-1, Math.min(1, e.wheelDelta || -e.detail)); // Ms Remember the current middle time const middleTime = this.startTimestamp + (this.hoursPerRuler * this.playBarDistanceLeft * 3600 * 1000); if (delta < 0) { this.zoom = this.zoom + 4; if (this.zoom >= 24) { // Shrink to a minimum of 24 hours this.zoom = 24; } this.hoursPerRuler = this.zoom; } else if (delta > 0) { // amplification this.zoom = this.zoom - 4; if (this.zoom <= 1) { // Zoom in at most one hour this.zoom = 1; } this.hoursPerRuler = this.zoom; } this.clearCanvas(); // // startTimestamp = current middle time - zoom /2 this.startTimestamp = middleTime - (this.hoursPerRuler * 3600 * 1000) / 2; this.init(this.startTimestamp, this.timecell, true); this.drawPalyBar(); } /** * Get the mouse POSx * @param e event */ get_cursor_x_position(e) { let posx = 0; let posy = 0; if (!e) { e = window.event; } if (e.offsetX || e.offsetY) { posx = e.offsetX; posy = e.offsetY; } return { posX: posx, posY: posy }; } /** * The offset of the left start time, returns the unit ms * @param timestamp The time stamp * @param step The offset */ ms_to_next_step(timestamp, step) { const remainder = timestamp % step; return remainder ? step - remainder : 0; } /** * Set the time to jump to the middle red line * @param time Unit of ms */ set_time_to_middle(time) { if (this.ctx) { this.clearCanvas(); this.startTimestamp = time - (this.hoursPerRuler * this.playBarDistanceLeft * 3600 * 1000); this.currentTimestamp = time; this.drawPalyBar(); this.init(this.startTimestamp, this.timecell, true); } } /** * To redraw on a canvas, it must first be cleared. */ clearCanvas() { this.ctx.clearRect(0, 0, this.canvasW, (this.scale * 7.5)); } /** * Click to play */ onPlayClick() { // this.setTimeMove = undefined; this.isPlayClick = true; this.setTimeMove = interval(this.speed).subscribe((d) => { this.playTime = Number(this.playTime) + 1 * 1000; this.playClick.emit(this.playTime); this.set_time_to_middle(this.playTime); }); } /** * Click on the pause */ onPauseClick() { this.isPlayClick = false; if (this.setTimeMove) { // this.setTimeMove = undefined; this.setTimeMove.unsubscribe(); this.playClick.emit(this.playTime); } } /** * Change video segment */ changeVideo() { const cells = [ { beginTime: new Date().getTime() - 1 * 1000 * 3600, endTime: new Date().getTime() + 2 * 1000 * 3600, style: { background: 'rgba(132, 244, 180, 0.498039)' } } ]; this.clearCanvas(); this.drawPalyBar(); this.init(this.startTimestamp, cells, true); } /** * Temporary unused * @param event MatDatepickerInputEvent(Date) */ selectedTime(event) { const timestamp = new Date(event.value.getTime()); this.set_time_to_middle(Number(timestamp)); } /** * Temporary unused * @param event MouseEvent */ onDragStart(e) { e.preventDefault(); return false; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: NgxVideoTimelineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.5", type: NgxVideoTimelineComponent, isStandalone: true, selector: "ngx-video-timeline", inputs: { canvasHeight: "canvasHeight", playTime: "playTime", speed: "speed", forWardValue: "forWardValue", startTimeThreshold: "startTimeThreshold", endTimeThreshold: "endTimeThreshold", borderColor: "borderColor", bgColor: "bgColor", bottomLineColor: "bottomLineColor", verticalBarColor: "verticalBarColor", playBarColor: "playBarColor", videoCells: "videoCells", isPlayClick: "isPlayClick" }, outputs: { playClick: "playClick", mouseUp: "mouseUp", mouseDown: "mouseDown", keyUp: "keyUp", keyDown: "keyDown" }, host: { listeners: { "window:resize": "onResize()", "window:keydown": "onKeyDown($event)", "window:keyup": "onKeyUp($event)" } }, viewQueries: [{ propertyName: "canvasExp", first: true, predicate: ["timeline"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `<canvas #timeline class="canvas" [ngStyle]="{cursor: 'pointer',border: '1px solid',borderColor: borderColor,'backgroundColor': bgColor}" (dragstart)="onDragStart($event)" (mouseup)="mouseupFunc($event)" (mousewheel)="mousewheelFunc($event)" (mousedown)="mousedownFunc($event)" (mousemove)="mousemoveFunc($event)" (mouseout)="mouseoutFunc()"></canvas> `, isInline: true, styles: [".canvas{width:100%;height:100%}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.5", ngImport: i0, type: NgxVideoTimelineComponent, decorators: [{ type: Component, args: [{ imports: [ NgStyle ], selector: 'ngx-video-timeline', template: `<canvas #timeline class="canvas" [ngStyle]="{cursor: 'pointer',border: '1px solid',borderColor: borderColor,'backgroundColor': bgColor}" (dragstart)="onDragStart($event)" (mouseup)="mouseupFunc($event)" (mousewheel)="mousewheelFunc($event)" (mousedown)="mousedownFunc($event)" (mousemove)="mousemoveFunc($event)" (mouseout)="mouseoutFunc()"></canvas> `, standalone: true, styles: [".canvas{width:100%;height:100%}\n"] }] }], ctorParameters: () => [], propDecorators: { canvasHeight: [{ type: Input }], playTime: [{ type: Input }], speed: [{ type: Input }], forWardValue: [{ type: Input }], startTimeThreshold: [{ type: Input }], endTimeThreshold: [{ type: Input }], borderColor: [{ type: Input }], bgColor: [{ type: Input }], bottomLineColor: [{ type: Input }], verticalBarColor: [{ type: Input }], playBarColor: [{ type: Input }], videoCells: [{ type: Input }], isPlayClick: [{ type: Input }], playClick: [{ type: Output }], mouseUp: [{ type: Output }], mouseDown: [{ type: Output }], keyUp: [{ type: Output }], keyDown: [{ type: Output }], canvasExp: [{ type: ViewChild, args: ['timeline', { static: true }] }], onResize: [{ type: HostListener, args: ['window:resize', []] }], onKeyDown: [{ type: HostListener, args: ['window:keydown', ['$event']] }], onKeyUp: [{ type: HostListener, args: ['window:keyup', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZWxpbmUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdGltZWxpbmUvc3JjL2xpYi90aW1lbGluZS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzFDLE9BQU8sRUFDTCxTQUFTLEVBRVQsWUFBWSxFQUNaLFlBQVksRUFDWixLQUFLLEVBR0wsTUFBTSxFQUNOLFNBQVMsRUFDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUM5QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7O0FBbUI5QyxNQUFNLE9BQU8seUJBQXlCO0lBR3BDLGlDQUFpQztJQUN4QixZQUFZLEdBQUcsRUFBRSxDQUFDO0lBRTNCLHFEQUFxRDtJQUNyRCxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7SUFFakMsc0JBQXNCO0lBQ2IsUUFBUSxDQUF5QjtJQUUxQyxxQ0FBcUM7SUFDNUIsS0FBSyxDQUFTO0lBRXZCLDJCQUEyQjtJQUNsQixZQUFZLENBQVM7SUFFOUIsOEJBQThCO0lBQ3JCLGtCQUFrQixDQUF5QjtJQUVwRCw0QkFBNEI7SUFDbkIsZ0JBQWdCLENBQXlCO0lBRWxELHdCQUF3QjtJQUV4Qix5QkFBeUI7SUFDaEIsV0FBVyxDQUFTO0lBRTdCLDhCQUE4QjtJQUNyQixPQUFPLENBQVM7SUFFekIsMEJBQTBCO0lBQ2pCLGVBQWUsQ0FBUztJQUVqQywyQkFBMkI7SUFDbEIsZ0JBQWdCLENBQVM7SUFFbEMsdUJBQXVCO0lBQ2QsWUFBWSxDQUFTO0lBRzlCLHNCQUFzQjtJQUV0QixjQUFjO0lBQ0wsVUFBVSxDQUF1QjtJQUUxQyw0QkFBNEI7SUFDbkIsV0FBVyxDQUFVO0lBRTlCLGtDQUFrQztJQUNmLFNBQVMs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