简体   繁体   中英

d3 count overlapping shapes at point

I have this basic drawing of ellipses: https://codepen.io/almn22/pen/zJrWrd

I am trying to make it so that when you mouse over an area, there is text output below that displays how many shapes are at that point. So in the example below, when you mouseover the darkest gray area, there should be a text display of "3".

For my real use case, the shapes are random with no predictable form so I can't count on them being ellipses or circles. I am plotting them as svg polygons using d3js. The data I have for the polygons is just the "points" attribute.

Any help would be greatly appreciated!

 <!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } ellipse { stroke: white; fill: lightgray; mix-blend-mode: multiply; } </style> </head> <body> <script> const svgContainer = d3.select("body") .append("svg") .attr("width","560") .attr("height","900").attr("translate", "45, 45"); const ellipses = [ {"cx": 145, "cy": 125, "rx": 88, "ry": 20}, {"cx": 175, "cy": 175, "rx": 88, "ry": 77}, {"cx": 225, "cy": 125, "rx": 88, "ry": 55}, {"cx": 275, "cy": 275, "rx": 88, "ry": 77} ]; const svgEllipses = svgContainer .selectAll("ellipse") .data(ellipses) .enter() .append("ellipse"); svgEllipses .attr("cx", (d,i) => { return d.cx; }) .attr("cy", (d,i) => { return d.cy; }) .attr("rx", (d,i) => { return d.rx; }) .attr("ry", (d,i) => { return d.ry; }); </script> </body> 

This is my solution to this question.

The main idea is that on click all the shapes are insensitive to the mouse. Also a counter n is started from 0. Then one by one every shape become sensitive to the mouse. If the mouse is inside the shape the counter n is is increasing by one: n++ .

I hope it helps.

 let m = {};// mouse let shapes = Array.from(document.querySelectorAll(".shape")); svg.addEventListener("click", e => { let n = 0;// a counter m = oMousePos(e);// thr mouse position on click shapes.map(s=>{ // all the shapes are insensitive to the mouse shapes.map(_s=>{_s.style.pointerEvents = "none";}) // this shape is the only one sensitive to the mouse in this moment s.style.pointerEvents = "all"; // detecting if the mouse is inside the shape let elmt = document.elementFromPoint(mx, my); // if it is and the element has className.baseVal == "shape" if(elmt.className.baseVal == "shape"){ //increase tho counter n++ }; }); //use the counter console.log(n); }); function oMousePos(evt) { return { x: evt.clientX, y: evt.clientY }; } 
 svg { border: 1px solid; display: block; margin: 0 auto; } .shape { mix-blend-mode: multiply; } 
 <svg id="svg" width="500" height="400" translate="45, 45"> <ellipse class="shape" cx="145" cy="125" rx="88" ry="20" fill="#aaa"></ellipse> <circle class="shape" cx="175" cy="175" r="88" fill="#bbb"></circle> <ellipse class="shape" cx="225" cy="125" rx="88" ry="55" fill="#ccc"></ellipse> <circle class="shape" cx="275" cy="275" r="77" fill="#ddd"></circle> </svg> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM