Reputation: 1114
I'm trying to render a box with the rotating point in the bottom. Normaly, we can render a box with the property hasRotatingPoint: true
and a handle appear in the top side of the box to the user rotate it.
What I want is to draw it in the bottom side of the box.
This could be achieved by set angle: 180
and the rotating point will appear in the bottom side (as we rotate the box 180°) but I got a draw problem with this approach: the drawing process also rotated 180° and now my box goes in the opposite direction when I'm drawing.
Thanks in advance for any help!
Edit 1
There is a very similar question about this problem here How to change Rotating point position to bottom in FabricJS? but the solution accepted creates another bug in my context as described in the third paragraph.
Upvotes: 0
Views: 2202
Reputation: 1511
You need to rewrite 3 functions. fabric.Object.prototype.calcCoords
, fabric.Object.prototype.drawControls
, fabric.Object.prototype.drawBorders
Those 3 are almost the same, the only difference is that the mtr point is calculated different.
fabric.Object.prototype.calcCoords= function(absolute) {
var rotateMatrix = this._calcRotateMatrix(),
translateMatrix = this._calcTranslateMatrix(),
startMatrix = fabric.util.multiplyTransformMatrices(translateMatrix, rotateMatrix),
vpt = this.getViewportTransform(),
finalMatrix = absolute ? startMatrix : fabric.util.multiplyTransformMatrices(vpt, startMatrix),
dim = this._getTransformedDimensions(),
w = dim.x / 2, h = dim.y / 2,
tl = fabric.util.transformPoint({ x: -w, y: -h }, finalMatrix),
tr = fabric.util.transformPoint({ x: w, y: -h }, finalMatrix),
bl = fabric.util.transformPoint({ x: -w, y: h }, finalMatrix),
br = fabric.util.transformPoint({ x: w, y: h }, finalMatrix);
if (!absolute) {
var padding = this.padding, angle = fabric.util.degreesToRadians(this.angle),
cos = fabric.util.cos(angle), sin = fabric.util.sin(angle),
cosP = cos * padding, sinP = sin * padding, cosPSinP = cosP + sinP,
cosPMinusSinP = cosP - sinP;
if (padding) {
tl.x -= cosPMinusSinP;
tl.y -= cosPSinP;
tr.x += cosPSinP;
tr.y -= cosPMinusSinP;
bl.x -= cosPSinP;
bl.y += cosPMinusSinP;
br.x += cosPMinusSinP;
br.y += cosPSinP;
}
var ml = new fabric.Point((tl.x + bl.x) / 2, (tl.y + bl.y) / 2),
mt = new fabric.Point((tr.x + tl.x) / 2, (tr.y + tl.y) / 2),
mr = new fabric.Point((br.x + tr.x) / 2, (br.y + tr.y) / 2),
mb = new fabric.Point((br.x + bl.x) / 2, (br.y + bl.y) / 2),
mtr = new fabric.Point(mb.x - sin * this.rotatingPointOffset, mb.y + cos * this.rotatingPointOffset);
}
// if (!absolute) {
// var canvas = this.canvas;
// setTimeout(function() {
// canvas.contextTop.clearRect(0, 0, 700, 700);
// canvas.contextTop.fillStyle = 'green';
// canvas.contextTop.fillRect(mb.x, mb.y, 3, 3);
// canvas.contextTop.fillRect(bl.x, bl.y, 3, 3);
// canvas.contextTop.fillRect(br.x, br.y, 3, 3);
// canvas.contextTop.fillRect(tl.x, tl.y, 3, 3);
// canvas.contextTop.fillRect(tr.x, tr.y, 3, 3);
// canvas.contextTop.fillRect(ml.x, ml.y, 3, 3);
// canvas.contextTop.fillRect(mr.x, mr.y, 3, 3);
// canvas.contextTop.fillRect(mt.x, mt.y, 3, 3);
// canvas.contextTop.fillRect(mtr.x, mtr.y, 3, 3);
// }, 50);
// }
var coords = {
// corners
tl: tl, tr: tr, br: br, bl: bl,
};
if (!absolute) {
// middle
coords.ml = ml;
coords.mt = mt;
coords.mr = mr;
coords.mb = mb;
// rotating point
coords.mtr = mtr;
}
return coords;
}
fabric.Object.prototype.drawControls=function(ctx, styleOverride) {
styleOverride = styleOverride || {};
var wh = this._calculateCurrentDimensions(),
width = wh.x,
height = wh.y,
scaleOffset = styleOverride.cornerSize || this.cornerSize,
left = -(width + scaleOffset) / 2,
top = -(height + scaleOffset) / 2,
transparentCorners = typeof styleOverride.transparentCorners !== 'undefined' ?
styleOverride.transparentCorners : this.transparentCorners,
hasRotatingPoint = typeof styleOverride.hasRotatingPoint !== 'undefined' ?
styleOverride.hasRotatingPoint : this.hasRotatingPoint,
methodName = transparentCorners ? 'stroke' : 'fill';
ctx.save();
ctx.strokeStyle = ctx.fillStyle = styleOverride.cornerColor || this.cornerColor;
if (!this.transparentCorners) {
ctx.strokeStyle = styleOverride.cornerStrokeColor || this.cornerStrokeColor;
}
this._setLineDash(ctx, styleOverride.cornerDashArray || this.cornerDashArray, null);
// top-left
this._drawControl('tl', ctx, methodName,
left,
top, styleOverride);
// top-right
this._drawControl('tr', ctx, methodName,
left + width,
top, styleOverride);
// bottom-left
this._drawControl('bl', ctx, methodName,
left,
top + height, styleOverride);
// bottom-right
this._drawControl('br', ctx, methodName,
left + width,
top + height, styleOverride);
if (!this.get('lockUniScaling')) {
// middle-top
this._drawControl('mt', ctx, methodName,
left + width / 2,
top, styleOverride);
// middle-bottom
this._drawControl('mb', ctx, methodName,
left + width / 2,
top + height, styleOverride);
// middle-right
this._drawControl('mr', ctx, methodName,
left + width,
top + height / 2, styleOverride);
// middle-left
this._drawControl('ml', ctx, methodName,
left,
top + height / 2, styleOverride);
}
// middle-top-rotate
if (hasRotatingPoint) {
this._drawControl('mtr', ctx, methodName,
left + width / 2,
top + height + this.rotatingPointOffset, styleOverride);
}
ctx.restore();
return this;
}
fabric.Object.prototype.drawBorders=function(ctx, styleOverride) {
styleOverride = styleOverride || {};
var wh = this._calculateCurrentDimensions(),
strokeWidth = 1 / this.borderScaleFactor,
width = wh.x + strokeWidth,
height = wh.y + strokeWidth,
drawRotatingPoint = typeof styleOverride.hasRotatingPoint !== 'undefined' ?
styleOverride.hasRotatingPoint : this.hasRotatingPoint,
hasControls = typeof styleOverride.hasControls !== 'undefined' ?
styleOverride.hasControls : this.hasControls,
rotatingPointOffset = typeof styleOverride.rotatingPointOffset !== 'undefined' ?
styleOverride.rotatingPointOffset : this.rotatingPointOffset;
ctx.save();
ctx.strokeStyle = styleOverride.borderColor || this.borderColor;
this._setLineDash(ctx, styleOverride.borderDashArray || this.borderDashArray, null);
ctx.strokeRect(
-width / 2,
-height / 2,
width,
height
);
if (drawRotatingPoint && this.isControlVisible('mtr') && hasControls) {
var rotateHeight = height / 2;
ctx.beginPath();
ctx.moveTo(0, rotateHeight);
ctx.lineTo(0, rotateHeight + rotatingPointOffset);
ctx.stroke();
}
ctx.restore();
return this;
}
body {
background-color: ivory;
padding:20px;
}
#canvas {
border:1px solid red;
}
<canvas id="canvas" width="666" height="444"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.0.0/fabric.js"></script>
<script>
var obj = new fabric.Triangle({
fill: 'lime',
top: 110,
left: 110,
borderColor: 'red',
cornerColor: 'cyan',
cornerSize: 9,
transparentCorners: false
});
var canvas = new fabric.Canvas('canvas');
canvas.add(obj);
</script>
Upvotes: 3