FabricJS Catch 点击组内的对象
FabricJS Catch click on object inside group
我尝试了很多事情,比如计算位置、处理我们在原始 fabricjs 中确实有的事件。有人做过吗?
可能对你有帮助http://jsfiddle.net/UKbaseduser/Kt9Mk/1/
$("#1").click(function(){
ZoomIn('tmp1');
});
$("#2").click(function(){
ZoomOut('tmp1');
});
$("#3").click(function(){
ZoomIn('tmp2');
});
$("#4").click(function(){
ZoomOut('tmp2');
});
var canvas = new fabric.Canvas('c');
var rect1 = new fabric.Rect({ left: 150, top: 150, width: 100, height: 100, fill: 'green'});
var rect2 = new fabric.Rect({ left: 250, top: 250, width: 100, height: 100, fill: 'green'});
rect1.grp='tmp1';
rect2.grp='tmp1';
var c = new fabric.Circle({
left: 200,
top: 200,
radius: 50,
fill: 'red',
opacity:0.8
});
c.grp='tmp2';
canvas.add(rect1);
canvas.add(rect2);
canvas.add(c);
canvas.renderAll();
function ZoomIn(inGrp){
var SCALE_FACTOR = 1.2;
var objects = canvas.getObjects();
objects.forEach(function(obj){
if (obj.grp==inGrp){
var scaleX = obj.scaleX;
var scaleY = obj.scaleY;
var left = obj.left;
var top = obj.top;
var tempScaleX = scaleX * SCALE_FACTOR;
var tempScaleY = scaleY * SCALE_FACTOR;
var tempLeft = left * SCALE_FACTOR;
var tempTop = top * SCALE_FACTOR;
obj.scaleX = tempScaleX;
obj.scaleY = tempScaleY;
obj.left = tempLeft;
obj.top = tempTop;
obj.setCoords();
}
});
canvas.renderAll();
}
function ZoomOut(inGrp){
var SCALE_FACTOR = 1.2;
var objects = canvas.getObjects();
objects.forEach(function(obj){
if (obj.grp==inGrp){
var scaleX = obj.scaleX;
var scaleY = obj.scaleY;
var left = obj.left;
var top = obj.top;
var tempScaleX = scaleX * 1/SCALE_FACTOR;
var tempScaleY = scaleY * 1/SCALE_FACTOR;
var tempLeft = left * 1/SCALE_FACTOR;
var tempTop = top * 1/SCALE_FACTOR;
obj.scaleX = tempScaleX;
obj.scaleY = tempScaleY;
obj.left = tempLeft;
obj.top = tempTop;
obj.setCoords();
}
});
canvas.renderAll();
}
这里也有类似的讨论https://groups.google.com/forum/#!topic/fabricjs/hQwHxGfyx6w可能会给你一些建议。
在 FabricJS 中,一旦对象被组装成一个组,事件只会在那里发生,即使是选定的事件——所以你无法检测到组中的哪些项目被选中。在事件处理程序中
var g = new fabric.Group([ rect, text ], {
g.on('mousedown', function(e) {
// Inspect, for a collection of the objects in this group
this._objects
});
即使在组装到组中之前将事件处理程序附加到对象,处理程序也不会触发:(
我从 asturur repo 下载了 fabricjs。
构建 fabric.js 文件
node build.js modules=ALL exclude=json,gestures
而且有效!
然后您可以在组中的对象上使用事件。
canvas._objects[0]._objects[0].on('mousedown', function(e){ this.stroke = 'black'});
在我的应用程序中,我决定从 mousedown 回调中搜索事件
group.on('mousedown', function(e){
var innerTarget = group._searchPossibleTargets(e.e);
console.log(innerTarget);
});
group._searchPossibleTargets = function(e) {
var pointer = this.canvas.getPointer(e, true);
var i = objects.length,
normalizedPointer = this.canvas._normalizePointer(this, pointer);
while (i--) {
if (this.canvas._checkTarget(normalizedPointer, this._objects[i])) {
return this._objects[i];
}
}
return null;
}
可以通过向 fabric.Group 对象添加选项 subTargetCheck: true
来监听内部对象上的事件。
// create a group
let group = new fabric.Group([circle, rect], {
subTargetCheck: true
});
circle.on('mousedown', function(e) {
// e.target should be the circle
console.log(e.target);
});
这对我有用:
// create a group
let group = new fabric.Group([circle, rect], {
subTargetCheck: true
});
canvas.on('mouse:down', function (e) {
// clicked item will be
console.log(e.subTargets[0])
});
我没有足够的声誉来对现有答案发表评论,所以就这样吧。我正在使用 v2.X 的 Fabric,所有现有的解决方案都不起作用。对于不再存在的方法的控制台错误,或者在 containsPoint
的情况下总是 false
,所以我构建了自己的方法。
js
const getSelectedObject = (target, e) => {
const point = target.canvas.getPointer(e, false);
const objects = findSubTargets(target, []);
const objectIndex = objects
.reduce((reduction, object, index) => {
reduction.push(
getBoundingPoints(
object,
index === 0 ? 0 : reduction[0].start.x,
index === 0 ? 0 : reduction[0].start.y
)
);
return reduction;
}, [])
.reverse()
.findIndex((bounds) => pointIsInBounds(point, bounds));
return objects.reverse()[objectIndex];
};
和辅助函数
js
const getBoundingPoints = (object, deltaX, deltaY) => {
const coords = object.get("aCoords");
const x1 = coords.tl.x + deltaX;
const y1 = coords.tl.y + deltaY;
const x2 = coords.br.x + deltaX;
const y2 = coords.br.y + deltaY;
return {
start: { x: x1, y: y1 },
finish: { x: x2, y: y2 }
};
};
const pointIsInBounds = (point, bounds) => {
const xIsInBounds = point.x >= bounds.start.x && point.x <= bounds.finish.x;
const yIsInBounds = point.y >= bounds.start.y && point.y <= bounds.finish.y;
return xIsInBounds && yIsInBounds;
};
const findSubTargets = (target, objects) => {
if (target.isType("group")) {
objects.push(target);
target.forEachObject((object) => findSubTargets(object, objects));
}
return objects;
};
我已经用简单组、嵌套组和组内组内组进行了测试。
您可以将 subTarget
添加到群组中。子目标对象将添加到目标事件中。
let group = new fabric.Group([circle, rect], {
subTargetCheck: true
});
canvas.on('mouse:down', (event) => {
const { subTargets } = event; // subTargets will include circle object
....
})
我尝试了很多事情,比如计算位置、处理我们在原始 fabricjs 中确实有的事件。有人做过吗?
可能对你有帮助http://jsfiddle.net/UKbaseduser/Kt9Mk/1/
$("#1").click(function(){
ZoomIn('tmp1');
});
$("#2").click(function(){
ZoomOut('tmp1');
});
$("#3").click(function(){
ZoomIn('tmp2');
});
$("#4").click(function(){
ZoomOut('tmp2');
});
var canvas = new fabric.Canvas('c');
var rect1 = new fabric.Rect({ left: 150, top: 150, width: 100, height: 100, fill: 'green'});
var rect2 = new fabric.Rect({ left: 250, top: 250, width: 100, height: 100, fill: 'green'});
rect1.grp='tmp1';
rect2.grp='tmp1';
var c = new fabric.Circle({
left: 200,
top: 200,
radius: 50,
fill: 'red',
opacity:0.8
});
c.grp='tmp2';
canvas.add(rect1);
canvas.add(rect2);
canvas.add(c);
canvas.renderAll();
function ZoomIn(inGrp){
var SCALE_FACTOR = 1.2;
var objects = canvas.getObjects();
objects.forEach(function(obj){
if (obj.grp==inGrp){
var scaleX = obj.scaleX;
var scaleY = obj.scaleY;
var left = obj.left;
var top = obj.top;
var tempScaleX = scaleX * SCALE_FACTOR;
var tempScaleY = scaleY * SCALE_FACTOR;
var tempLeft = left * SCALE_FACTOR;
var tempTop = top * SCALE_FACTOR;
obj.scaleX = tempScaleX;
obj.scaleY = tempScaleY;
obj.left = tempLeft;
obj.top = tempTop;
obj.setCoords();
}
});
canvas.renderAll();
}
function ZoomOut(inGrp){
var SCALE_FACTOR = 1.2;
var objects = canvas.getObjects();
objects.forEach(function(obj){
if (obj.grp==inGrp){
var scaleX = obj.scaleX;
var scaleY = obj.scaleY;
var left = obj.left;
var top = obj.top;
var tempScaleX = scaleX * 1/SCALE_FACTOR;
var tempScaleY = scaleY * 1/SCALE_FACTOR;
var tempLeft = left * 1/SCALE_FACTOR;
var tempTop = top * 1/SCALE_FACTOR;
obj.scaleX = tempScaleX;
obj.scaleY = tempScaleY;
obj.left = tempLeft;
obj.top = tempTop;
obj.setCoords();
}
});
canvas.renderAll();
}
这里也有类似的讨论https://groups.google.com/forum/#!topic/fabricjs/hQwHxGfyx6w可能会给你一些建议。
在 FabricJS 中,一旦对象被组装成一个组,事件只会在那里发生,即使是选定的事件——所以你无法检测到组中的哪些项目被选中。在事件处理程序中
var g = new fabric.Group([ rect, text ], {
g.on('mousedown', function(e) {
// Inspect, for a collection of the objects in this group
this._objects
});
即使在组装到组中之前将事件处理程序附加到对象,处理程序也不会触发:(
我从 asturur repo 下载了 fabricjs。 构建 fabric.js 文件
node build.js modules=ALL exclude=json,gestures
而且有效!
然后您可以在组中的对象上使用事件。
canvas._objects[0]._objects[0].on('mousedown', function(e){ this.stroke = 'black'});
在我的应用程序中,我决定从 mousedown 回调中搜索事件
group.on('mousedown', function(e){
var innerTarget = group._searchPossibleTargets(e.e);
console.log(innerTarget);
});
group._searchPossibleTargets = function(e) {
var pointer = this.canvas.getPointer(e, true);
var i = objects.length,
normalizedPointer = this.canvas._normalizePointer(this, pointer);
while (i--) {
if (this.canvas._checkTarget(normalizedPointer, this._objects[i])) {
return this._objects[i];
}
}
return null;
}
可以通过向 fabric.Group 对象添加选项 subTargetCheck: true
来监听内部对象上的事件。
// create a group
let group = new fabric.Group([circle, rect], {
subTargetCheck: true
});
circle.on('mousedown', function(e) {
// e.target should be the circle
console.log(e.target);
});
这对我有用:
// create a group
let group = new fabric.Group([circle, rect], {
subTargetCheck: true
});
canvas.on('mouse:down', function (e) {
// clicked item will be
console.log(e.subTargets[0])
});
我没有足够的声誉来对现有答案发表评论,所以就这样吧。我正在使用 v2.X 的 Fabric,所有现有的解决方案都不起作用。对于不再存在的方法的控制台错误,或者在 containsPoint
的情况下总是 false
,所以我构建了自己的方法。
js
const getSelectedObject = (target, e) => {
const point = target.canvas.getPointer(e, false);
const objects = findSubTargets(target, []);
const objectIndex = objects
.reduce((reduction, object, index) => {
reduction.push(
getBoundingPoints(
object,
index === 0 ? 0 : reduction[0].start.x,
index === 0 ? 0 : reduction[0].start.y
)
);
return reduction;
}, [])
.reverse()
.findIndex((bounds) => pointIsInBounds(point, bounds));
return objects.reverse()[objectIndex];
};
和辅助函数
js
const getBoundingPoints = (object, deltaX, deltaY) => {
const coords = object.get("aCoords");
const x1 = coords.tl.x + deltaX;
const y1 = coords.tl.y + deltaY;
const x2 = coords.br.x + deltaX;
const y2 = coords.br.y + deltaY;
return {
start: { x: x1, y: y1 },
finish: { x: x2, y: y2 }
};
};
const pointIsInBounds = (point, bounds) => {
const xIsInBounds = point.x >= bounds.start.x && point.x <= bounds.finish.x;
const yIsInBounds = point.y >= bounds.start.y && point.y <= bounds.finish.y;
return xIsInBounds && yIsInBounds;
};
const findSubTargets = (target, objects) => {
if (target.isType("group")) {
objects.push(target);
target.forEachObject((object) => findSubTargets(object, objects));
}
return objects;
};
我已经用简单组、嵌套组和组内组内组进行了测试。
您可以将 subTarget
添加到群组中。子目标对象将添加到目标事件中。
let group = new fabric.Group([circle, rect], {
subTargetCheck: true
});
canvas.on('mouse:down', (event) => {
const { subTargets } = event; // subTargets will include circle object
....
})