2016-05-20 11 views
2

Ich versuche Mausereignisse zu erhalten, um zwischen verschiedenen Elementen in einem Streudiagramm zusammenzuarbeiten. Die Komponente brush von D3 fügt dem aufgerufenen Element einige Listener hinzu (z. B. svg.call(brush)). Ich möchte auch Punkte anzeigen, die an das SVG gebunden sind, ähnlich wie ein Streudiagramm, und für diese Punkte, um mouseover Ereignisse zu unterstützen (für Tooltips und andere Interaktionen).Getting Point Mausinteraktion und Pinsel zusammenarbeiten

Eine previous solution schlägt vor dem Aufrufen des Pinsels das Zeichnen von Punkten vor, die Mouseover auf Punkten unterstützt, während der Pinsel gezeichnet und der Umfang geändert werden kann. Wenn die Ziehbewegung für den Pinsel jedoch an einem Punkt beginnt (was ich bei sehr dichten Diagrammen erwarte), verhält sich die Pinselkomponente fehlerhaft, wenn bereits ein Extent aktiv ist (beim Umsetzen des Pinsels wird stattdessen die Ausdehnung geändert). Sie können es unter this example ausprobieren, wo die oben vorgeschlagene Lösung implementiert wurde.

Failed solution example

Ich habe das Problem verringert, wie das Ereignis brushstart() Funktion, die in d3 im Innern der d3.svg.brush Komponente behandelt wird. Hier sehen Sie, wie relevante Variablen aussehen, wenn der Pinsel korrekt arbeitet.

     this   eventTarget       dragging resizing 
        -------------- ------------------------------------- ---------- ---------- 
Translating extent brush parent rect.extent       true  0   
Resizing extent  brush parent rect (invisible rects for resizing) false  e.g. "e" 
Redrawing   brush parent rect.background      false  0   

Dies ist, wie es zur Zeit aussieht, mit der Lösung oben:

     this   eventTarget dragging resizing   
-------------------- -------------- ------------- ---------- ---------------- 
Translating extent brush parent circle  false  circle.datum() 
Resizing extent  brush parent circle  false  circle.datum() 
Redrawing   brush parent circle  false  circle.datum() 

Die eigentliche Frage ist: Wie kann ich die Quelle von d3.event.target frisieren die erste Tabelle übereinstimmen? Wenn ich das kann, kann ich das Verhalten bekommen, das ich möchte. Danke für jede Hilfe!

Wenn Sie es verpasst haben, hier ist ein bl.ock dieses Rätsels in Aktion: http://bl.ocks.org/yelper/d38ddf461a0175ebd927946d15140947

+0

Im Falle eines leeren Pinsel auf einem Kreis gestartet man könnte so etwas wie dies gerade tun: http://blockbuilder.org/larsenmtl/2862c433899f63456f5279e4a6281f5e, behebt nicht den Umzug begann jedoch aus einem Kreis. – Mark

Antwort

2

ist hier ein schneller Hack, die das Verhalten korrigiert:

.on('mousedown', function(d){ 
    var e = brush.extent(), 
     m = d3.mouse(svg.node()), // pointer position with respect to g 
     p = [x.invert(m[0]), y.invert(m[1])]; // position in user space 

    if (brush.empty() || // if there is no brush 
     (e[0][0] > d[0] || d[0] > e[1][0] 
     || e[0][1] > d[1] || d[1] > e[1][1]) // or our current circle is outside the bounds of the brush 
) { 
    brush.extent([p,p]); // set brush to current position 
    } else { 
    d3.select(this).classed('extent', true); // else we are moving the brush, so fool d3 (I got this from looking at source code, it's how d3 determines a drag) 
    } 
}); 

Arbeits Code unten, aktualisiert Block here.

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> 
 
    .axis path, 
 
    .axis line { 
 
     fill: none; 
 
     stroke: #000; 
 
     shape-rendering: crispEdges; 
 
    } 
 
    
 
    .hidden { 
 
     opacity: 0.3; 
 
    } 
 
    
 
    
 
    .extent { 
 
     fill: #000; 
 
     fill-opacity: .125; 
 
     stroke: #fff; 
 
    } 
 
</style> 
 
<body> 
 
<script src="//d3js.org/d3.v3.js"></script> 
 
<script> 
 
    
 
var margin = {top: 20, right: 50, bottom: 30, left: 50}, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 350 - margin.top - margin.bottom; 
 
    
 
var x = d3.scale.linear() 
 
    .range([0, width]) 
 
    .domain([0, 10]); 
 
    
 
var y = d3.scale.linear() 
 
    .range([height, 0]) 
 
    .domain([0, 10]); 
 
    
 
var xAxis = d3.svg.axis() 
 
    .scale(x) 
 
    .orient("bottom"); 
 

 
var yAxis = d3.svg.axis() 
 
    .scale(y) 
 
    .orient("left"); 
 
    
 
var curPt = d3.select('body') 
 
    .append('p') 
 
    .html("Current point: ") 
 
    .append('span') 
 
     .attr('id', 'curPt'); 
 
    
 
var svg = d3.select('body').insert('svg', 'p') 
 
    .attr('width', width + margin.left + margin.right) 
 
    .attr('height', height + margin.top + margin.bottom) 
 
    .append('g') 
 
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); 
 
    
 
svg.append('g') 
 
    .attr('class', 'x axis') 
 
    .attr('transform', 'translate(0,'+height+')') 
 
    .call(xAxis); 
 
    
 
svg.append('g') 
 
    .attr('class', 'y axis') 
 
    .call(yAxis); 
 
    
 
var brush = d3.svg.brush() 
 
    .x(x) 
 
    .y(y) 
 
    .on("brush", function() { 
 
     var e = brush.extent(), 
 
     \t c = svg.selectAll('circle'); 
 
     \t c.classed('extent', false); 
 
     c.classed('hidden', function(d) { 
 
      return e[0][0] > d[0] || d[0] > e[1][0] 
 
       || e[0][1] > d[1] || d[1] > e[1][1]; 
 
      } 
 
     ); 
 
    }) 
 
    .on("brushend", function() { 
 
     if (brush.empty()) svg.selectAll('circle').classed('hidden', false); 
 
    }); 
 
    
 
svg.call(brush); 
 
    
 
var data = d3.range(50).map(function() { return [Math.random() * 10, Math.random() * 10]; }); 
 

 
svg.append('g') 
 
    .attr('class', 'points') 
 
    .selectAll('circle') 
 
    .data(data).enter() 
 
    .append('circle') 
 
    .attr('cx', function(d) { return x(d[0]); }) 
 
    .attr('cy', function(d) { return y(d[1]); }) 
 
    .attr('r', 10) 
 
    .style('fill', 'steelblue') 
 
    .on('mouseover', function(d) { 
 
     curPt.html("[" + d[0] + ", " + d[1] + "]"); 
 
    }) 
 
    .on('mouseout', function(d) { 
 
     curPt.html(""); 
 
    }) 
 
\t \t .on('mousedown', function(d){ 
 
    \t \t var e = brush.extent(), 
 
      m = d3.mouse(svg.node()), 
 
      p = [x.invert(m[0]), y.invert(m[1])]; 
 
     
 
     if (brush.empty() || 
 
      (e[0][0] > d[0] || d[0] > e[1][0] 
 
      || e[0][1] > d[1] || d[1] > e[1][1]) 
 
    ) { 
 
     brush.extent([p,p]); 
 
     } else { 
 
     d3.select(this).classed('extent', true); 
 
     } 
 
    }); 
 

 
    
 
</script>

+0

Super, danke für die Hilfe! Das ist definitiv das Verhalten, das ich will. Ich begann dieses Wochenende eine andere Straße zu gehen, endete mit so etwas wie dieser Block, aber es erfordert zwei Klicks auf einen Punkt zu arbeiten: https: //bl.ocks.org/yelper/dc2bbff489dbf0820ccf8d73537f071c ... Ich wäre neugierig, was in diesem Beispiel fehlt, damit es funktioniert. – yelper

+1

@ yelper, Ihr Ansatz sieht gut aus, aber es scheint nicht so, als würde "d3" Ihr erneut gesendetes mousedown-Ereignis aufnehmen. Ich habe versucht, das 'd3.event' zu verwenden und es an den' rect.background' zu senden (anstatt ein neues Ereignis zu erstellen), aber das funktioniert auch nicht .... – Mark

0

Hier ist die Arbeitsbeispiel: https://jsfiddle.net/paradite/rpqusqdc/2/

Im Grunde habe ich meine bisher Auswahlwerkzeug codiert Bereich drag mit Ereignis statt brush: http://bl.ocks.org/paradite/71869a0f30592ade5246

Es stört nicht mit Ihren Kreisen. Sie müssen also nur die aktuellen rect Dimensionen zu erhalten und Ihre Kreise entsprechend aktualisieren:

// select your points here 
    var e = selectionRect.getCurrentAttributes(); 
    svg.selectAll('circle').classed('hidden', function(d) { 
    return e.x1 > x(d[0]) || x(d[0]) > e.x2 || e.y1 > y(d[1]) || y(d[1]) > e.y2; 
    }); 

Natürlich kann man Teile seiner Logik entfernen kann es so viel ist nicht erforderlich, für Ihren Fall.

+0

Danke für Ihre Antwort! Es sieht jedoch nicht so aus, als würde man über Punkte innerhalb des Rechtecks ​​schweben, und man kann das Rechteck nicht ziehen (übersetzen). – yelper

+0

Ich habe das 'mouseover'-Problem behoben, das' drag'-Feature ist etwas, das mein Code nicht implementiert. Wenn Sie es brauchen, können Sie vielleicht versuchen, es zu codieren? – paradite

Verwandte Themen