diff --git a/curveEditor.js b/curveEditor.js index 2e589a9..b84c9c1 100644 --- a/curveEditor.js +++ b/curveEditor.js @@ -1,10 +1,14 @@ export class CurveEditor { - constructor(canvas, timelineLength = 10, _slider) { + constructor(canvas, timelineLength = 6, _slider) { this.canvas = canvas; + canvas.width = canvas.offsetWidth; + canvas.height = canvas.offsetHeight; this.ctx = canvas.getContext('2d'); this.timelineLength = timelineLength; this.scale = 1; + this.scaleX = 1; + this.scaleY = 1; this.offset = { x: 0, y: 0 }; this.pixelsPerSecond = 48; @@ -133,15 +137,17 @@ export class CurveEditor { addChannel(motorID) { this.setCurves([ { - startPoint: { x: this.valueToX(0), y: this.valueToY(0) }, - startPointHandle: { x: this.valueToX(this.timelineLength * 0.25), y: this.valueToY(0) }, - endPointHandle: { x: this.valueToX(this.timelineLength * 0.75), y: this.valueToY(0) }, - endPoint: { x: this.valueToX(this.timelineLength), y: this.valueToY(0) } + startPoint: { x: 0, y: this.canvas.height / 2 }, + startPointHandle: { x: this.timelineLength * this.pixelsPerSecond * 0.25, y: this.canvas.height / 2 }, + endPointHandle: { x: this.timelineLength * this.pixelsPerSecond * 0.75, y: this.canvas.height / 2 }, + endPoint: { x: this.timelineLength * this.pixelsPerSecond, y: this.canvas.height / 2 } } ]); + console.log("TL LENGTH: " + this.timelineLength); this.curveSets[motorID] = this.curves; } + setLength(endTime) { this.timelineLength = endTime / this.pixelsPerSecond; console.log("new endtime: " + endTime); @@ -178,12 +184,12 @@ export class CurveEditor { valueToY(v) { - return (this.canvas.height / 2 - v * (this.canvas.height / 2)) * this.scale + this.offset.y; + return (this.canvas.height / 2 - v * (this.canvas.height / 2)) * this.scaleY + this.offset.y; } // Maps pixel value of y axis to -1 to 1 normalised value yToValue(y) { - return ((this.canvas.height / 2 - (y - this.offset.y) / this.scale) / (this.canvas.height / 2)); + return ((this.canvas.height / 2 - (y - this.offset.y) / this.scaleY) / (this.canvas.height / 2)); } // Maps normalised -1 to 1 value to motor range (0, 4095) @@ -206,25 +212,27 @@ export class CurveEditor { } - valueToX(t) { - return t * this.pixelsPerSecond * this.scale + this.offset.x; + valueToX(value) { + return value * this.pixelsPerSecond * this.scaleX + this.offset.x; } + xToValue(x) { - return (x - this.offset.x) / (this.pixelsPerSecond * this.scale); + return (x - this.offset.x) / (this.pixelsPerSecond * this.scaleX); } + transform(p) { return { - x: p.x * this.scale + this.offset.x, - y: p.y * this.scale + this.offset.y + x: p.x * this.scaleX + this.offset.x, + y: p.y * this.scaleY + this.offset.y }; } inverseTransform(p) { return { - x: (p.x - this.offset.x) / this.scale, - y: (p.y - this.offset.y) / this.scale + x: (p.x - this.offset.x) / this.scaleX, + y: (p.y - this.offset.y) / this.scaleY }; } @@ -389,14 +397,6 @@ export class CurveEditor { } } - - - - - - - - // Draw control points (optional) if (showControlPoints) { // Draw handles @@ -448,7 +448,7 @@ export class CurveEditor { ctx.lineWidth = 1.5; ctx.font = "12px sans-serif"; ctx.fillStyle = "#666"; - ctx.fillText(`${time}s`, x + 2, 12); + ctx.fillText(`${time}s`, x + 0 / this.scaleX, 12 / this.scaleY); } else if (s % 2 === 0) { ctx.strokeStyle = "#bbb"; ctx.lineWidth = 1; @@ -475,7 +475,8 @@ export class CurveEditor { ctx.font = "12px sans-serif"; ctx.fillStyle = "#666"; - ctx.fillText(v.toFixed(2), 4, y - 4); + ctx.fillText(v.toFixed(2), 4 / this.scaleX + 10, y - 6 / this.scaleY); + } } @@ -572,6 +573,7 @@ export class CurveEditor { const mouse = this.inverseTransform({ x: e.offsetX, y: e.offsetY }); if (e.button === 1) { + e.preventDefault(); // Prevent page panning this.isPanning = true; this.panStart = { x: e.offsetX, y: e.offsetY }; return; @@ -620,31 +622,31 @@ export class CurveEditor { this.isPanning = false; }); - this.canvas.addEventListener('wheel', e => { - e.preventDefault(); - const mouse = { x: e.offsetX, y: e.offsetY }; - const zoomFactor = e.deltaY < 0 ? 1.1 : 0.9; + this.canvas.addEventListener('wheel', e => { + e.preventDefault(); + const mouse = { x: e.offsetX, y: e.offsetY }; + const zoomFactor = e.deltaY < 0 ? 1.1 : 0.9; - const before = this.inverseTransform(mouse); + const before = this.inverseTransform(mouse); - // Apply zoom based on modifier keys - if (e.ctrlKey && !e.altKey) { - this.scaleX *= zoomFactor; - } else if (e.altKey && !e.ctrlKey) { - this.scaleY *= zoomFactor; - } else { - // Default: uniform zoom - this.scaleX *= zoomFactor; - this.scaleY *= zoomFactor; - } + // Apply zoom based on modifier keys + if (e.ctrlKey && !e.altKey) { + this.scaleX *= zoomFactor; + } else if (e.altKey && !e.ctrlKey) { + this.scaleY *= zoomFactor; + } else { + // Default: uniform zoom + this.scaleX *= zoomFactor; + this.scaleY *= zoomFactor; + } - const after = this.inverseTransform(mouse); + const after = this.inverseTransform(mouse); - this.offset.x += (after.x - before.x) * this.scaleX; - this.offset.y += (after.y - before.y) * this.scaleY; + this.offset.x += (after.x - before.x) * this.scaleX; + this.offset.y += (after.y - before.y) * this.scaleY; - this.draw(); -}); + this.draw(); + }); this.canvas.addEventListener('dblclick', e => { diff --git a/index.html b/index.html index 84724f5..4417a95 100644 --- a/index.html +++ b/index.html @@ -155,7 +155,7 @@