2016-08-23 3 views
0

Ich versuche, eine Möglichkeit zu entwickeln, Objekte auszuwählen, die unter und (vollständig) von anderen Objekten überlagert sind. Eine Idee ist, das oberste Objekt auszuwählen und dann über nach unten durch die Ebenen zu gehen. Dies ist, was ich im Moment habe:Wie man verdeckte Objekte per Maus in fabricJS auswählt?

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>

Wie Sie sehen können, von den red Rechteck auszuwählen versuchen, innerhalb der blue eine funktioniert nicht. Ich kann nur die green oder die blue auswählen. Ich denke, dass nach dem ersten doubleclick funktioniert (green ist ausgewählt), klicken Sie erneut nur blue, so dass der folgende Doppelklick ist nur in der Lage, green wieder zu bekommen.

Gibt es einen Weg um dies? Irgendwelche anderen Ideen?

+0

** „Jede andere Ideen?“ ** Sicher, wenn ein FabricJS getroffen Test von mehrschichtigen Rechtecke ist nicht ohne weiteres verfügbar, iterieren nur durch die Rects und mathematisch-Test, wenn der mouseX , mouseY ist in jedem rect. Siehe hierzu Html5-Canvas [Dokumentationsbeispiel] (http://stackoverflow.com/documentation/html5-canvas/5017/collisions-and-intersections/17716/is-an-xy-point-inside-a-rectangle#t= 201608240434175724158). Auf diese Weise müssen Sie nicht versuchen, Klicks & Doppelklicks & Tripleclicks etc. zu koordinieren ;-) – markE

+0

@markE: Das spricht mein Problem nicht an. Ich weiß bereits, welche Objekte vom Mauszeiger getroffen werden (dies sind meine '_Ziele' im obigen Code). Ich brauche einen Mechanismus, um Objekte auszuwählen, die von anderen abgedeckt werden. Und die darunter und so weiter. – Fidel90

+0

Ich bin kein FabricJS-Guru, aber können Sie keine Gruppe von Objekten mit 'fabric.Group' auswählen? 'var group = new fabric.Group(); group.addWithUpdate (Zielobjekt); canvas.setActiveObject (Gruppe); canvas.add (Gruppe); ' – markE

Antwort

1

Nach einiger Zeit konnte ich das endlich selbst lösen. Ein Klick auf ein Objekt bringt es an die Spitze. Beim Doppelklick versuche ich das Objekt eine Schicht hinter dem aktuellen Objekt zu bekommen. Bei einem weiteren Doppelklick bekomme ich den hinter und so weiter. Funktioniert gut für mich und ermöglicht auch die Auswahl von vollständig bedeckten Objekten ohne die Notwendigkeit, andere zu bewegen.

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>

Verwandte Themen