2016-08-23 138 views
0

我想开发一种方法来选择分层下面和(完全)被其他对象覆盖的对象。一个想法是选择最上面的对象,然后通过向下穿过层。这是我的时刻了:如何通过鼠标在fabricJS中选择遮盖物体?

var canvas = new fabric.Canvas("c"); 
 

 
fabric.util.addListener(canvas.upperCanvasEl, "dblclick", function (e) { 
 
    var _canvas = canvas; 
 
    var _mouse = _canvas.getPointer(e); 
 
    var _active = _canvas.getActiveObject(); 
 
    
 
    if (e.target) { 
 
    var _targets = _canvas.getObjects().filter(function (_obj) { 
 
     return _obj.containsPoint(_mouse); 
 
    }); 
 
     
 
    //console.warn(_targets); 
 
     
 
    for (var _i=0, _max=_targets.length; _i<_max; _i+=1) { 
 
     //check if target is currently active 
 
     if (_targets[_i] == _active) { 
 
     \t //then select the one on the layer below 
 
     \t _targets[_i-1] && _canvas.setActiveObject(_targets[_i-1]); 
 
     break; 
 
     } 
 
     } 
 
    } 
 
}); 
 

 
canvas 
 
    .add(new fabric.Rect({ 
 
    top: 25, 
 
    left: 25, 
 
    width: 100, 
 
    height: 100, 
 
    fill: "red" 
 
    })) 
 
    .add(new fabric.Rect({ 
 
    top: 50, 
 
    left: 50, 
 
    width: 100, 
 
    height: 100, 
 
    fill: "green" 
 
    })) 
 
    .add(new fabric.Rect({ 
 
    top: 75, 
 
    left: 75, 
 
    width: 100, 
 
    height: 100, 
 
    fill: "blue" 
 
    })) 
 
    .renderAll();
canvas { 
 
border: 1px solid; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.min.js"></script> 
 
<canvas id="c" width="300" height="200"></canvas>

正如你所看到的,试图从blue一个内选择red矩形没有工作。我只能选择​​或blue。我猜想,在第一个doubleclick工作后(选择了​​),再次点击只需选择blue,因此以下doubleclick只能再次获得​​。

有没有办法解决这个问题?任何其他想法?

+0

**“任何其他的想法?” **当然,如果一个FabricJS打多层矩形的测试是没有现成的,只是通过rects迭代,如果mouseX数学测试,mouseY在任何矩形内。看到这个Html5-Canvas [Documentation Example](http://stackoverflow.com/documentation/html5-canvas/5017/collisions-and-intersections/17716/is-an-xy-point-inside-a-rectangle#t= 201608240434175724158)。这样您就不需要尝试协调点击次数和双击和三次点击等;-) – markE

+0

@markE:这不是解决我的问题。我已经知道哪些对象被鼠标指针击中(这些是我上面代码中的'_targets')。我需要一种机制来“选择”被他人覆盖的对象。下面的那个,等等。 – Fidel90

+0

我不是FabricJS大师,但不能用'fabric.Group'选择一组对象吗? 'var group = new fabric.Group(); group.addWithUpdate(targetObject); canvas.setActiveObject(基); canvas.add(组);' – markE

回答

1

过了一段时间我终于能够自己解决了。点击一个对象将其带到顶部。双击我试图让对象在当前对象后面一层。在另一个dblclick上,我得到了后面的一个,等等。对我很好,也可以选择完全覆盖的物体而无需移动其他物体。

var canvas = new fabric.Canvas("c"); 
 

 
canvas.on("object:selected", function (e) { 
 
    if (e.target) { 
 
    e.target.bringToFront(); 
 
    this.renderAll(); 
 
    } 
 
}); 
 

 
var _prevActive = 0; 
 
var _layer = 0; 
 

 
// 
 
fabric.util.addListener(canvas.upperCanvasEl, "dblclick", function (e) { 
 
    var _canvas = canvas; 
 
    //current mouse position 
 
    var _mouse = _canvas.getPointer(e); 
 
    //active object (that has been selected on click) 
 
    var _active = _canvas.getActiveObject(); 
 
    //possible dblclick targets (objects that share mousepointer) 
 
    var _targets = _canvas.getObjects().filter(function (_obj) { 
 
     return _obj.containsPoint(_mouse) && !_canvas.isTargetTransparent(_obj, _mouse.x, _mouse.y); 
 
    }); 
 
    
 
    _canvas.deactivateAll(); 
 
     
 
    //new top layer target 
 
    if (_prevActive !== _active) { 
 
     //try to go one layer below current target 
 
     _layer = Math.max(_targets.length-2, 0); 
 
    } 
 
    //top layer target is same as before 
 
    else { 
 
     //try to go one more layer down 
 
     _layer = --_layer < 0 ? Math.max(_targets.length-2, 0) : _layer; 
 
    } 
 

 
    //get obj on current layer 
 
    var _obj = _targets[_layer]; 
 

 
    if (_obj) { 
 
    \t _prevActive = _obj; 
 
    \t _obj.bringToFront(); 
 
    \t _canvas.setActiveObject(_obj).renderAll(); 
 
    } 
 
}); 
 

 
//create something to play with 
 
canvas 
 
    //fully covered rect is selectable with dblclicks 
 
    .add(new fabric.Rect({ 
 
    top: 75, 
 
    left: 75, 
 
    width: 50, 
 
    height: 50, 
 
    fill: "black", 
 
    stroke: "black", 
 
    globalCompositeOperation: "xor", 
 
    perPixelTargetFind: true 
 
    })) 
 
    .add(new fabric.Circle({ 
 
    top: 25, 
 
    left: 25, 
 
    radius: 50, 
 
    fill: "rgba(255,0,0,.5)", 
 
    stroke: "black", 
 
    perPixelTargetFind: true 
 
    })) 
 
    .add(new fabric.Circle({ 
 
    top: 50, 
 
    left: 50, 
 
    radius: 50, 
 
    fill: "rgba(0,255,0,.5)", 
 
    stroke: "black", 
 
    perPixelTargetFind: true 
 
    })) 
 
    .add(new fabric.Circle({ 
 
    top: 75, 
 
    left: 75, 
 
    radius: 50, 
 
    fill: "rgba(0,0,255,.5)", 
 
    stroke: "black", 
 
    perPixelTargetFind: true 
 
    })) 
 
    .renderAll();
canvas { 
 
border: 1px solid; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.4/fabric.min.js"></script> 
 
<canvas id="c" width="300" height="200"></canvas>

相关问题