How to trigger click of both elements, when clicking overlapping area - javascript

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.com/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>

I 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 compute the intersection. Such approaches will eventually fail or simply become too complicated 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.org/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.com/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>

Related

How to reverse the order of svg elements

I am working with a svg element which is following
<svg class="layer1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150">
<rect class="bg" id="bg" width="150" height="150" fill="#e6e6e6"></rect>
<circle class="circ0" id="circ0" cx="75" cy="75" r="72" fill="none" stroke="blue" stroke-linecap="round" stroke-linejoin="round"></circle>
<circle class="circ1" id="circ1" cx="75" cy="75" r="69" fill="none" stroke="green" stroke-linecap="round" stroke-linejoin="round"></circle>
<circle class="circ2" id="circ2" cx="75" cy="75" r="66" fill="none" stroke="red" stroke-linecap="round" stroke-linejoin="round"></circle>
<script href="index.js"></script>
</svg>
I want to reverse the order of these circles with javascript, which I am currently doing by this way
const svg = document.querySelector("svg");
var x = document.querySelectorAll("[class^='circ']");
var bucket = [];
x.forEach((a, i) => {
bucket.push(a)
});
bucket.reverse();
x.forEach(
(a, i) => a.parentNode.removeChild(a)
);
bucket.forEach(
(a, i) => {
a.setAttribute("class", 'circ' + [i]);
a.setAttribute("id", "circ" + [i]);
svg.appendChild(a);
}
)
<svg class="layer1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150">
<rect class="bg" id="bg" width="150" height="150" fill="#e6e6e6"></rect>
<circle class="circ0" id="circ0" cx="75" cy="75" r="72" fill="none" stroke="blue" stroke-linecap="round" stroke-linejoin="round"></circle>
<circle class="circ1" id="circ1" cx="75" cy="75" r="69" fill="none" stroke="green" stroke-linecap="round" stroke-linejoin="round"></circle>
<circle class="circ2" id="circ2" cx="75" cy="75" r="66" fill="none" stroke="red" stroke-linecap="round" stroke-linejoin="round"></circle>
<script href="index.js"></script>
</svg>
It gives me this
Is there a better way of doing this?
append(child) by itself moves DOM Nodes. So your code can be simplified.
But for complexer SVG you probably want to swap DOM positions, because there could be other Elements in between you don't want to affect.
Hold CTRL key to see what happens with append
Click to see the swapping version,
a matter of processing an Array and swapping the first with the last element.
Note: append was not available in Internet Explorer, that is why you see most posts using appendChild.
Modern browsers have loads more DOM goodies: replaceWith after , before etc.
<svg viewBox="0 0 10 10" style="height:200px">
<style>
text { font-size: 2px }
[y="3"]{ fill:yellow }
.first { stroke: black; stroke-width: 0.5 }
</style>
<rect class="bg" id="bg" width="10" height="10" fill="grey"></rect>
<circle class="first" id="c0" cx="2" cy="5" r="2" fill="red" />
<text x="0" y="3">R</text>
<circle class="second" id="c1" cx="4" cy="5" r="3" fill="green" />
<text x="1" y="3">G</text>
<circle class="last" id="c2" cx="6" cy="5" r="4" fill="blue" />
<text x="2" y="3">B</text>
<text x="1" y="6">Click Me!</text>
</svg>
<script>
let svg = document.querySelector("svg");
function append() {
[...svg.querySelectorAll("circle")]
.reverse().forEach((c, i) => {
c.parentNode.append(c);
c.setAttribute("class", c.id = 'c' + i);
});
}
function swap() {
function swapElements(e1, e2) {
let {id,previousSibling,className:{baseVal:c2}} = e2;
e1.after(e2); // put e2 after e1
e2.id = e1.id; e2.setAttribute("class", e1.getAttribute("class"));
previousSibling.after(e1); // put e1 after where e2 WAS
e1.id = id; e1.setAttribute("class", c2);
}
let circles = [...svg.querySelectorAll("circle")];
while (circles.length) {
let c1 = circles.shift();
if (circles.length) swapElements(c1, circles.pop())
}
}
svg.onclick = (e) => (e.ctrlKey && append()) || swap();
</script>

How to increase stroke outside of svg path without using paint-order="stroke"?

I am facing a problem while increasing stroke width. When I am using the attribute paint-order="stroke" it's not meet my requirement, because stroke width increasing on both sides (inside and outside). Please look into the attached images.
original svg :-
Actual svg :-
Expected svg(Which is my requirement) :-
Code :-
<html>
<body>
<svg height="300" width="500">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="20" paint-order="stroke" fill="red" />
<circle cx="152" cy="50" r="40" stroke="black" stroke-width="20" paint-order="stroke" fill="none" />
<circle cx="252" cy="50" r="40" stroke="black" stroke-width="10" paint-order="stroke" fill="none" />
</svg>
</body>
</html>
A stroke with a width of 20px of a circle is symmetrically located on either side of the centerline. 10px outside, 10px inside the circle
The circle at the top has a smaller radius equal to half the stroke of the lower circle 40 - 10 = 30px
Therefore, the inside of the stroke of the lower, larger circle will be hidden. Only the outside of the large circle will be visible.
<html>
<body>
<svg height="300" width="500">
<!-- Sample circle without overlap -->
<circle cx="52" cy="50" r="40" stroke="black" stroke-width="20" paint-order="stroke" fill="none" /> >
<circle cx="152" cy="50" r="40" stroke="blue" stroke-width="20" paint-order="stroke" fill="none" />
<!-- The circle at the top has a smaller radius equal to half the stroke of the lower circle -->
<circle cx="152" cy="50" r="30" stroke="white" stroke-width="20" paint-order="stroke" fill="none" />
</svg>
</body>
</html>

Fill Percentage area in a custom Oval SVG image

I would like to fill a custom SVG to a specific percentage.
Here is my initial SVG
<svg width="202" height="195" viewBox="0 0 202 195" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.1" d="M96.8166 4.06964C16.0794 8.40606 -20.4645 94.8546 20.2957 157.019C54.6867 204.16 143.361 202.123 184.273 150.807C226.464 97.5789 163.505 0.38025 96.8166 4.06964Z" stroke="#313848" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Suppose there is a progress of x% so I would like to fill this SVG like
<svg width="207" height="203" viewBox="0 0 207 203" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.1" d="M99.8166 12.0696C19.0794 16.4061 -17.4645 102.855 23.2957 165.019C57.6867 212.16 146.361 210.123 187.273 158.807C229.464 105.579 166.505 8.38025 99.8166 12.0696Z" stroke="#313848" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M99.8142 12.0736C166.502 8.38527 229.463 105.585 187.273 158.812" stroke="#EA7052" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M96.1683 2.4287C88.1789 2.85671 84.5529 11.2658 88.579 17.3074C91.9765 21.8887 100.751 21.6836 104.805 16.6905C108.986 11.5113 102.768 2.06471 96.1683 2.4287Z" fill="#EDEDEE" stroke="#EA7052" stroke-width="4.76054" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M171.545 162.236C169.583 169.548 177.007 175.33 184.329 173.522C189.985 171.84 192.408 163.889 188.57 158.747C184.582 153.434 173.156 156.193 171.545 162.236Z" fill="#EDEDEE" stroke="#EA7052" stroke-width="4.76054" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
I am not able to figure out how to achieve this.
I want it to be dynamic so that I can make it for any percentage.
Also, I need to animate it from the starting point to the endpoint in a circular motion.
Any help would be highly appreciatable.
As I've commented:
You can calculate the length of the path using the getTotalLength() method. This represents 100%.
Next you can get the length representing the x% (xperc in the code).
Now you can use stroke-dasharray to represent the partial path.
You can calculate the position of the last point using the getPointAtLength() method.
Please read the comments in my code.
//the desired percentege
let xperc = .35;
//the total length of the path
let tl = base.getTotalLength();
//the partial length at the given percentage xperc
let partial = tl * xperc;
//set the stroke-dasharray of the second use element
perc.setAttribute("stroke-dasharray", `${partial} ${tl -partial}`)
//calculate the position of the point marking the end position
let theEnd = base.getPointAtLength(partial);
// set the cx and the cy attributes for the end point
end.setAttribute("cx", theEnd.x);
end.setAttribute("cy", theEnd.y);
circle {
stroke: red;
fill:white;
stroke-width: 6.87634;
}
<svg width="207" height="203" viewBox="0 0 207 203" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="base" d="M99.8166,12.0696L99.8166,12.0696C166.505,8.38025 229.464,105.579 187.273,158.807C146.361,210.123 57.6867,212.16 23.2957,165.019C-17.4645,102.855 19.0794,16.4061 99.8166,12.0696Z" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</defs>
<use xlink:href="#base" stroke="silver" />
<use xlink:href="#base" stroke="red" id="perc" />
<circle cx="99.8166" cy="12.0696" r="10" />
<circle id="end" r="10" />
</svg>
OBSERVATION: since your path goes counter clockwise I had to reverse the path to get the desired result
And this is an example where I'm using an input type range to change the percent value:
let xperc = itr.value;
onInput();
itr.addEventListener("input", onInput)
function onInput() {
xperc = itr.value;
let tl = base.getTotalLength();
let partial = tl * xperc;
perc.setAttribute("stroke-dasharray", `${partial} ${tl - partial}`);
let theEnd = base.getPointAtLength(partial);
end.setAttribute("cx", theEnd.x);
end.setAttribute("cy", theEnd.y);
}
circle {
stroke: red;
fill:white;
stroke-width: 6.87634;
}
<input id="itr" type="range" min="0" max="1" step=".001" value=".35" /><br>
<svg width="207" viewBox="-5 -5 220 220" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="base" d="M99.8166,12.0696L99.8166,12.0696C166.505,8.38025 229.464,105.579 187.273,158.807C146.361,210.123 57.6867,212.16 23.2957,165.019C-17.4645,102.855 19.0794,16.4061 99.8166,12.0696Z" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</defs>
<use xlink:href="#base" stroke="silver" />
<use xlink:href="#base" stroke="red" id="perc" />
<circle cx="99.8166" cy="12.0696" r="10" />
<circle id="end" r="10" />
</svg>
And another demo where I'm using javascript to animate it from 0 to 1:
//the animation begins at 0
let xperc = 0;
//get the total length of the path
let tl = base.getTotalLength();
//the request animation id
let rid = null;
function Animation() {
rid = window.requestAnimationFrame(Animation);
// while xperc < 1 increase it's value by 0.001. Else stop the animation
if (xperc < 1) {
xperc += 0.001;
}else{window.cancelAnimationFrame(rid)}
//the same as in the first example
let partial = tl * xperc;
perc.setAttribute("stroke-dasharray", `${partial} ${tl - partial}`);
let theEnd = base.getPointAtLength(partial);
end.setAttribute("cx", theEnd.x);
end.setAttribute("cy", theEnd.y);
}
Animation();
circle {
stroke: red;
fill:white;
stroke-width: 6.87634;
}
<svg width="207" viewBox="-5 -5 220 220" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="base" d="M99.8166,12.0696L99.8166,12.0696C166.505,8.38025 229.464,105.579 187.273,158.807C146.361,210.123 57.6867,212.16 23.2957,165.019C-17.4645,102.855 19.0794,16.4061 99.8166,12.0696Z" stroke-width="6.87634" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</defs>
<use xlink:href="#base" stroke="silver" />
<use xlink:href="#base" stroke="red" id="perc" />
<circle cx="99.8166" cy="12.0696" r="10" />
<circle id="end" r="10" />
</svg>

Add CSS styling to SVG

I have an SVG in which i want to add a particular styling to all circle having r="5"
<div class="svgchart">
<svg width="1190" height="390">
<circle class="bubble-plot-chart-circle" cx="400" cy="400" r="40" fill="blue"></circle>
<circle class="bubble-plot-chart-circle" cx="400" cy="400" r="5" fill="blue"></circle>
<circle class="bubble-plot-chart-circle " cx="400" cy="400" r="5" fill="blue"></circle>
</svg>
</div>
I have tried this but does not work
var allElements = document.getElementsByClassName("bubble-plot-chart-circle");
for(var i = 0; i < allElements.length; i++) {
var element = allElements[i];
if(element.getAttribute("r") === "5") {
// it takes the initial inline style which was applied at the time of crating the SVG
element.setAttribute("opacity", "0 !important");// does not work for SVG
element.addClass("test"); // does not work for SVG
}
}
can any one help me on this as i am new to SVG
Try this once:
I used querySelectorAll to get the filtered elements with provided class name and attribute.
var allElements = document.querySelectorAll(".bubble-plot-chart-circle[r='5']"); // filtering as required
for(var i = 0; i < allElements.length; i++) {
var element = allElements[i];
element.setAttribute("opacity", "0"); // !important is invalid in presentation attribute (check comment above)
element.classList.add("test"); // JavaScript's method instead of jquery's addClass method
}
and also addClass method is not available for JavaScript DOM object. It is available for jQuery object. If you want to use addClass method, convert the DOM object to jquery object as shown below:
var jqueryElement = $(element);
jqueryElement.addClass('test');
And also, you can do the same selection using CSS as well:
.bubble-plot-chart-circle[r='5'] {
/* SVG styles here */
}
Its working. See this. Use element.classList.add() instead:
window.onload = function(e) {
var allElements = document.getElementsByClassName("bubble-plot-chart-circle");
for (var i = 0; i < allElements.length; i++) {
var element = allElements[i];
if (element.getAttribute("r") === "5") {
element.classList.add("test");
}
}
}
.test {
opacity: 0.3 !important;
}
<div class="svgchart">
<svg width="1190" height="390">
<circle class="bubble-plot-chart-circle" cx="100" cy="100" r="40" fill="blue"></circle>
<circle class="bubble-plot-chart-circle" cx="100" cy="200" r="5" fill="blue"></circle>
<circle class="bubble-plot-chart-circle " cx="100" cy="300" r="5" fill="blue"></circle>
</svg>
</div>
Actually your code does work. What doesn't work, is your attribute.
I think you should look at https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity
This works in plunker:
<body>
<div class="svgchart">
<svg width="1190" height="390">
<circle class="bubble-plot-chart-circle" cx="400" cy="400" r="40" fill="blue"></circle>
<circle class="bubble-plot-chart-circle" cx="400" cy="400" r="5" fill="blue"></circle>
<circle class="bubble-plot-chart-circle " cx="400" cy="400" r="5" fill="blue"></circle>
</svg>
</div>
<script>
var allElements = document.getElementsByClassName("bubble-plot-chart-circle");
for(var i = 0; i < allElements.length; i++) {
var element = allElements[i];
element.setAttribute("fill-opacity", "0");
}
</script>
</body>
You can filter elements by attribute as you do. However, you need to wait till content is loaded.
A short D3 solution (since you have the d3js tag in your question), using selection and filter:
var circles = d3.selectAll("circle").filter(function(){
return d3.select(this).attr("r") == 5;});
And that's all you need: circles is a selection containing all the circles with a 5-pixel radius.
Once we have the proper selection, we can manipulate it the way we want. For instance, making all these circles moving to the right:
circles.transition().duration(1000).attr("transform", "translate(100,0)");
Here is a demo snippet:
var circles = d3.selectAll("circle").filter(function(){
return d3.select(this).attr("r") == 5;});
circles.transition().delay(500).duration(1000).attr("transform", "translate(100,0)");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="390" height="390">
<circle class="bubble-plot-chart-circle" cx="20" cy="40" r="40" fill="blue"></circle>
<circle class="bubble-plot-chart-circle" cx="100" cy="40" r="5" fill="blue"></circle>
<circle class="bubble-plot-chart-circle " cx="140" cy="40" r="5" fill="blue"></circle>
</svg>
This can be achive using d3.js. please find the answer below
var circle = d3.selectAll('.bubble-plot-chart-circle');
circle._groups.forEach(function(t){
t.forEach(function(e){
if(d3.select(e).attr("r") == 5){
d3.select(e).style('fill','red')
}})
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<div class="svgchart">
<svg width="500" height="310">
<circle class="bubble-plot-chart-circle" cx="400" cy="100" r="40" fill="blue"></circle>
<circle class="bubble-plot-chart-circle" cx="400" cy="200" r="5" fill="blue"></circle>
<circle class="bubble-plot-chart-circle " cx="400" cy="250" r="5" fill="blue"></circle>
</svg>
</div>
CSS makes this pretty easy.
circle[r="5"]{
fill: #f12222;
}
Codepen: http://codepen.io/daveycakes/pen/RGZVPv
Remember, these are html elements with attributes; it doesn't have to get so weird.

Changing colour using Javascript [duplicate]

I created a SVG file contains 5 polygons, then I need to embed Javascript so 4 of the polygons' color changes to Red when mouseover, and when mouseout, the color changes to Green. I tried to write the code but it didn't work, what could be the problem? Thanks for help and tips!
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="26cm" height="24cm" viewBox="0 0 2600 2400" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink= "http://www.w3.org/1999/xlink">
<script type="text/javascript">
<![CDATA[
document.getElementById("test").onmouseover = function(){changeColor()};
function changeColor() {
document.getElementById("test").style.color = "red";
}
document.getElementById("test").onmouseout = function(){changeColor()};
function changeColor() {
document.getElementById("test").style.color = "green";
}
]]>
</script>
<circle cx="1600" cy="700" r="600" fill="yellow" stroke="black" stroke-width="3"/>
<ellipse id="test" cx="1300" cy="500" rx="74" ry="120" fill="blue" stroke="black" stroke-width="3" onmouseover="javascript:red();" onmouseout="javascript:green();"/>
<ellipse id="test" cx="1850" cy="500" rx="74" ry="120" fill="blue" stroke="black" stroke-width="3" onmouseover="javascript:red();" onmouseout="javascript:green();"/>
<rect id="test" x="1510" y="650" width="160" height="160" fill="blue" stroke="black" stroke-width="3" onmouseover="javascript:red();" onmouseout="javascript:green();"/>
<polygon id="test" points="1320,800 1370,1080 1820,1080 1870,800 1820,1000 1370,1000" name="mouth" fill="blue" stroke="black" stroke-width="3" onmouseover="javascript:red();" onmouseout="javascript:green();"/>
</svg>
For what you are doing I would recommend using pure CSS.
Here is some working code.
svg:hover .recolor {
fill: red;
}
As you see, you can just use the :hover event in CSS to recolor the necessary elements. And set them to your default color (green), which will take effect when the user is not hovered.
You have various errors
you've two functions called changeColor, functions must have unique names
SVG does not use color to colour elements, instead it uses fill (and stroke).
id values must be unique, you probably want to replace id by class and then use getElementsByClassName instead of getElementById. If you do that you'll need to cope with more than one element though. I've not completed that part, you should try it yourself so you understand what's going on.
I've removed all but one id from my version so you can see it working on the left eye.
document.getElementById("test").onmouseover = function(){changeColor()};
function changeColor() {
document.getElementById("test").style.fill = "red";
}
document.getElementById("test").onmouseout = function(){changeColor2()};
function changeColor2() {
document.getElementById("test").style.fill = "green";
}
<svg width="26cm" height="24cm" viewBox="0 0 2600 2400" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink= "http://www.w3.org/1999/xlink">
<circle cx="1600" cy="700" r="600" fill="yellow" stroke="black" stroke-width="3"/>
<ellipse id="test" cx="1300" cy="500" rx="74" ry="120" fill="blue" stroke="black" stroke-width="3"/>
<ellipse cx="1850" cy="500" rx="74" ry="120" fill="blue" stroke="black" stroke-width="3" />
<rect x="1510" y="650" width="160" height="160" fill="blue" stroke="black" stroke-width="3" />
<polygon points="1320,800 1370,1080 1820,1080 1870,800 1820,1000 1370,1000" name="mouth" fill="blue" stroke="black" stroke-width="3"/>
</svg>

Categories