better zooming
This commit is contained in:
parent
4bd0cc0900
commit
a18017124a
2 changed files with 107 additions and 41 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue