I have two elements overlapping each other, Both has click events. Clicking on each element works fine.
If I click on an overlapping area as shown below, can I trigger the click of both?
Below is my code
$("#circle1").click(function(d) {
alert("circle1");
});
$("#circle2").click(function(d) {
alert("circle2");
});
.path {
fill: red;
}
<script src=".3.1/jquery.min.js"></script>
<svg width="525" height="226">
<circle id="circle1" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
<circle id="circle2" cx="80" cy="50" r="40" stroke="black" stroke-width="3" fill="transparent" />
</svg>
I have two elements overlapping each other, Both has click events. Clicking on each element works fine.
If I click on an overlapping area as shown below, can I trigger the click of both?
Below is my code
$("#circle1").click(function(d) {
alert("circle1");
});
$("#circle2").click(function(d) {
alert("circle2");
});
.path {
fill: red;
}
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg width="525" height="226">
<circle id="circle1" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
<circle id="circle2" cx="80" cy="50" r="40" stroke="black" stroke-width="3" fill="transparent" />
</svg>
Share
Improve this question
edited Jan 14, 2020 at 9:54
Reza Paidar
8835 gold badges21 silver badges52 bronze badges
asked Dec 19, 2019 at 8:27
ozilozil
7,1459 gold badges36 silver badges61 bronze badges
1
-
If you have some way of determining that click was on the mon area you can simply call
$( "#circle2" ).trigger( "click" );
This is not the right way, but just an idea on the top of my head – M Usama Alvi Commented Dec 19, 2019 at 8:29
3 Answers
Reset to default 4I would use clip-path to get the intersection of the 2 circles. Then I would attach the event to intersection.
intersection.addEventListener("click",()=>{
console.log("intersection")
})
circle{stroke-width:3;stroke:black;}
svg{border:1px solid}
<svg id="svg" viewBox="0 0 525 226">
<defs>
<circle id="circle1" cx="50" cy="50" r="40" />
<circle id="circle2" cx="80" cy="50" r="40" />
<clipPath id="clip"><use xlink:href="#circle2" />
</clipPath>
</defs>
<use xlink:href="#circle1" class="circle" fill="red" />
<use xlink:href="#circle2" class="circle" fill="transparent" />
<use xlink:href="#circle1" id="intersection" clip-path="url(#clip)" fill="gold" />
</svg>
You should not rely on any approach that calculates the position of the intersection or that creates another element just to pute the intersection. Such approaches will eventually fail or simply bee too plicated and cumbersome.
Instead of that, use the event itself and a method like document.elementFromPoint
to get all elements under the click. For instance, you can use document.elementFromPoint
“recursively”, as described here. Then, using selection.dispatch
, you dispatch the click event to all elements under the click.
Here is a very basic demo (click on the blue circle, the red circle or the intersection):
let clicked;
d3.select(".blue").on("click", function() {
if (!clicked) return;
console.log("blue circle were clicked")
});
d3.select(".red").on("click", function() {
if (!clicked) return;
console.log("red circle were clicked")
});
d3.select("svg").on("click", function() {
clicked = true;
getAllElements(...d3.mouse(this));
clicked = false;
function getAllElements(x, y) {
const elements = [];
let thisElement = document.elementFromPoint(x, y);
while (thisElement && thisElement.nearestViewportElement) {
elements.push(thisElement);
d3.select(thisElement).style("display", "none");
thisElement = document.elementFromPoint(x, y);
}
elements.forEach(function(elm) {
d3.select(elm).style("display", null)
.dispatch("click");
});
};
})
.as-console-wrapper {
max-height: 30% !important;
}
<script src="https://d3js/d3.v5.min.js"></script>
<svg>
<circle cx="100" cy="75" r="60" fill="powderblue" stroke="gray" stroke-width="2" opacity="0.75" class="blue"></circle>
<circle cx="170" cy="75" r="60" fill="tomato" stroke="gray" stroke-width="2" opacity="0.75" class="red"></circle>
</svg>
Here is how you can calculate the overlap area calculate clientX
for each click event
and make sure it is overlap area as you have already provide X
and Y
for your circles
. Here is example. In example, I have provided a rough idea you can calculate according to your actual dimesions.
$(".circle").click(function(e) {
if((event.clientX>50 && event.clientX<80) && (event.clientY>25 && event.clientY<85)){
alert('overlaper area');
}
});
.path {
fill: red;
}
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<svg width="525" height="226">
<circle class="circle" id="circle1" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
<circle class="circle" id="circle2" cx="80" cy="50" r="40" stroke="black" stroke-width="3" fill="transparent" />
</svg>