Find centre of svg path elements - javascript

Hello I am fairly new with svg and JavaScript and I am trying to make some svg elements popup (by scaling) when the mouse is over the svg and vice versa when the mouse is off the svg element.
I have been able to make the svg element increase in size by using transformation, but is there a way that they scale from their center's?
Here is my svg (I created it using this website svg-edit):
// event-driven mouse-interaction with SVG objects
function unselected_colour(evt) {
// get the element that triggered the browser event
let target = evt.target;
// modify the element
target.setAttribute('transform', 'scale(1)')
}
function selected_colour(evt) {
// get the element that triggered the browser event
let target = evt.target;
// modify the element
target.setAttribute('transform', 'scale(1.25)')
}
// find the SVG rectangle in the DOM
let mileEndRoad_obj = document.getElementById('mile_end_road');
let bandcroftRoad_obj = document.getElementById('bandcroft_road');
let godwardSquare_obj = document.getElementById('godward_sqaure');
let compSci_obj = document.getElementById('computer_science');
let itl_obj = document.getElementById('itl');
let engineering_obj = document.getElementById('engineering');
let peoplePalace_obj = document.getElementById('people_palace');
// pass the above functions as callbacks, to be triggered by mouse events
godwardSquare_obj.addEventListener('mouseover', selected_colour, false);
godwardSquare_obj.addEventListener('mouseout', unselected_colour, false);
compSci_obj.addEventListener('mouseover', selected_colour, false);
compSci_obj.addEventListener('mouseout', unselected_colour, false);
itl_obj.addEventListener('mouseover', selected_colour, false);
itl_obj.addEventListener('mouseout', unselected_colour, false);
engineering_obj.addEventListener('mouseover', selected_colour, false);
engineering_obj.addEventListener('mouseout', unselected_colour, false);
peoplePalace_obj.addEventListener('mouseover', selected_colour, false);
peoplePalace_obj.addEventListener('mouseout', unselected_colour, false);
<svg width="1640" height="480" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<!-- Created with SVG-edit - https://github.com/SVG-Edit/svgedit-->
<g class="layer">
<title>map</title>
<path d="m38,86.66667l0,94l64.66666,0l0.00001,-28l8.66666,0l0,27.33333l35.33334,0l-11.33334,-20l-12.66666,0l-0.00001,-8c8,0 12.66667,0 12.66667,0c0,0 -0.66667,-65.33333 0,-65.33333c0.66667,0 -89.33333,0 -97.33333,0z"
fill="rgb(94,43,126)" id="computer_science" stroke="#000000" stroke-width="5"/>
<rect fill="#10a3a3" height="447.44527" id="bandcroft_road" stroke="#10a3a3" stroke-width="5" width="35.76642" x="308.90512" y="-24.52553"/>
<rect fill="#10a3a3" height="54.74453" id="mile_end_road" stroke="#10a3a3" stroke-width="5" width="647.44528" x="-1.31387" y="425.10952"/>
<path d="m239.41174,257.50001l-133.52938,-0.14706l-0.00001,-69.85294l50.7353,-0.00001l-16.17647,-31.61765l58.82353,0l0,30.14706l39.70588,0l0.44115,71.4706z"
fill="#1bd1a6" id="godward_sqaure" stroke="#1bd1a6" stroke-width="5"/>
<rect fill="rgb(94,43,126)" height="100.5" id="itl" stroke="#000000" stroke-width="5" width="65" x="37" y="192"/>
<path d="m174.99947,274.5c-0.33149,41.16667 0.33149,82.83333 0,124l290.39161,0l0,-11.5l69.138332,0l0,-37l-68.641082,0l0,-142.5l-101.93541,0l0,167.5l-73.09515,0l0,-101l-115.8583,0.5z"
fill="rgb(94,43,126)" id="engineering" stroke="#000000" stroke-width="5"/>
<path d="m534.99996,206.029419l70.147082,-0.147072c0,0 0.441155,35.441191 -0.294139,34.705896c-0.735294,-0.735294 33.088235,0.000001 32.64708,-0.147072c-0.441155,-0.147073 0.441156,39.852955 0,39.705882c-0.441155,-0.147073 -18.676491,0.147074 -19.117647,0c-0.441156,-0.147073 0.441155,116.323546 0,116.176471c-0.441155,-0.147076 -82.647081,0.882369 -83.088235,0.735294c-0.441154,-0.147076 -0.294141,-191.764693 -0.294141,-191.029399z"
fill="rgb(94,43,126)" id="people_palace" stroke="#000000" stroke-width="5"/>
</g>
</svg>
If any further explanation please let me know.
Any help would be appreciated, thank you very much.

You can find the center with getBBox
https://developer.mozilla.org/en-US/docs/Web/API/SVGGraphicsElement/getBBox
Then scale with a matrix
how to use a svg matrix transform to scale only not to translate (implicite)?

Related

Filling an existing svg rectangle with text

I'm trying to use JavaScript to create an SVG rectangle with text in it. I've already got the rectangle (generated by morris.js, a charting library) but can't seem to be able to get the text in.
The output I want to achieve would look a bit like this:
<svg>
<g>
<rect x="0" y="0" width="100" height="100" fill="red"></rect>
<text x="0" y="50" font-family="Verdana" font-size="35" fill="blue">Hello</text>
</g>
</svg>
This is my code now (snippet will not run because rectangleElement is undefined here):
console.log(rectangleElement);
/* output:
<rect x="1205.5019308035712" y="0" width="193.5206919642857" height="307" r="0" rx="0" ry="0" fill="#E5E5E5" stroke="none" fill-opacity="0.8" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0); fill-opacity: 0;"></rect>
*/
var t = document.createElementNS('http://www.w3.org/2000/svg', 'text');
var g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
g.appendChild(t);
g.appendChild(rectangleElement);
console.log(g);
/* output:
<g><text></text></g>
*/
As you can see, the rectangleElement isn't being added to my group (g). I'm also not getting any errors in the console when trying to append the rectangle to the group.
Any ideas on what I could be doing wrong?
I ended up fixing it myself. I'm not at all sure what the issue was, when I added the seemingly unrelated code below, it started working.
var txtElem = document.createElementNS("http://www.w3.org/2000/svg", "text");
txtElem.setAttributeNS(null,"x",20);
txtElem.setAttributeNS(null,"y",40);
var theText = "text";
var theMSG = document.createTextNode(theText);
txtElem.appendChild(theMSG);

add SVGs inside an SVG programmatically

I need to add SVG objects to specific locations inside an SVG object that's appended to the DOM.
But whenever I do that I see nothing rendered on the screen. I can see the SVG objects are added (in Elements tab of DevTools) but they're not rendered. They're pure SVG (not wrapped around an HTML element like a DIV).
I've tried loading SVGs with ajax and adding them, tried to do with Snap, tried to have these elements inside a <defs> tag, find them with Snap and then add them to the main Snap object. Nothing seems to work. The objects are always added but not rendered.
Is that even possible?
The SVG
<svg width="400" height="300" style="background: gray">
<defs>
<circle id="redc" cx="50" cy="50" r="50" style="fill: red" />
<circle id="yelc" cx="40" cy="40" r="40" style="fill: yellow" />
</defs>
<circle id="bluc" cx="200" cy="200" r="50" style="fill: blue" />
</svg>
JavaScript
const s = Snap("#root");
Snap.load('images/all.svg', function(data){
var all = data;
// append the all.svg node. cool
s.append( all.node );
// get the red circle definition
var redc = all.select('#redc');
s.append(redc.node); // doesn't work
});
with foreign object:
Snap.load('images/all.svg', function(data){
var all = data;
// append the all.svg node. cool
s.append( all.node );
// get the red circle definition
var redc = all.select('#redc');
// foreign object
var foreign = document.createElementNS('http://www.w3.org/2000/svg',"foreignObject");
foreign.setAttribute('width', 500);
foreign.setAttribute('height', 150);
foreign.appendChild(redc);
// add the foreign object - doesn't work
s.append( foreign );
});
It doesn't work because you're appending the circle outside of the <svg> tree i.e. directly under #root which is probably some kind of HTML element such as a <div>
The foreignObject problem is basically the same. Not sure why you're trying to add a circle as a child of a foreignObject (that won't work as you'd need an svg element to be its parent). I've used an html element instead.
const s = Snap("#root");
var svg = '<svg width="400" height="300" style="background: gray"><defs><circle id="redc" cx="50" cy="50" r="50" style="fill: red" /><circle id="yelc" cx="40" cy="40" r="40" style="fill: yellow" /></defs><circle id="bluc" cx="200" cy="200" r="50" style="fill: blue" /></svg>';
var all = Snap.parse(svg);
// append the all.svg node. cool
s.append( all.node );
// get the red circle definition
var redc = all.select('#redc');
all.node.append(redc.node); // append as a child of the svg node
// foreign object
var foreign = document.createElementNS('http://www.w3.org/2000/svg',"foreignObject");
foreign.setAttribute('width', 500);
foreign.setAttribute('height', 150);
foreign.setAttribute('fill', 'pink');
var p = document.createElement('p');
foreign.appendChild(p);
var text = document.createTextNode("Hello World");
p.appendChild(text);
// add the foreign object to the correct part of the tree
all.node.append( foreign );
<script src="http://snapsvg.io/assets/js/snap.svg-min.js"></script>
<div id="root"></div>

need to set value for r(radius) in the <circle> tag using javascript

I have a scatter plot with line created using D3.js (as shown in the image).
The initial value to the circle radius is set to 4 however, when mouseover or click event are fired on the circle it should become 6 (r=6).
Whereas I am able to achieve this in chrome as following:
document.getElementById('dotGain' + count).style.r = 6;
the same doesn't work in IE.
The HTML created as dom is:
<circle xmlns="http://www.w3.org/2000/svg" class="dotGain" id="dotGain51" style="cursor: pointer; fill: red;" cx="440.621" cy="3.78507" r="4" />
I need to modify the r="4" to "6" on click/mouseOver in IE.
Some added help:
I tried the following to achieve the required in IE, but in vain
document.getElementById('dotGain' + count).r.animVal.valueAsString = "6";
document.getElementById('dotGain' + count).r.animVal.value = 6;
You should be changing the r attribute, not the style; and this is wrong: document.getElementById('#MyCircle') because you have a hashtag in the id name.
See a working example here:
var c = document.getElementById('c');
c.addEventListener('click', function(){
c.setAttribute('r', 6);
})
Click the circle
<svg viewBox="0 0 120 120" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<circle cx="10" cy="10" r="4" id="c"/>
</svg>
r is a element attribute. To change it You can use jQuery
$(el).attr('r', 6)
or in vanilla js
el.setAttribute('r', 6);

how to scale the element created by use by keeping the fixed position in svg

I want to scale the element created by use by keeping the fixed position in svg.
I read this
but my element is created by use
so it shows
Simply I can remove the old one and create a new one ,but I feel this a bit trouble.
So I wonder whether it exists any convenient way?
function tableBindMouseClick(parametersObject)
{
var table = document.getElementById("PointsTable");
var length = $('#PointsTable tbody tr').length;//get table rows number
for(var i =0;i<length;i++)
{
var id = i;
$($('#PointsTable tbody tr')[i]).bind('click',
(function(id)
{
return function()
{
var p = parametersObject.pointArray[id];
var x = p[0] -5;//coordinate x
var y = p[1] -5;//coordinate y
var icon = document.getElementById("point"+id);
icon.setAttributeNS(null, "transform", "translate("+-x+"," + -y +") scale(3) translate("+x+","+y+")");
};
})(id));
}
I do not know whether it is enough.
I am still modifying it.It can run but its effect is still incorrect.
The result
I can not see the error...
PS:Unfortunately,I use the defs element instead of symbol element to create icon.I also want to know difference in them,including g element.
I complete it by this parameters:
icon.setAttributeNS(null, "transform", "translate("+-2*x+"," + -2*y +")" + " scale(3)" );
I think the post makes some mistakes...
This example may make sense.
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Scalable Vector Graphics (SVG) 1.1 (Second Edition)</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" width="5000" height="5000" viewBox="0 0 5000 5000">
<rect x="100" y="100" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"/>
<rect x="100" y="100" width="30" height="30" stroke="black" fill="transparent" stroke-width="5"
transform ="translate(-230,-230 ) scale(3)" />
</svg>
</body>
</html>

How to add an animated svg via javascript?

<svg width="5cm" height="3cm" viewBox="0 0 500 300">
<path id="path1" d="M100,250 C 100,50 400,50 400,250"
fill="none" stroke="blue" stroke-width="7.06" />
<circle r="17.64" fill="red">
<animateMotion dur="6s" repeatCount="1" rotate="auto" >
<mpath xlink:href="#path1"/>
</animateMotion>
</circle>
</svg>
If I write the svg in plain html/svg file, it works fine, the circle animates correctly.
But if I add the circle element dynamically via javascript, circle was added, but it didn't animate. What's wrong? js code:
var svg = $("svg"); //use jquery
var circle = document.createElementNS("http://www.w3.org/2000/svg","circle");
circle.setAttribute("r", "5");
circle.setAttribute("fill", "red");
var ani = document.createElementNS("http://www.w3.org/2000/svg","animateMotion");
ani.setAttribute("dur", "26s");
ani.setAttribute("repeatCount", "indefinite");
ani.setAttribute("rotate", "auto");
var mpath = document.createElementNS("http://www.w3.org/2000/svg","mpath");
mpath.setAttribute("xlink:href", "#path1");
ani.appendChild(mpath);
circle.appendChild(ani);
svg.append(circle);
Use setAttributeNS on "mpath" instead of setAttribute.
mpath.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#path1");
Here's a demo: http://jsfiddle.net/zh553/
Agree with using setAttributeNS on "mpath" instead of setAttribute.
However at least for Chrome (and other WebKit based browsers?) it seems to be necessary to pay attention to http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-ElSetAttrNS where it says the second parameter is the qualifiedName, the qualified name of the attribute to create or alter.
mpath.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#path1");
Or, if needed, more generically:
mpath.setAttributeNS("http://www.w3.org/1999/xlink",
mpath.lookupPrefix("http://www.w3.org/1999/xlink") + ":href",
"#path1");
Also discussed at https://bugs.webkit.org/show_bug.cgi?id=22958

Categories