2013-06-14 12 views
15

Ich habe einige Drag Verhalten definiert, die wie folgt erwartet funktioniert (Code in Coffeescript):Wie kann verhindert werden, dass d3 den Rechtsklick auslöst?

nodeDrag = d3.behavior.drag() 
    .on("dragstart", (d, i) -> 
    force.stop()) 
    .on("drag", (d, i) -> 
    d.px += d3.event.dx 
    d.py += d3.event.dy 
    d.x += d3.event.dx 
    d.y += d3.event.dy 
    tick()) 
    .on("dragend", (d, i) -> 
    force.resume() 
    d.fixed = true 
    tick()) 

// ... 

nodes = vis.selectAll(".node") 
    .data(graph.nodes) 
    .enter() 
    .append("g") 
    // ... 
    .call(nodeDrag) 

ich jetzt versuchen, benutzerdefinierte Verhalten für Rechtsklicks auf Knoten zu erstellen. Dies löst jedoch "dragstart" und "drag" aus, dh nachdem ichim "contextmenu" -Ereignis aufgerufen habe, bleibt der fragliche Knoten an meinem Mauszeiger und folgt ihm, bis ich einen weiteren (linken) Klick mache, um eine Freigabe zu erzwingen (Ich nehme an, e.preventDefault() verursacht auch "dragend", nie zu feuern).

Ich fand eine kurze Diskussion dieses Problems in einer thread on Google Groups und einer discussion in d3's issues on Github. Ich kann jedoch aus diesen Kommentaren nicht herausfinden, wie ich dieses Verhalten verhindern kann.

Wie kann ich das Ziehen bei Rechtsklick nicht auslösen?

+0

Im 'dragstart' Event konnten Sie überprüfen, ob die rechte Maustaste angeklickt wurde (mit d3.Ereignis) und wenn nicht, rufen Sie 'force.stop()' auf. –

+0

Wie kann ich überprüfen, welche Maustaste in 'd3.event' angeklickt wurde? Alle Vorschläge, die ich finden kann, wie 'which',' button' und 'keyCode' geben mir' undefined'. Abgesehen davon: Ich rufe 'force.stop()' auf, um den Layoutalgorithmus zu stoppen, während der Benutzer zieht. Wenn Sie es nicht aufrufen, wird die Ziehbewegung nicht verhindert. – notan3xit

+1

Ich denke, 'd3.event' hat ein Mitglied' sourceEvent' oder etwas ähnliches, das Ihnen Zugriff auf das eigentliche Ereignis gibt. Und ja, Sie würden auch etwas wie 'preventDefault()' benötigen. –

Antwort

9

Ich habe eine Möglichkeit gefunden, die Drag-Gesten nur auf die linke Maustaste zu beschränken.

Es beinhaltet ein zusätzliches Feld, das aufzeichnet, wenn eine Geste initiiert worden ist:

ist
dragInitiated = false 

Der Rest des Codes dann Einleitung und Beendigung eines gewünschten drag Gesten auf „drag“ und „dragend registrieren modifizierte ", beziehungsweise. Aktionen für "Ziehen" werden nur ausgeführt, wenn eine Ziehen-Gesten ordnungsgemäß eingeleitet wurde.

nodeDrag = d3.behavior.drag() 
    .on "dragstart", (d, i) -> 
    if (d3.event.sourceEvent.which == 1) # initiate on left mouse button only 
     dragInitiated = true    # -> set dragInitiated to true 
     force.stop() 
    .on "drag", (d, i) -> 
    if (dragInitiated)     # perform only if a drag was initiated 
     d.px += d3.event.dx 
     d.py += d3.event.dy 
     d.x += d3.event.dx 
     d.y += d3.event.dy 
     tick() 
    .on "dragend", (d, i) -> 
    if (d3.event.sourceEvent.which == 1) # only take gestures into account that 
     force.resume()      # were valid in "dragstart" 
     d.fixed = true 
     tick() 
     dragInitiated = false    # terminate drag gesture 

Ich bin nicht sicher, ob dies die eleganteste Lösung, aber es funktioniert und ist nicht außergewöhnlich ungeschickt oder ein großer Hack.

+0

Wie bei d3 v3.5.3, um zu überprüfen, welche Taste man 'd3.event.button' – herrlich10

+1

für v3.5.6 verwenden kann, sollte der richtige Weg' d3.event.sourceEvent.button' anstelle von 'd3.event sein .button' – paradite

+0

Auch sollte es gleich 0 sein, nicht 1 :) – thatOneGuy

1

Wenig spät auf die Party, hatte ich das gleiche Problem und ich verwendete die folgende Methode, um sicherzustellen, dass meine drag nur funktioniert für left click.

var drag = d3.behavior.drag() 

      .on('drag', function() { 

      console.log(d3.event.sourceEvent.button); 

      if(d3.event.sourceEvent.button == 0){ 
       var mouse = d3.mouse(this); 
       d3.select(this) 
         .attr('x', mouse[0]) 
         .attr('y', mouse[1]); 
      } 

     }); 
1

Um alle Zuhörer von Drag-Ereignis zu behandeln, können Sie den Code unten verwenden:

function dragChartStart() { 
    if(d3.event.sourceEvent.button !== 0) { 
     console.log("not left click"); 
     return; 
    } 
    console.log("dragStart"); 
} 

function dragChartEnd() { 
    if(d3.event.sourceEvent.button !== 0) { 
     console.log("not left click"); 
     return; 
    } 
    console.log("dragEnd"); 
} 

function dragChartMove() { 
    if(d3.event.sourceEvent.button !== 0) { 
     console.log("not left click"); 
     return; 
    } 
    console.log("dragMove"); 
} 

var dragBehavior = d3.behavior.drag() 
    .on("drag", dragChartMove) 
    .on("dragstart", dragChartStart) 
    .on("dragend", dragChartEnd); 
1

für D3 drag.filter([filter])

v4 zu sehen, ob Filter angegeben wird, setzt den Filter auf die angegebene Funktion und gibt das Ziehverhalten zurück. Wenn Filter nicht angegeben ist, wird der aktuelle Filter zurückgegeben, der standardmäßig verwendet wird.

drag.filter([filter]) 

für den Rechtsklick:

.filter(['touchstart'])

Filter verfügbar

mousedown-, mousemove-, mouseup, drag, selectstart, klicken Sie auf, Berührungsstart, Berührungsbewegungs, touchend, touchcancel

+0

Willkommen bei SO. Bitte lesen Sie [how-to-answer] (http://stackoverflow.com/help/how-to-answer). Einen Link hinzufügen ist nicht schlecht, aber möglicherweise nicht im Laufe der Zeit zugänglich. – thewaywewere

0

Eigentlich wi th verschiedene Version von d3 möchten Sie möglicherweise d3.event.which anstelle von d3.event.sourceEvent.which verwenden, um zu erkennen, auf welche Maustaste Sie geklickt haben.

Verwandte Themen