问题
i try to draw a polygon with the mouse , and i have found that example on jsfiddle: http://jsfiddle.net/Kienz/ujefxh7w/.
the problem is that when we finish the draw and try to selet the object, the borders are outside of the shape.
can we fixe that or is it a fabric.js bug?
as we can also see on the official fabricjs.com/ page, on the front page examples, the free hand drawings are also out of the border frame.
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c');
// Do some initializing stuff
fabric.Object.prototype.set({
transparentCorners: false,
cornerColor: 'rgba(102,153,255,0.5)',
cornerSize: 12,
padding: 7
});
// ADD YOUR CODE HERE
var mode = "add",
currentShape;
canvas.observe("mouse:move", function (event) {
var pos = canvas.getPointer(event.e);
if (mode === "edit" && currentShape) {
var points = currentShape.get("points");
points[points.length - 1].x = pos.x - currentShape.get("left");
points[points.length - 1].y = pos.y - currentShape.get("top");
currentShape.set({
points: points
});
canvas.renderAll();
}
});
canvas.observe("mouse:down", function (event) {
var pos = canvas.getPointer(event.e);
if (mode === "add") {
var polygon = new fabric.Polygon([{
x: pos.x,
y: pos.y
}, {
x: pos.x + 0.5,
y: pos.y + 0.5
}], {
fill: 'blue',
opacity: 0.5,
selectable: false
});
currentShape = polygon;
canvas.add(currentShape);
mode = "edit";
} else if (mode === "edit" && currentShape && currentShape.type === "polygon") {
var points = currentShape.get("points");
points.push({
x: pos.x - currentShape.get("left"),
y: pos.y - currentShape.get("top")
});
currentShape.set({
points: points
});
canvas.renderAll();
}
});
fabric.util.addListener(window, 'keyup', function (e) {
if (e.keyCode === 27) {
if (mode === 'edit' || mode === 'add') {
mode = 'normal';
currentShape.set({
selectable: true
});
currentShape._calcDimensions(false);
currentShape.setCoords();
} else {
mode = 'add';
}
currentShape = null;
}
canvas.renderAll();
})
回答1:
THE PROBLEM
_calcDimensions() calculates width, height, minX and minY of the polygon, so as you can see with this fiddle http://jsfiddle.net/ujefxh7w/90/ the centerpoint of our polygon (that is calculated using width and height) will be changed after calling _calcDimensions() (before this, the centerpoint's value was equal to the top-left point because width and height were zero).
However we inserted all points to the polygon by subtracting the left-top position to them, but after calling _calcDimensions() those points will be rendered by starting from the "new" (correct) centerpoint, as you can see from your fiddle.
Moreover we have to handle minX and minY offsets introduced by _calcDimensions(). If we don't do this you can manage to draw some shapes with some area of out the bounds. (e.g. draw a triangle with those coordinates [(100,100),(150,50),(200,200)], the second point will be out of bound).
THE SOLUTION
We have to
- add minX and minY offset to the left-top position of our shape and subtracting them from the new points's values
- recalculate points's coordinates by using the actual centerpoint and the left-top position of our polygon
http://jsfiddle.net/ujefxh7w/115/
fabric.util.addListener(window, 'keyup', function (e) {
if (e.keyCode === 27) {
if (mode === 'edit' || mode === 'add') {
mode = 'normal';
// remove last useless point
var points = currentShape.get("points");
points.pop();
currentShape.set({points: points});
// call helpers
currentShape._calcDimensions();
currentShape.setCoords();
// adjust shape position by using minX and minY offsets
var minx = currentShape.get("minX");
var miny = currentShape.get("minY");
currentShape.set({
left: currentShape.get("left") + minx,
top: currentShape.get("top") + miny
});
// adjust points coordinates by
// 1- subtracting the center point coords
// 2- adding the left-top coords
// 3- subtracting minX and minY offsets
var pCenter = currentShape.getCenterPoint();
var l = currentShape.get("left");
var t = currentShape.get("top");
var adjPoints = currentShape.get("points").map(function(p) {
return {
x: p.x - pCenter.x + l - minx,
y: p.y - pCenter.y + t - miny
};
});
currentShape.set({
points: adjPoints,
selectable: true
});
canvas.setActiveObject(currentShape);
canvas.renderAll();
} else {
mode = 'add';
}
currentShape = null;
}
});
来源:https://stackoverflow.com/questions/28769421/wrong-border-coords-on-draw-a-polygon-with-the-fabric-js