wacomink
Version:
255 lines (187 loc) • 8.11 kB
JavaScript
var WILL = {
MIN_SCALE_FACTOR: 1,
MAX_SCALE_FACTOR: 3,
backgroundColor: Module.Color.WHITE,
color: Module.Color.from(204, 204, 204),
strokes: new Array(),
init: function(width, height) {
this.VIEW_AREA = Module.RectTools.create(0, 0, width, height);
this.initInkEngine(width, height);
this.initEvents();
},
initInkEngine: function(width, height) {
this.canvas = new Module.InkCanvas(document.getElementById("canvas"), width, height);
this.strokesLayer = this.canvas.createLayer();
this.strokesAndCurrentStrokeLayer = this.canvas.createLayer();
this.brush = new Module.DirectBrush();
this.pathBuilder = new Module.SpeedPathBuilder();
this.pathBuilder.setNormalizationConfig(182, 3547);
this.pathBuilder.setPropertyConfig(Module.PropertyName.Width, 2.05, 34.53, 0.72, NaN, Module.PropertyFunction.Power, 1.19, false);
this.smoothener = new Module.MultiChannelSmoothener(this.pathBuilder.stride);
this.strokeRenderer = new Module.StrokeRenderer(this.canvas);
this.strokeRenderer.configure({brush: this.brush, color: this.color});
this.transform = Module.MatTools.create();
this.clear();
},
initEvents: function() {
var self = this;
$(Module.canvas).on("mousedown", function(e) {self.beginStroke(e);});
$(Module.canvas).on("mousemove", function(e) {self.moveStroke(e);});
$(document).on("mouseup", function(e) {self.endStroke(e);});
var zoomNode = document.getElementById("zoom");
var panNode = document.getElementById("pan");
var lastPoint;
document.addEventListener("wheel", function(e) {
WILL.zoom(e);
zoomNode.innerHTML = Math.floor(WILL.transform.a * 100);
panNode.innerHTML = "x: " + Math.floor(WILL.transform.tx) + ", y: " + Math.floor(WILL.transform.ty);
});
Module.canvas.addEventListener("mousedown", function(e) {
if (e.button == 2) lastPoint = {x: e.clientX, y: e.clientY};
});
Module.canvas.addEventListener("mousemove", function(e) {
if (e.button != 2) return;
var delta = {x: e.clientX - lastPoint.x, y: e.clientY - lastPoint.y};
lastPoint = {x: e.clientX, y: e.clientY};
WILL.pan(delta);
panNode.innerHTML = "x: " + Math.floor(WILL.transform.tx) + ", y: " + Math.floor(WILL.transform.ty);
});
document.getElementById("reset").addEventListener("click", function(e) {
zoomNode.innerHTML = "100";
panNode.innerHTML = "x: 0, y: 0";
WILL.resetTransforms();
});
},
getMousePos: function(e) {
var pos = {x: e.clientX, y: e.clientY};
var transform = Module.MatTools.invert(this.transform);
var pt = Module.MatTools.transformPoint(pos, transform);
return pt;
},
beginStroke: function(e) {
if (["mousedown", "mouseup"].contains(e.type) && e.button != 0) return;
this.inputPhase = Module.InputPhase.Begin;
this.buildPath(this.getMousePos(e));
this.drawPath();
},
moveStroke: function(e) {
if (!this.inputPhase) return;
this.inputPhase = Module.InputPhase.Move;
this.pointerPos = this.getMousePos(e);
if (WILL.frameID != WILL.canvas.frameID) {
var self = this;
WILL.frameID = WILL.canvas.requestAnimationFrame(function() {
if (self.inputPhase && self.inputPhase == Module.InputPhase.Move) {
self.buildPath(self.pointerPos);
self.drawPath();
}
}, true);
}
},
endStroke: function(e) {
if (!this.inputPhase) return;
this.inputPhase = Module.InputPhase.End;
this.buildPath(this.getMousePos(e));
this.drawPath();
delete this.inputPhase;
},
buildPath: function(pos) {
if (this.inputPhase == Module.InputPhase.Begin)
this.smoothener.reset();
var pathPart = this.pathBuilder.addPoint(this.inputPhase, pos, Date.now()/1000);
var smoothedPathPart = this.smoothener.smooth(pathPart, this.inputPhase == Module.InputPhase.End);
var pathContext = this.pathBuilder.addPathPart(smoothedPathPart);
this.pathPart = pathContext.getPathPart();
this.path = pathContext.getPath();
if (this.inputPhase == Module.InputPhase.Move) {
var preliminaryPathPart = this.pathBuilder.createPreliminaryPath();
var preliminarySmoothedPathPart = this.smoothener.smooth(preliminaryPathPart, true);
this.preliminaryPathPart = this.pathBuilder.finishPreliminaryPath(preliminarySmoothedPathPart);
}
},
drawPath: function() {
switch (this.inputPhase) {
case Module.InputPhase.Begin:
if (this.pathPart.points.length > 0) {
this.strokeRenderer.draw(this.pathPart, false);
this.refresh(this.strokeRenderer.updatedArea);
}
break;
case Module.InputPhase.Move:
this.strokeRenderer.draw(this.pathPart, false);
this.refresh(this.strokeRenderer.updatedArea);
break;
case Module.InputPhase.End:
var stroke = this.strokeRenderer.toStroke(this.path);
this.strokes.push(stroke);
this.strokeRenderer.draw(this.pathPart, true);
this.refresh(this.strokeRenderer.updatedArea);
this.strokeRenderer.blendStroke(this.strokesLayer);
break;
default:
throw new Error("Invalid input phase:", this.inputPhase);
}
},
refresh: function(dirtyArea) {
if (!dirtyArea) return;
var strokesLayer = this.strokesLayer;
var transformArea = Module.MatTools.transformRect(dirtyArea, this.transform);
if (this.inputPhase) {
strokesLayer = this.strokesAndCurrentStrokeLayer;
this.strokesAndCurrentStrokeLayer.blend(this.strokesLayer, {mode: Module.BlendMode.NONE, rect: dirtyArea});
if (this.inputPhase == Module.InputPhase.Move)
this.strokeRenderer.drawPreliminary(this.preliminaryPathPart);
this.strokeRenderer.blendUpdatedArea(this.strokesAndCurrentStrokeLayer);
}
this.canvas.clear(transformArea, this.backgroundColor);
this.canvas.blend(strokesLayer, {sourceRect: dirtyArea, destinationRect: transformArea});
},
clear: function() {
this.strokes = new Array();
this.strokesLayer.clear();
this.refresh(WILL.VIEW_AREA);
},
zoom: function(e) {
var pos = {x: e.clientX, y: e.clientY};
var scale = (e.deltaY > 0)?0.97:1.03;
var transform = Module.MatTools.makeScaleAtPoint(scale, pos);
transform = Module.MatTools.multiply(transform, this.transform);
if ((this.transform.a == WILL.MIN_SCALE_FACTOR && transform.a < WILL.MIN_SCALE_FACTOR) || (this.transform.a == WILL.MAX_SCALE_FACTOR && transform.a > WILL.MAX_SCALE_FACTOR))
return;
if (transform.a < WILL.MIN_SCALE_FACTOR) {
transform.a = WILL.MIN_SCALE_FACTOR;
transform.d = WILL.MIN_SCALE_FACTOR;
}
else if (transform.a > WILL.MAX_SCALE_FACTOR) {
transform.a = WILL.MAX_SCALE_FACTOR;
transform.d = WILL.MAX_SCALE_FACTOR;
}
var transformArea = Module.MatTools.transformRect(WILL.VIEW_AREA, transform);
if (transform.tx > 0) transform.tx = 0;
if (transform.ty > 0) transform.ty = 0;
if (transform.tx < WILL.VIEW_AREA.width - transformArea.width) transform.tx = WILL.VIEW_AREA.width - transformArea.width;
if (transform.ty < WILL.VIEW_AREA.height - transformArea.height) transform.ty = WILL.VIEW_AREA.height - transformArea.height;
this.transform = transform;
this.canvas.clear();
this.refresh(WILL.VIEW_AREA);
},
pan: function(delta) {
var transformArea = Module.MatTools.transformRect(WILL.VIEW_AREA, this.transform);
var transform = Module.MatTools.makeTranslate(delta);
transform = Module.MatTools.multiply(transform, this.transform);
if (transform.tx > 0) transform.tx = 0;
if (transform.ty > 0) transform.ty = 0;
if (transform.tx < WILL.VIEW_AREA.width - transformArea.width) transform.tx = WILL.VIEW_AREA.width - transformArea.width;
if (transform.ty < WILL.VIEW_AREA.height - transformArea.height) transform.ty = WILL.VIEW_AREA.height - transformArea.height;
this.transform = transform;
this.canvas.clear();
this.refresh(WILL.VIEW_AREA);
},
resetTransforms: function() {
this.transform = Module.MatTools.create();
this.refresh(WILL.VIEW_AREA);
}
};
Module.addPostScript(function() {
WILL.init(1600, 600);
});