better zooming

This commit is contained in:
BroodjeAap 2023-01-20 10:03:40 +00:00
parent 4bd0cc0900
commit a18017124a
2 changed files with 107 additions and 41 deletions

View file

@ -433,6 +433,7 @@ var Point = /** @class */ (function () {
var MouseState = /** @class */ (function () { var MouseState = /** @class */ (function () {
function MouseState() { function MouseState() {
this.canvas = new Point(); this.canvas = new Point();
this.absCanvas = new Point();
this.world = new Point(); this.world = new Point();
this.offset = new Point(); this.offset = new Point();
this.delta = new Point(); this.delta = new Point();
@ -457,9 +458,9 @@ var Diagrams = /** @class */ (function () {
this.nodeDragging = null; this.nodeDragging = null;
this.nodeHover = null; this.nodeHover = null;
this.newConnection = null; this.newConnection = null;
this.scaleLevel = 0; this.scale = 4;
this.scaleMax = 3; this.scales = 10;
this.scaleMin = -1; this.scalingFactor = 1;
this.editNodeCallback = function () { }; this.editNodeCallback = function () { };
this.deleteNodeCallback = function () { }; this.deleteNodeCallback = function () { };
this.canvas = document.getElementById(canvasId); this.canvas = document.getElementById(canvasId);
@ -481,11 +482,12 @@ var Diagrams = /** @class */ (function () {
window.onresize = diagramOnResize; window.onresize = diagramOnResize;
tick(); tick();
} }
Object.defineProperty(Diagrams.prototype, "scale", { Object.defineProperty(Diagrams.prototype, "inverseScalingFactor", {
get: function () { return 1 - (1 / this.scaleMax) * this.scaleLevel; }, get: function () { return 1 / this.scalingFactor; },
enumerable: true, enumerable: true,
configurable: true configurable: true
}); });
;
Diagrams.prototype.tick = function () { Diagrams.prototype.tick = function () {
var e_2, _a, e_3, _b, e_4, _c, e_5, _d; var e_2, _a, e_3, _b, e_4, _c, e_5, _d;
this.drawBackground(); this.drawBackground();
@ -556,11 +558,13 @@ var Diagrams = /** @class */ (function () {
}; };
Diagrams.prototype.onmousemove = function (ev) { Diagrams.prototype.onmousemove = function (ev) {
var canvasRect = this.canvas.getBoundingClientRect(); var canvasRect = this.canvas.getBoundingClientRect();
var scale = 1 / this.scale; var scale = this.scalingFactor;
this.mouseState.canvas.x = (ev.x - canvasRect.left) * scale; this.mouseState.absCanvas.x = ev.x - canvasRect.left;
this.mouseState.canvas.y = (ev.y - canvasRect.top) * scale; this.mouseState.absCanvas.y = ev.y - canvasRect.top;
this.mouseState.delta.x = ev.movementX * scale; this.mouseState.canvas.x = this.mouseState.absCanvas.x / scale;
this.mouseState.delta.y = ev.movementY * scale; this.mouseState.canvas.y = this.mouseState.absCanvas.y / scale;
this.mouseState.delta.x = ev.movementX / scale;
this.mouseState.delta.y = ev.movementY / scale;
if (this.mouseState.panning) { if (this.mouseState.panning) {
this.mouseState.offset.x += this.mouseState.delta.x; this.mouseState.offset.x += this.mouseState.delta.x;
this.mouseState.offset.y += this.mouseState.delta.y; this.mouseState.offset.y += this.mouseState.delta.y;
@ -607,25 +611,50 @@ var Diagrams = /** @class */ (function () {
ev.preventDefault(); ev.preventDefault();
var sign = Math.sign(ev.deltaY); var sign = Math.sign(ev.deltaY);
var zoomOut = sign > 0; var zoomOut = sign > 0;
if (zoomOut && this.scaleLevel >= this.scaleMax - 1) { if (zoomOut && this.scale >= this.scales - 1) {
return; return;
} }
var zoomIn = !zoomOut; var zoomIn = !zoomOut;
if (zoomIn && this.scaleLevel <= this.scaleMin) { if (zoomIn && this.scale <= 0) {
return; return;
} }
// undo previous scaling var oldWorldPos = new Point(this.mouseState.world.x, this.mouseState.world.y);
var currentScale = this.scale; var oldCanvasPos = new Point(this.mouseState.canvas.x, this.mouseState.canvas.y);
var unscale = 1 / currentScale; console.log(oldWorldPos);
this.ctx.scale(unscale, unscale); this.scale += sign;
this.scaleLevel += sign; var zoomOutFactor = 0.9;
var zoomInFactor = 1 / zoomOutFactor;
var zoomFactor = zoomIn ? zoomInFactor : zoomOutFactor;
this.ctx.scale(zoomFactor, zoomFactor);
this.scalingFactor *= zoomFactor;
this.mouseState.canvas.x *= zoomFactor;
this.mouseState.canvas.y *= zoomFactor;
//this.mouseState.canvas.x = this.mouseState.absCanvas.x * this.scalingFactor;
//this.mouseState.canvas.y = this.mouseState.absCanvas.y * this.scalingFactor;
var mouseDelta = new Point(oldCanvasPos.x - this.mouseState.canvas.x, oldCanvasPos.y - this.mouseState.canvas.y);
this.mouseState.offset.x += mouseDelta.x;
this.mouseState.offset.y += mouseDelta.y;
console.log(this.mouseState.world);
/*
// scale with new value // scale with new value
var scale = this.scale; let scale = this.scale;
this.ctx.scale(scale, scale); this.ctx.scale(scale, scale);
// recalculate mouse 'world' position, so we can realign it after zooming
this.mouseState.canvas.x = this.mouseState.absCanvas.x / scale;
this.mouseState.canvas.y = this.mouseState.absCanvas.y / scale;
this.mouseState.world.x = (this.mouseState.canvas.x - this.mouseState.offset.x) * scale;
this.mouseState.world.y = (this.mouseState.canvas.y - this.mouseState.offset.y) * scale;
this.mouseState.offset.x -= (oldWorld.x - this.mouseState.world.x);
this.mouseState.offset.y -= (oldWorld.y - this.mouseState.world.y);
console.log(this.mouseState.offset);
*/
}; };
Diagrams.prototype.drawBackground = function () { Diagrams.prototype.drawBackground = function () {
this.ctx.fillStyle = "#D8D8D8"; this.ctx.fillStyle = "#D8D8D8";
var scale = 1 / this.scale; var scale = this.inverseScalingFactor;
this.ctx.fillRect(0, 0, this.canvas.width * scale, this.canvas.height * scale); this.ctx.fillRect(0, 0, this.canvas.width * scale, this.canvas.height * scale);
this.ctx.strokeStyle = "#888"; this.ctx.strokeStyle = "#888";
this.ctx.lineWidth = 5 * scale; this.ctx.lineWidth = 5 * scale;

View file

@ -505,6 +505,7 @@ class Point {
} }
class MouseState { class MouseState {
canvas: Point = new Point(); canvas: Point = new Point();
absCanvas: Point = new Point();
world: Point = new Point(); world: Point = new Point();
offset: Point = new Point(); offset: Point = new Point();
delta: Point = new Point(); delta: Point = new Point();
@ -535,10 +536,10 @@ class Diagrams {
newConnection: NewConnection | null = null; newConnection: NewConnection | null = null;
scaleLevel: number = 0; scale: number = 4;
scaleMax: number = 3; scales: number = 10;
scaleMin: number = -1; scalingFactor: number = 1;
get scale(): number {return 1 - (1 / this.scaleMax) * this.scaleLevel;} get inverseScalingFactor(): number {return 1 / this.scalingFactor};
editNodeCallback: (node: DiagramNode) => void = function (){}; editNodeCallback: (node: DiagramNode) => void = function (){};
deleteNodeCallback: (node: DiagramNode) => void = function (){}; deleteNodeCallback: (node: DiagramNode) => void = function (){};
@ -599,17 +600,19 @@ class Diagrams {
onmousemove(ev: MouseEvent){ onmousemove(ev: MouseEvent){
let canvasRect = this.canvas.getBoundingClientRect(); let canvasRect = this.canvas.getBoundingClientRect();
let scale = 1 / this.scale; let scale = this.scalingFactor;
this.mouseState.canvas.x = (ev.x - canvasRect.left) * scale; this.mouseState.absCanvas.x = ev.x - canvasRect.left
this.mouseState.canvas.y = (ev.y - canvasRect.top) * scale; this.mouseState.absCanvas.y = ev.y - canvasRect.top;
this.mouseState.delta.x = ev.movementX * scale; this.mouseState.canvas.x = this.mouseState.absCanvas.x / scale;
this.mouseState.delta.y = ev.movementY * scale; this.mouseState.canvas.y = this.mouseState.absCanvas.y / scale;
this.mouseState.delta.x = ev.movementX / scale;
this.mouseState.delta.y = ev.movementY / scale;
if (this.mouseState.panning){ if (this.mouseState.panning){
this.mouseState.offset.x += this.mouseState.delta.x; this.mouseState.offset.x += this.mouseState.delta.x;
this.mouseState.offset.y += this.mouseState.delta.y; this.mouseState.offset.y += this.mouseState.delta.y;
} }
this.mouseState.world.x = this.mouseState.canvas.x - this.mouseState.offset.x; this.mouseState.world.x = this.mouseState.canvas.x - this.mouseState.offset.x;
this.mouseState.world.y = this.mouseState.canvas.y - this.mouseState.offset.y; this.mouseState.world.y = this.mouseState.canvas.y - this.mouseState.offset.y;
} }
@ -644,29 +647,63 @@ class Diagrams {
ev.preventDefault(); ev.preventDefault();
let sign = Math.sign(ev.deltaY); let sign = Math.sign(ev.deltaY);
let zoomOut = sign > 0; let zoomOut = sign > 0;
if (zoomOut && this.scaleLevel >= this.scaleMax-1) { if (zoomOut && this.scale >= this.scales-1) {
return; return;
} }
let zoomIn = !zoomOut let zoomIn = !zoomOut
if (zoomIn && this.scaleLevel <= this.scaleMin) { if (zoomIn && this.scale <= 0) {
return; return;
} }
// undo previous scaling let oldWorldPos = new Point(this.mouseState.world.x, this.mouseState.world.y)
let currentScale = this.scale; let oldCanvasPos = new Point(this.mouseState.canvas.x, this.mouseState.canvas.y)
let unscale = 1 / currentScale; console.log(oldWorldPos);
this.ctx.scale(unscale, unscale);
this.scale += sign;
this.scaleLevel += sign; let zoomOutFactor = 0.9;
let zoomInFactor = 1 / zoomOutFactor
let zoomFactor = zoomIn ? zoomInFactor : zoomOutFactor;
this.ctx.scale(zoomFactor, zoomFactor);
this.scalingFactor *= zoomFactor;
this.mouseState.canvas.x *= zoomFactor;
this.mouseState.canvas.y *= zoomFactor;
//this.mouseState.canvas.x = this.mouseState.absCanvas.x * this.scalingFactor;
//this.mouseState.canvas.y = this.mouseState.absCanvas.y * this.scalingFactor;
let mouseDelta = new Point(
oldCanvasPos.x - this.mouseState.canvas.x,
oldCanvasPos.y - this.mouseState.canvas.y
)
this.mouseState.offset.x += mouseDelta.x;
this.mouseState.offset.y += mouseDelta.y;
console.log(this.mouseState.world);
/*
// scale with new value // scale with new value
let scale = this.scale; let scale = this.scale;
this.ctx.scale(scale, scale); this.ctx.scale(scale, scale);
// recalculate mouse 'world' position, so we can realign it after zooming
this.mouseState.canvas.x = this.mouseState.absCanvas.x / scale;
this.mouseState.canvas.y = this.mouseState.absCanvas.y / scale;
this.mouseState.world.x = (this.mouseState.canvas.x - this.mouseState.offset.x) * scale;
this.mouseState.world.y = (this.mouseState.canvas.y - this.mouseState.offset.y) * scale;
this.mouseState.offset.x -= (oldWorld.x - this.mouseState.world.x);
this.mouseState.offset.y -= (oldWorld.y - this.mouseState.world.y);
console.log(this.mouseState.offset);
*/
} }
drawBackground(){ drawBackground(){
this.ctx.fillStyle = "#D8D8D8"; this.ctx.fillStyle = "#D8D8D8";
let scale = 1 / this.scale; let scale = this.inverseScalingFactor;
this.ctx.fillRect(0,0,this.canvas.width * scale, this.canvas.height * scale); this.ctx.fillRect(0,0,this.canvas.width * scale, this.canvas.height * scale);
this.ctx.strokeStyle = "#888"; this.ctx.strokeStyle = "#888";
this.ctx.lineWidth = 5 * scale; this.ctx.lineWidth = 5 * scale;