class TimeWindowPicker { constructor (canvasElement, rangeStart, rangeEnd) { this.canvasElement = canvasElement; this.rangeStart = rangeStart; this.rangeEnd = rangeEnd; this.leftSliderPos = rangeStart; this.rightSliderPos = rangeEnd; this.sliderPixelWidth = 10; this.sliderColor = '#4444ff'; this.sliderBorderColor = '#FFFFFF'; this.canvasBorderColor = '#FFFFFF'; this.leftDraggingNow = false; this.rightDraggingNow = false; this.rangeDraggingNow = false; this.rangeDragSize = undefined; this.rangeDragXStart = undefined; this.rangeDragInitialLeftValue = undefined; this.leftSliderXStart = 0; this.rightSliderXStart = 0; this.canvasElement.addEventListener('mousedown', this.mouseDownHandler); this.canvasElement.addEventListener('mouseup', this.mouseUpHandler); this.canvasElement.addEventListener('mousemove', this.mouseMoveHandler); this.canvasElement.addEventListener('mouseout', this.mouseOutHandler); //this.canvasElement.addEventListener('touchstart', this.mouseDownHandler); //this.canvasElement.addEventListener('touchEnd', this.mouseUpHandler); this.onMoveCallback = undefined; this.onSetCallback = undefined; this.updateTextCallback = undefined; this.minMillisBetweenMouseMoves = 16; this.lastMouseMoveTime = Date.now(); } draw () { const bgColor = '#000000'; const middleColor = '#555555'; var ctx = this.canvasElement.getContext('2d'); ctx.fillStyle = bgColor; ctx.fillRect(0, 0, this.canvasElement.width, this.canvasElement.height); ctx.strokeStyle = this.canvasBorderColor; ctx.strokeRect(0, 0, this.canvasElement.width, this.canvasElement.height); const fullRange = this.rangeEnd - this.rangeStart; const pixelTimeRatio = this.canvasElement.width / fullRange; // pixels per second // draw left slider // determine centerpoint of slider let leftSliderCenter = parseInt((this.leftSliderPos - this.rangeStart) * pixelTimeRatio); // theoretically we will only have to check this for the left end if (leftSliderCenter < this.sliderPixelWidth / 2) {leftSliderCenter = this.sliderPixelWidth / 2;} ctx.fillStyle = this.sliderColor; ctx.fillRect(leftSliderCenter - this.sliderPixelWidth / 2, 0, this.sliderPixelWidth, this.canvasElement.height); ctx.strokeStyle = this.sliderBorderColor; ctx.strokeRect(leftSliderCenter - this.sliderPixelWidth / 2, 0, this.sliderPixelWidth, this.canvasElement.height); this.leftSliderXStart = leftSliderCenter - this.sliderPixelWidth / 2; // now the right let rightSliderCenter = parseInt((this.rightSliderPos - this.rangeStart) * pixelTimeRatio); if (rightSliderCenter > this.canvasElement.width - (this.sliderPixelWidth / 2)) { rightSliderCenter = this.canvasElement.width - (this.sliderPixelWidth / 2);} ctx.fillStyle = this.sliderColor; ctx.fillRect(rightSliderCenter - this.sliderPixelWidth / 2, 0, this.sliderPixelWidth, this.canvasElement.height); ctx.strokeStyle = this.sliderBorderColor; ctx.strokeRect(rightSliderCenter - this.sliderPixelWidth / 2, 0, this.sliderPixelWidth, this.canvasElement.height); this.rightSliderXStart = rightSliderCenter - this.sliderPixelWidth / 2; // draw the middle range in a different color ctx.fillStyle = middleColor; ctx.fillRect(leftSliderCenter + this.sliderPixelWidth / 2, 0, rightSliderCenter - leftSliderCenter - this.sliderPixelWidth, this.canvasElement.height); if (this.updateTextCallback) { this.updateTextCallback(); } } adjustVisibleRange (leftSliderValue, rightSliderValue, callbackDisable=false) { //console.log('twp.adjustVisibleRange called, callbackDisable: ' + callbackDisable) if (leftSliderValue) { this.leftSliderPos = leftSliderValue; } if (rightSliderValue) { this.rightSliderPos = rightSliderValue; } if (this.leftSliderPos < this.rangeStart) { this.leftSliderPos = this.rangeStart; } if (this.rightSliderPos > this.rangeEnd) { this.rightSliderPos = this.rangeEnd; } if (this.leftSliderPos > this.rightSliderPos) { this.leftSliderPos = this.rightSliderPos - ((this.rangeEnd - this.rangeStart) / 25); } this.draw(); if (this.onMoveCallback && !callbackDisable) { //console.log(callbackDisable); if (this.leftDraggingNow || this.rightDraggingNow) { this.onMoveCallback(this.leftSliderPos, this.rightSliderPos); } } if (this.onSetCallback && !callbackDisable) { if (!this.leftDraggingNow && !this.rightDraggingNow) { this.onSetCallback(this.leftSliderPos, this.rightSliderPos); } } //console.log('TWP left: ' + twp.leftSliderPos + ' right: ' + twp.rightSliderPos); } adjustFullRange(start, end) { //console.log('adjustFullRange called with start ' + start + ' end ' + end + ' diff ' + (end - start)); if (this.leftSliderPos < start) { this.leftSliderPos = start; } if (this.rightSliderPos > end) { this.rightSliderPos = end; } this.rangeStart = start; this.rangeEnd = end; //console.log(this.rangeStart + ' ' + this.rangeEnd); this.draw(); } mouseDownHandler (event) { let mouseX = getMousePos(twp.canvasElement, event)['x']; // are we within the left or right slider pos? if (mouseX >= twp.leftSliderXStart && mouseX <= twp.leftSliderXStart + twp.sliderPixelWidth) { twp.leftDraggingNow = true; twp.rightDraggingNow = false; twp.rangeDraggingNow = false; //console.log('mousedown on left slider') } else if (mouseX >= twp.rightSliderXStart && mouseX <= twp.rightSliderXStart + twp.sliderPixelWidth) { twp.leftDraggingNow = false; twp.rightDraggingNow = true; twp.rangeDraggingNow = false; //console.log('mousedown on right slider') } else if (mouseX > twp.leftSliderXStart + twp.sliderPixelWidth && mouseX < twp.rightSliderXStart - twp.sliderPixelWidth ) { //console.log('fart'); twp.rangeDraggingNow = true; twp.leftDraggingNow = false; twp.rightDraggingNow = false; twp.rangeDragSize = twp.rightSliderPos - twp.leftSliderPos; twp.rangeDragXStart = mouseX; twp.rangeDragInitialLeftValue = twp.leftSliderPos; } else { twp.leftDraggingNow = false; twp.rightDraggingNow = false; twp.rangeDraggingNow = false; } } mouseMoveHandler (event) { let now = Date.now(); if (now - twp.lastMouseMoveTime < twp.minMillisBetweenMouseMoves) { return; } let mouseX = getMousePos(twp.canvasElement, event)['x']; const fullRange = twp.rangeEnd - twp.rangeStart; const pixelTimeRatio = fullRange / twp.canvasElement.width; if (twp.leftDraggingNow) { let newLeftXStart = parseInt(mouseX * pixelTimeRatio + twp.rangeStart); twp.adjustVisibleRange(newLeftXStart); } else if (twp.rightDraggingNow) { let newRightXStart = parseInt(mouseX * pixelTimeRatio + twp.rangeStart); twp.adjustVisibleRange(undefined, newRightXStart); } else if (twp.rangeDraggingNow) { let xDiff = mouseX - twp.rangeDragXStart; let valueChange = parseInt(xDiff * pixelTimeRatio); // converting pixels to seconds let newLeftValue = twp.rangeDragInitialLeftValue + valueChange; let newRightValue = newLeftValue + twp.rangeDragSize; twp.adjustVisibleRange(newLeftValue, newRightValue); } twp.lastMouseMoveTime = now; } mouseUpHandler (event) { let mouseX = getMousePos(twp.canvasElement, event)['x']; const fullRange = twp.rangeEnd - twp.rangeStart; const pixelTimeRatio = fullRange / twp.canvasElement.width; // seconds per pixel if (twp.leftDraggingNow) { let newLeftXStart = parseInt(mouseX * pixelTimeRatio + twp.rangeStart); twp.leftDraggingNow = false; twp.rightDraggingNow = false; twp.rangeDraggingNow = false; twp.adjustVisibleRange(newLeftXStart); } else if (twp.rightDraggingNow) { let newRightXStart = parseInt(mouseX * pixelTimeRatio + twp.rangeStart); twp.leftDraggingNow = false; twp.rightDraggingNow = false; twp.rangeDraggingNow = false; twp.adjustVisibleRange(undefined, newRightXStart); } else if (twp.rangeDraggingNow) { let xDiff = this.rangeDragXStart - mouseX; let valueChange = parseInt(xDiff * pixelTimeRatio); // converting pixels to seconds let newLeftValue = this.rangeDragInitialLeftValue + valueChange; let newRightValue = newLeftValue + twp.rangeDragSize; twp.leftDraggingNow = false; twp.rightDraggingNow = false; twp.rangeDraggingNow = false; twp.adjustVisibleRange(newLeftValue, newRightValue); } } mouseOutHandler (event) { twp.leftDraggingNow = false; twp.rightDraggingNow = false; twp.rangeDraggingNow = false; } } function getMousePos (canvas, evt) { var rect = canvas.getBoundingClientRect(); return { x: evt.clientX - rect.left, y: evt.clientY - rect.top } }