I'm working on a project where images can be added to a FabricJS
canvas at a variety of resolutions. Because of how Fabric handles stroke widths, this variance in image sizes causes strokes to be inconsistently rendered.
Borrowing from byoungb's solution for maintaining a constant stroke width, I've managed to get my image borders to remain both visually consistent, and have correct control/bounding positions by overriding the _renderStroke
and _getTransformedDimensions
methods of the Image
class. This breaks down however in cases where the image is skewed and I can't seem to nail down the correct place to modify the object dimension calculation in cases where skewing is present (I expect I need to modify the _calcDimensionsTransformMatrix
method for Image
but have had no success so far).
http://jsfiddle.net/melchiar/bt4ckmea/ (bounding rectangle shown in black)
//override stroke rendering for constant stroke width independent of scaling
fabric.Image.prototype._renderStroke = function(ctx) {
if (!this.stroke || this.strokeWidth === 0) {
return;
}
if (this.shadow && !this.shadow.affectStroke) {
this._removeShadow(ctx);
}
ctx.save();
ctx.scale(1 / this.scaleX, 1 / this.scaleY);
this._setLineDash(ctx, this.strokeDashArray, this._renderDashedStroke);
this._applyPatternGradientTransform(ctx, this.stroke);
ctx.stroke();
ctx.restore();
};
//modify method for calculating control and bounding box positions
fabric.Image.prototype._getTransformedDimensions = function(skewX, skewY) {
if (typeof skewX === 'undefined') {
skewX = this.skewX;
}
if (typeof skewY === 'undefined') {
skewY = this.skewY;
}
var dimensions = this._getNonTransformedDimensions();
if (skewX === 0 && skewY === 0) {
return {
x: dimensions.x * this.scaleX + (this.strokeWidth * (1 - this.scaleX)),
y: dimensions.y * this.scaleY + (this.strokeWidth * (1 - this.scaleY))
};
}
var dimX = dimensions.x / 2,
dimY = dimensions.y / 2,
points = [{
x: -dimX,
y: -dimY
},
{
x: dimX,
y: -dimY
},
{
x: -dimX,
y: dimY
},
{
x: dimX,
y: dimY
}
],
i, transformMatrix = this._calcDimensionsTransformMatrix(skewX, skewY, false),
bbox;
for (i = 0; i < points.length; i++) {
points[i] = fabric.util.transformPoint(points[i], transformMatrix);
}
bbox = fabric.util.makeBoundingBoxFromPoints(points);
return {
x: bbox.width,
y: bbox.height
};
};