mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Add interpolation when using the pen tool quickly
This commit is contained in:
parent
946444a16b
commit
9758aa62d9
@ -55,4 +55,41 @@
|
|||||||
ns.BaseTool.prototype.removeCanvasOverlays = function () {
|
ns.BaseTool.prototype.removeCanvasOverlays = function () {
|
||||||
$(".canvas-overlay").remove();
|
$(".canvas-overlay").remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bresenham line algorihtm: Get an array of pixels from
|
||||||
|
* start and end coordinates.
|
||||||
|
*
|
||||||
|
* http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
|
||||||
|
* http://stackoverflow.com/questions/4672279/bresenham-algorithm-in-javascript
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ns.BaseTool.prototype.getLinePixels_ = function(x0, x1, y0, y1) {
|
||||||
|
|
||||||
|
var pixels = [];
|
||||||
|
var dx = Math.abs(x1-x0);
|
||||||
|
var dy = Math.abs(y1-y0);
|
||||||
|
var sx = (x0 < x1) ? 1 : -1;
|
||||||
|
var sy = (y0 < y1) ? 1 : -1;
|
||||||
|
var err = dx-dy;
|
||||||
|
|
||||||
|
while(true){
|
||||||
|
|
||||||
|
// Do what you need to for this
|
||||||
|
pixels.push({"col": x0, "row": y0});
|
||||||
|
|
||||||
|
if ((x0==x1) && (y0==y1)) break;
|
||||||
|
var e2 = 2*err;
|
||||||
|
if (e2>-dy){
|
||||||
|
err -= dy;
|
||||||
|
x0 += sx;
|
||||||
|
}
|
||||||
|
if (e2 < dx) {
|
||||||
|
err += dx;
|
||||||
|
y0 += sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pixels;
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
this.toolId = "tool-pen"
|
this.toolId = "tool-pen"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.previousCol = null;
|
||||||
|
this.previousRow = null;
|
||||||
|
|
||||||
pskl.utils.inherit(ns.SimplePen, ns.BaseTool);
|
pskl.utils.inherit(ns.SimplePen, ns.BaseTool);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,6 +20,9 @@
|
|||||||
*/
|
*/
|
||||||
ns.SimplePen.prototype.applyToolAt = function(col, row, frame, color, canvas, dpi) {
|
ns.SimplePen.prototype.applyToolAt = function(col, row, frame, color, canvas, dpi) {
|
||||||
|
|
||||||
|
this.previousCol = col;
|
||||||
|
this.previousRow = row;
|
||||||
|
|
||||||
// Change model:
|
// Change model:
|
||||||
var color = pskl.utils.normalizeColor(color);
|
var color = pskl.utils.normalizeColor(color);
|
||||||
if (color != frame[col][row]) {
|
if (color != frame[col][row]) {
|
||||||
@ -29,6 +35,21 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
ns.SimplePen.prototype.moveToolAt = function(col, row, frame, color, canvas, dpi) {
|
ns.SimplePen.prototype.moveToolAt = function(col, row, frame, color, canvas, dpi) {
|
||||||
this.applyToolAt(col, row, frame, color, canvas, dpi);
|
|
||||||
|
if((Math.abs(col - this.previousCol) > 1) || (Math.abs(row - this.previousRow) > 1)) {
|
||||||
|
// The pen movement is too fast for the mousemove frequency, there is a gap between the
|
||||||
|
// current point and the previously drawn one.
|
||||||
|
// We fill the gap by calculating missing dots (simple linear interpolation) and draw them.
|
||||||
|
var interpolatedPixels = this.getLinePixels_(col, this.previousCol, row, this.previousRow);
|
||||||
|
for(var i=0, l=interpolatedPixels.length; i<l; i++) {
|
||||||
|
this.applyToolAt(interpolatedPixels[i].col, interpolatedPixels[i].row, frame, color, canvas, dpi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.applyToolAt(col, row, frame, color, canvas, dpi);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.previousCol = col;
|
||||||
|
this.previousRow = row;
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -99,41 +99,4 @@
|
|||||||
this.removeCanvasOverlays();
|
this.removeCanvasOverlays();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Bresenham line algorihtm: Get an array of pixels from
|
|
||||||
* start and end coordinates.
|
|
||||||
*
|
|
||||||
* http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
|
|
||||||
* http://stackoverflow.com/questions/4672279/bresenham-algorithm-in-javascript
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ns.Stroke.prototype.getLinePixels_ = function(x0, x1, y0, y1) {
|
|
||||||
|
|
||||||
var pixels = [];
|
|
||||||
var dx = Math.abs(x1-x0);
|
|
||||||
var dy = Math.abs(y1-y0);
|
|
||||||
var sx = (x0 < x1) ? 1 : -1;
|
|
||||||
var sy = (y0 < y1) ? 1 : -1;
|
|
||||||
var err = dx-dy;
|
|
||||||
|
|
||||||
while(true){
|
|
||||||
|
|
||||||
// Do what you need to for this
|
|
||||||
pixels.push({"col": x0, "row": y0});
|
|
||||||
|
|
||||||
if ((x0==x1) && (y0==y1)) break;
|
|
||||||
var e2 = 2*err;
|
|
||||||
if (e2>-dy){
|
|
||||||
err -= dy;
|
|
||||||
x0 += sx;
|
|
||||||
}
|
|
||||||
if (e2 < dx) {
|
|
||||||
err += dx;
|
|
||||||
y0 += sy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pixels;
|
|
||||||
};
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
64
js/piskel.js
64
js/piskel.js
@ -11,18 +11,23 @@ $.namespace("pskl");
|
|||||||
DEFAULT_PEN_COLOR = '#000000',
|
DEFAULT_PEN_COLOR = '#000000',
|
||||||
PISKEL_SERVICE_URL = 'http://2.piskel-app.appspot.com',
|
PISKEL_SERVICE_URL = 'http://2.piskel-app.appspot.com',
|
||||||
|
|
||||||
|
// Temporary zoom implementation to easily get bigger canvases to
|
||||||
|
// see how good perform critical algorithms on big canvas.
|
||||||
|
zoom = 1,
|
||||||
|
|
||||||
// Configuration:
|
// Configuration:
|
||||||
// Canvas size in pixel size (not dpi related)
|
// Canvas size in pixel size (not dpi related)
|
||||||
framePixelWidth = 32,
|
framePixelWidth = 32 * zoom,
|
||||||
framePixelHeight = 32,
|
framePixelHeight = 32 * zoom,
|
||||||
|
|
||||||
|
|
||||||
// Scaling factors for a given frameSheet rendering:
|
// Scaling factors for a given frameSheet rendering:
|
||||||
// Main drawing area:
|
// Main drawing area:
|
||||||
drawingCanvasDpi = 20,
|
drawingCanvasDpi = Math.ceil(20/ zoom),
|
||||||
// Canvas previous in the slideshow:
|
// Canvas previous in the slideshow:
|
||||||
previewTileCanvasDpi = 4,
|
previewTileCanvasDpi = Math.ceil(4 / zoom),
|
||||||
// Ainmated canvas preview:
|
// Ainmated canvas preview:
|
||||||
previewAnimationCanvasDpi = 8,
|
previewAnimationCanvasDpi = Math.ceil(8 / zoom),
|
||||||
|
|
||||||
// DOM references:
|
// DOM references:
|
||||||
drawingAreaContainer,
|
drawingAreaContainer,
|
||||||
@ -39,6 +44,7 @@ $.namespace("pskl");
|
|||||||
paletteColors = [],
|
paletteColors = [],
|
||||||
currentFrame = null;
|
currentFrame = null;
|
||||||
currentToolBehavior = null,
|
currentToolBehavior = null,
|
||||||
|
previousMousemoveTime = 0,
|
||||||
|
|
||||||
//utility
|
//utility
|
||||||
_normalizeColor = function (color) {
|
_normalizeColor = function (color) {
|
||||||
@ -131,21 +137,22 @@ $.namespace("pskl");
|
|||||||
},
|
},
|
||||||
|
|
||||||
removeMessage : function () {
|
removeMessage : function () {
|
||||||
var message = $("user-message");
|
var message = $("#user-message");
|
||||||
if (message) {
|
if (message.length) {
|
||||||
message.parentNode.removeChild(message);
|
message.remove();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
persistToLocalStorageRequest: function() {
|
persistToLocalStorageRequest: function() {
|
||||||
// Persist to localStorage when drawing. We throttle localStorage accesses
|
// Persist to localStorage when drawing. We throttle localStorage accesses
|
||||||
// for high frequency drawing (eg mousemove).
|
// for high frequency drawing (eg mousemove).
|
||||||
if(localStorageThrottler == null) {
|
if(localStorageThrottler != null) {
|
||||||
localStorageThrottler = window.setTimeout(function() {
|
window.clearTimeout(localStorageThrottler);
|
||||||
piskel.persistToLocalStorage();
|
|
||||||
localStorageThrottler = null;
|
|
||||||
}, 1000);
|
|
||||||
}
|
}
|
||||||
|
localStorageThrottler = window.setTimeout(function() {
|
||||||
|
piskel.persistToLocalStorage();
|
||||||
|
localStorageThrottler = null;
|
||||||
|
}, 1000);
|
||||||
},
|
},
|
||||||
|
|
||||||
persistToLocalStorage: function() {
|
persistToLocalStorage: function() {
|
||||||
@ -394,20 +401,25 @@ $.namespace("pskl");
|
|||||||
onCanvasMousemove : function (event) {
|
onCanvasMousemove : function (event) {
|
||||||
|
|
||||||
//this.updateCursorInfo(event);
|
//this.updateCursorInfo(event);
|
||||||
if (isClicked) {
|
var currentTime = new Date().getTime();
|
||||||
var spriteCoordinate = this.getSpriteCoordinate(event);
|
// Throttling of the mousemove event:
|
||||||
currentToolBehavior.moveToolAt(
|
if ((currentTime - previousMousemoveTime) > 40 ) {
|
||||||
spriteCoordinate.col,
|
if (isClicked) {
|
||||||
spriteCoordinate.row,
|
var spriteCoordinate = this.getSpriteCoordinate(event);
|
||||||
currentFrame,
|
currentToolBehavior.moveToolAt(
|
||||||
penColor,
|
spriteCoordinate.col,
|
||||||
drawingAreaCanvas,
|
spriteCoordinate.row,
|
||||||
drawingCanvasDpi);
|
currentFrame,
|
||||||
|
penColor,
|
||||||
|
drawingAreaCanvas,
|
||||||
|
drawingCanvasDpi);
|
||||||
|
|
||||||
// TODO(vincz): Find a way to move that to the model instead of being at the interaction level.
|
// TODO(vincz): Find a way to move that to the model instead of being at the interaction level.
|
||||||
// Eg when drawing, it may make sense to have it here. However for a non drawing tool,
|
// Eg when drawing, it may make sense to have it here. However for a non drawing tool,
|
||||||
// you don't need to draw anything when mousemoving and you request useless localStorage.
|
// you don't need to draw anything when mousemoving and you request useless localStorage.
|
||||||
piskel.persistToLocalStorageRequest();
|
piskel.persistToLocalStorageRequest();
|
||||||
|
}
|
||||||
|
previousMousemoveTime = currentTime;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user