D3 souris sur les liens dans le diagramme nœud-lien, augmente la plage «acceptée»

Parfois, j'ai besoin d'afficher les bords dans les diagrammes de noeuds avec une très petite largeur de trame (<3px). Cela rend très difficile pour l'utilisateur de survoler.

J'utilise la fonction .on('mouseover', () => //do stuff) .

Existe-t-il un moyen simple d'augmenter le rayon qui déclencherait l'événement Mouseover? Disons que cela devrait toujours supposer que le bord a une largeur de course d'au moins 5px.

Je colorie les bords de façon dynamique, mais est-ce qu'il y a peut-être un moyen de définir la couleur du bord à quelque chose comme ça (voir le panneau gris comme bord, disposé horizontalement)

 transparent (2px) color (1px) transparent (2px) 

Donc, il a effectivement une taille de 5px, mais seulement 1px est visible?

Ou dois-je vraiment calculer si mon bord se chevauche avec ma souris manuellement? (C'est certainement possible, mais compte tenu du fait que certains bords sont courbés, d'autres non, … c'est vraiment un problème).

Existe-t-il un moyen simple d'augmenter le rayon qui déclencherait l'événement Mouseover?

Non, le gestionnaire d'événements est ajouté à l'élément, et si un élément étroit a une largeur de trait de 3px, la fonction ne fonctionnera que lorsque la souris est au-dessus de ces pixels.

Est-ce qu'il y a peut-être un moyen de définir la couleur du bord à quelque chose comme […] il a effectivement une taille de 5px, mais seulement 1px est visible?

C'est possible en utilisant un chemin et en combinant un remplissage coloré avec une course transparente. Cependant, une approche plus simple consiste à dupliquer la sélection, avec exactement les mêmes attributs, et à faire les meilleurs chemins ou lignes (par "haut", je veux dire la sélection qui vient plus tard dans le code) transparent et avec une plus grande largeur de trame.

Dans cette démo, par exemple, il existe des lignes transparentes de 20px, qui capturent l'événement mousemove , sur les lignes étroites visibles:

 //these lines are painted first var links = svg.selectAll("foo") .data(edges) .enter() .append("line") .style("stroke", "#ccc") .style("stroke-width", 1); //these transparent lines are painted on top, and they capture the mousemove var linksTransparent = svg.selectAll("foo") .data(edges) .enter() .append("line") .style("stroke", "none") .attr("pointer-events", "all") .style("stroke-width", 20) .on("mousemove", d => { console.log("source: " + d.source.id + ", target: " + d.target.id) }); 
 var width = 400; var height = 200; var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height); var nodes = [{ "id": "One" }, { "id": "Two" }, { "id": "Three" }, { "id": "Four" }]; var edges = [{ "source": 0, "target": 1 }, { "source": 0, "target": 2 }, { "source": 0, "target": 3 }]; var simulation = d3.forceSimulation() .force("link", d3.forceLink().distance(60)) .force("charge", d3.forceManyBody().strength(-200)) .force("center", d3.forceCenter(width / 2, height / 2)); var links = svg.selectAll("foo") .data(edges) .enter() .append("line") .style("stroke", "#ccc") .style("stroke-width", 1); var links2 = svg.selectAll("foo") .data(edges) .enter() .append("line") .style("stroke", "none") .attr("pointer-events", "all") .style("stroke-width", 20) .on("mousemove", d => { console.log("source: " + d.source.id + ", target: " + d.target.id) }); var color = d3.scaleOrdinal(d3.schemeCategory20); var node = svg.selectAll("foo") .data(nodes) .enter() .append("g") .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); var nodeCircle = node.append("circle") .attr("r", 10) .attr("stroke", "gray") .attr("fill", (d, i) => color(i)); var texts = node.append("text") .style("fill", "black") .attr("dx", 20) .attr("dy", 8) .text(function(d) { return d.id; }); simulation.nodes(nodes); simulation.force("link") .links(edges); simulation.on("tick", function() { links.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); links2.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("transform", (d) => "translate(" + dx + "," + dy + ")") }); function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = dx; d.fy = dy; } function dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } 
 <script src="https://d3js.org/d3.v4.min.js"></script>