feature : zoom level
- fix : removed duplicated code between ImageResizer and CanvasUtils (disabledImageSmoothing utility method) - added pskl.utils.UserAgent, basic user agent sniffer. I need it to sniff out IE10 for frame rendering (and it's not possible to feature detect here). Can check isChrome, isFirefox, isIE and get the version for each of them - added resizeNearestNeighbour in ImageResizer. Readapted from piskel website, this allows us to 1 - resize without AA on IE10, and 2 - add a pixel gap to reenable the GRID - finally : added back support for GRID ! - also extracted the 'zoomed out background color' as a constant in Constant.js
This commit is contained in:
parent
2248f41e68
commit
6e1ce724cb
8 changed files with 118 additions and 22 deletions
|
@ -46,6 +46,7 @@ var Constants = {
|
|||
IMAGE_SERVICE_GET_URL : 'http://screenletstore.appspot.com/img/',
|
||||
|
||||
GRID_STROKE_WIDTH: 1,
|
||||
ZOOMED_OUT_BACKGROUND_COLOR : '#A0A0A0',
|
||||
|
||||
LEFT_BUTTON : 'left_button_1',
|
||||
RIGHT_BUTTON : 'right_button_2',
|
||||
|
|
|
@ -17,7 +17,13 @@
|
|||
ns.CachedFrameRenderer.prototype.render = function (frame) {
|
||||
var offset = this.getOffset();
|
||||
var size = this.getDisplaySize();
|
||||
var serializedFrame = [this.getZoom(), offset.x, offset.y, size.width, size.height, frame.serialize()].join('-');
|
||||
var serializedFrame = [
|
||||
this.getZoom(),
|
||||
this.isGridEnabled(),
|
||||
offset.x, offset.y,
|
||||
size.width, size.height,
|
||||
frame.serialize()
|
||||
].join('-');
|
||||
if (this.serializedFrame != serializedFrame) {
|
||||
this.serializedFrame = serializedFrame;
|
||||
this.superclass.render.call(this, frame);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
y : 0
|
||||
};
|
||||
|
||||
this.isGridEnabled_ = false;
|
||||
this.supportGridRendering = renderingOptions.supportGridRendering;
|
||||
|
||||
this.classes = classes || [];
|
||||
|
@ -115,7 +116,7 @@
|
|||
x : this.offset.x,
|
||||
y : this.offset.y
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.moveOffset = function (x, y) {
|
||||
this.setOffset(this.offset.x + x, this.offset.y + y);
|
||||
|
@ -136,8 +137,11 @@
|
|||
};
|
||||
|
||||
ns.FrameRenderer.prototype.setGridEnabled = function (flag) {
|
||||
this.gridStrokeWidth = (flag && this.supportGridRendering) ? Constants.GRID_STROKE_WIDTH : 0;
|
||||
this.canvasConfigDirty = true;
|
||||
this.isGridEnabled_ = flag && this.supportGridRendering;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.isGridEnabled = function () {
|
||||
return this.isGridEnabled_;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.updateMargins_ = function () {
|
||||
|
@ -197,7 +201,7 @@
|
|||
x = x - this.margin.x;
|
||||
y = y - this.margin.y;
|
||||
|
||||
var cellSize = this.zoom + this.gridStrokeWidth;
|
||||
var cellSize = this.zoom;
|
||||
// apply frame offset
|
||||
x = x + this.offset.x * cellSize;
|
||||
y = y + this.offset.y * cellSize;
|
||||
|
@ -228,16 +232,28 @@
|
|||
|
||||
context = this.displayCanvas.getContext('2d');
|
||||
context.save();
|
||||
// zoom < 1
|
||||
context.fillStyle = "#aaa";
|
||||
// zoom < 1
|
||||
context.fillRect(0,0,this.displayCanvas.width, this.displayCanvas.height);
|
||||
context.translate(this.margin.x, this.margin.y);
|
||||
context.scale(this.zoom, this.zoom);
|
||||
context.translate(-this.offset.x, -this.offset.y);
|
||||
// zoom < 1
|
||||
context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
context.drawImage(this.canvas, 0, 0);
|
||||
|
||||
if (this.canvas.width*this.zoom < this.displayCanvas.width) {
|
||||
context.fillStyle = Constants.ZOOMED_OUT_BACKGROUND_COLOR;
|
||||
context.fillRect(0,0,this.displayCanvas.width, this.displayCanvas.height);
|
||||
}
|
||||
|
||||
context.translate(
|
||||
this.margin.x-this.offset.x*this.zoom,
|
||||
this.margin.y-this.offset.y*this.zoom
|
||||
);
|
||||
|
||||
context.clearRect(0, 0, this.canvas.width*this.zoom, this.canvas.height*this.zoom);
|
||||
|
||||
var isIE10 = pskl.utils.UserAgent.isIE && pskl.utils.UserAgent.version === 10;
|
||||
if (this.isGridEnabled() || isIE10) {
|
||||
var gridWidth = this.isGridEnabled() ? Constants.GRID_STROKE_WIDTH : 0;
|
||||
var scaled = pskl.utils.ImageResizer.resizeNearestNeighbour(this.canvas, this.zoom, gridWidth);
|
||||
context.drawImage(scaled, 0, 0);
|
||||
} else {
|
||||
context.scale(this.zoom, this.zoom);
|
||||
context.drawImage(this.canvas, 0, 0);
|
||||
}
|
||||
context.restore();
|
||||
};
|
||||
})();
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
var serializedRendering = [
|
||||
this.getZoom(),
|
||||
this.isGridEnabled(),
|
||||
offset.x,
|
||||
offset.y,
|
||||
size.width,
|
||||
|
|
|
@ -32,6 +32,11 @@
|
|||
if (canvas) {
|
||||
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
},
|
||||
|
||||
getImageDataFromCanvas : function (canvas) {
|
||||
var sourceContext = canvas.getContext('2d');
|
||||
return sourceContext.getImageData(0, 0, canvas.width, canvas.height).data;
|
||||
}
|
||||
};
|
||||
})();
|
|
@ -8,7 +8,7 @@
|
|||
context.save();
|
||||
|
||||
if (!smoothingEnabled) {
|
||||
this.disableSmoothingOnContext(context);
|
||||
pskl.CanvasUtils.disableImageSmoothing(canvas);
|
||||
}
|
||||
|
||||
context.translate(canvas.width / 2, canvas.height / 2);
|
||||
|
@ -19,12 +19,58 @@
|
|||
return canvas;
|
||||
},
|
||||
|
||||
disableSmoothingOnContext : function (context) {
|
||||
context.imageSmoothingEnabled = false;
|
||||
context.mozImageSmoothingEnabled = false;
|
||||
context.oImageSmoothingEnabled = false;
|
||||
context.webkitImageSmoothingEnabled = false;
|
||||
context.msImageSmoothingEnabled = false;
|
||||
/**
|
||||
* Manual implementation of resize using a nearest neighbour algorithm
|
||||
* It is slower than relying on the native 'disabledImageSmoothing' available on CanvasRenderingContext2d.
|
||||
* But it can be useful if :
|
||||
* - IE < 11 (doesn't support msDisableImageSmoothing)
|
||||
* - need to display a gap between pixel
|
||||
*
|
||||
* @param {Canvas2d} source original image to be resized, as a 2d canvas
|
||||
* @param {Number} zoom ratio between desired dim / source dim
|
||||
* @param {Number} margin gap to be displayed between pixels
|
||||
* @return {Canvas2d} the resized canvas
|
||||
*/
|
||||
resizeNearestNeighbour : function (source, zoom, margin) {
|
||||
margin = margin || 0;
|
||||
var canvas = pskl.CanvasUtils.createCanvas(zoom*source.width, zoom*source.height);
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
var imgData = pskl.CanvasUtils.getImageDataFromCanvas(source);
|
||||
|
||||
var yRanges = {},
|
||||
xOffset = 0,
|
||||
yOffset = 0,
|
||||
xRange,
|
||||
yRange;
|
||||
// Draw the zoomed-up pixels to a different canvas context
|
||||
for (var x = 0; x < source.width; x++) {
|
||||
// Calculate X Range
|
||||
xRange = (((x + 1) * zoom) | 0) - xOffset;
|
||||
|
||||
for (var y = 0; y < source.height; y++) {
|
||||
// Calculate Y Range
|
||||
if (!yRanges[y + ""]) {
|
||||
// Cache Y Range
|
||||
yRanges[y + ""] = (((y + 1) * zoom) | 0) - yOffset;
|
||||
}
|
||||
yRange = yRanges[y + ""];
|
||||
|
||||
var i = (y * source.width + x) * 4;
|
||||
var r = imgData[i];
|
||||
var g = imgData[i + 1];
|
||||
var b = imgData[i + 2];
|
||||
var a = imgData[i + 3];
|
||||
|
||||
context.fillStyle = "rgba(" + r + "," + g + "," + b + "," + (a / 255) + ")";
|
||||
context.fillRect(xOffset, yOffset, xRange-margin, yRange-margin);
|
||||
|
||||
yOffset += yRange;
|
||||
}
|
||||
yOffset = 0;
|
||||
xOffset += xRange;
|
||||
}
|
||||
return canvas;
|
||||
}
|
||||
};
|
||||
})();
|
20
js/utils/UserAgent.js
Normal file
20
js/utils/UserAgent.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
(function () {
|
||||
var ns = $.namespace('pskl.utils');
|
||||
var ua = navigator.userAgent;
|
||||
|
||||
ns.UserAgent = {
|
||||
isIE : /MSIE/i.test( ua ),
|
||||
isChrome : /Chrome/i.test( ua ),
|
||||
isFirefox : /Firefox/i.test( ua )
|
||||
};
|
||||
|
||||
ns.UserAgent.version = (function () {
|
||||
if (pskl.utils.UserAgent.isIE) {
|
||||
return parseInt(/MSIE\s?(\d+)/i.exec( ua )[1], 10);
|
||||
} else if (pskl.utils.UserAgent.isChrome) {
|
||||
return parseInt(/Chrome\/(\d+)/i.exec( ua )[1], 10);
|
||||
} else if (pskl.utils.UserAgent.isFirefox) {
|
||||
return parseInt(/Firefox\/(\d+)/i.exec( ua )[1], 10);
|
||||
}
|
||||
})();
|
||||
})();
|
|
@ -13,6 +13,7 @@ exports.scripts = [
|
|||
|
||||
// Libraries
|
||||
"js/utils/core.js",
|
||||
"js/utils/UserAgent.js",
|
||||
"js/utils/CanvasUtils.js",
|
||||
"js/utils/Math.js",
|
||||
"js/utils/FileUtils.js",
|
||||
|
|
Loading…
Reference in a new issue