SVG to Shape (EaselJS) - javascript

In EaselJS only shapes can became a masks, so I was wondering if I can convert somehow SVG made in Inkscape into EaselJS, I found this great tool - http://www.professorcloud.com/svg-to-canvas/ that allows me to convert SVG to Context, but is there a way/tool to easily convert SVG to EaselJS Shape (this is almost the same object as Shape in Flash/AS3)? I need only a basic shape like this:
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="776.4032"
height="405.87927"
id="svg1383">
<defs
id="defs1385" />
<metadata
id="metadata1388">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(15.455332,-13.016229)"
id="layer1">
<path
d="m 1193.5963,82.437378 a 369.81683,206.47517 0 1 1 -739.63371,0 A 369.81683,206.47517 0 1 1 1193.5963,82.437378 Z"
transform="matrix(1.0497132,0,0,0.98287671,-491.98585,134.93009)"
id="mask"
style="fill:#008000;fill-opacity:1;stroke:none;display:inline" />
</g>
<g
transform="translate(15.455332,-13.016229)"
id="layer2" />
</svg>

After you generate your js code on webpage you gave, you can override function in shape called draw. Just paste generated code in your function and you should be able to see your image.
Example code:
var s = new createjs.Shape();
// this is important because if we dont change graphics our overriden
// function wont be called.
s.graphics.beginFill("#FF0000").rect(0, 0, 75, 100);
//save old draw function
var oldDraw = s.draw;
// here we switch draw funciton to the one generated from svg file
s.draw = this.draw;
// draw our model on cache
s.cache(0, 0, 66, 113, 2);
// and now we can back to old drawing function
s.draw = oldDraw;

Related

Import external SVG file contents as a javascript variable/object

I have an external SVG file which contains the following SVG definition:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 150" ><path class="st0" fill="#FFFFFF" d="M50,145.5C40.6,131.6,2.5,73.4,2.5,50C2.5,23.8,23.8,2.5,50,2.5S97.5,23.8,97.5,50C97.5,73.4,59.4,131.6,50,145.5z"/><path class="st1" fill="#000000" d="m50 5c24.8 0 45 20.2 45 45 0 19.5-29.4 67.7-45 91.1-15.6-23.4-45-71.6-45-91.1 0-24.8 20.2-45 45-45m0-5c-27.6 0-50 22.4-50 50s50 100 50 100 50-72.4 50-100-22.4-50-50-50z"/><circle fill="#ffbf00" cx="50" cy="50" r="27.5"/><path d="m50 25c13.8 0 25 11.2 25 25s-11.2 25-25 25-25-11.2-25-25 11.2-25 25-25m0-5c-16.6 0-30 13.4-30 30s13.4 30 30 30 30-13.4 30-30-13.4-30-30-30z"/></svg>
The SVG has multiple paths, so for me to be able to change colours of individual paths I need to be able to load the SVG file contents into a Javascript variable like this:
var svgSource = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 150" ><path class="st0" fill="#FFFFFF" d="M50,145.5C40.6,131.6,2.5,73.4,2.5,50C2.5,23.8,23.8,2.5,50,2.5S97.5,23.8,97.5,50C97.5,73.4,59.4,131.6,50,145.5z"/><path class="st1" fill="#000000" d="m50 5c24.8 0 45 20.2 45 45 0 19.5-29.4 67.7-45 91.1-15.6-23.4-45-71.6-45-91.1 0-24.8 20.2-45 45-45m0-5c-27.6 0-50 22.4-50 50s50 100 50 100 50-72.4 50-100-22.4-50-50-50z"/><circle fill="#ffbf00" cx="50" cy="50" r="27.5"/><path d="m50 25c13.8 0 25 11.2 25 25s-11.2 25-25 25-25-11.2-25-25 11.2-25 25-25m0-5c-16.6 0-30 13.4-30 30s13.4 30 30 30 30-13.4 30-30-13.4-30-30-30z"/></svg>';
Then I can use conditional statements to alter the colours e.g.
switch(centerId) {
case 1:
svgSource = svgSource.replace("#ffbf00", "#005D00");
break;
case 2:
svgSource = svgSource.replace("#ffbf00", "#A20000");
break;
case 3:
svgSource = svgSource.replace("#ffbf00", "#ffbf00");
break;
}
I could define and use the inline SVG code hard coded into the Javascript as shown, but for maintenance and continuity it would be much better to use existing, centralised, external SVG files.
How can I load the contents of the SVG file into a javascript variable/object?
CSS Styling
Try using CSS to style the paths instead of replacing parts of source code.
Concept code example, using the style attribute of svg elements to apply some CSS:
"use strict";
const svg = document.querySelector("svg");
const paths = svg.querySelectorAll("path");
paths[0].style = "fill: #FF0000;"
svg.querySelector("circle").style = "fill: rebeccapurple";
svg {
height: 150px;
width: 100px;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 150" ><path class="st0" fill="#FFFFFF" d="M50,145.5C40.6,131.6,2.5,73.4,2.5,50C2.5,23.8,23.8,2.5,50,2.5S97.5,23.8,97.5,50C97.5,73.4,59.4,131.6,50,145.5z"/><path class="st1" fill="#000000" d="m50 5c24.8 0 45 20.2 45 45 0 19.5-29.4 67.7-45 91.1-15.6-23.4-45-71.6-45-91.1 0-24.8 20.2-45 45-45m0-5c-27.6 0-50 22.4-50 50s50 100 50 100 50-72.4 50-100-22.4-50-50-50z"/><circle fill="#ffbf00" cx="50" cy="50" r="27.5"/><path d="m50 25c13.8 0 25 11.2 25 25s-11.2 25-25 25-25-11.2-25-25 11.2-25 25-25m0-5c-16.6 0-30 13.4-30 30s13.4 30 30 30 30-13.4 30-30-13.4-30-30-30z"/></svg>
Potentially you could improve on this by writing svg source that expects to be styled by CSS instead of being over-ridden by style attribute values.
See also: How to use external SVG in HTML?
Getting the source of an external SVG file
An external svg file can be included in HTML using a pair of <object> tags. For example if "svg-file.svg" is in the same directory as the HTML file:
<object type="image/svg+xml" id="mySVG"
data="svg-file.svg"
width="100"
height="150"
></object>
Subject to security policies: the svg file must be from the same domain and served from a network or localhost server - due to blanket security restriction placed on local files, the source of svg files loaded using the file:// protocol. can't be accessed.
Picking up the svg source is a bit obscure. This worked for me after page load, using the above HTML:
window.onload = ()=> {
console.log("loaded");
const svgObject = document.querySelector("#mySVG");
const svg = svgObject.getSVGDocument().documentElement;
const svgSource = svg.outerHTML;
console.log("svgElement, tag name '%s' ", svg.tagName, svg);
console.log("svgSource: ", svgSource);
console.log("path.st0: ", svg.querySelector('.st0'));
};
One solution is to load the svg image by setting the innerHTML property of an arbitrary container to your svg string.
This then gives you two options: firstly, for heavy changes, you have access to each path as part of the DOM and can maniulate them using javascript. This simply requires making a reference to container.children[0]; Alternatively, for simple changes such as colour changes, it makes each element directly targetable by style rules where you can specify colours in the usual way.
The snippet illustrates adding the svg to the dom using your string, and resets some colours with simple style rules. Making a reference for changes using javascript is shown commented at the foot of the code.
let svgSource = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 150" ><path class="st0" fill="#FFFFFF" d="M50,145.5C40.6,131.6,2.5,73.4,2.5,50C2.5,23.8,23.8,2.5,50,2.5S97.5,23.8,97.5,50C97.5,73.4,59.4,131.6,50,145.5z"/><path class="st1" fill="#000000" d="m50 5c24.8 0 45 20.2 45 45 0 19.5-29.4 67.7-45 91.1-15.6-23.4-45-71.6-45-91.1 0-24.8 20.2-45 45-45m0-5c-27.6 0-50 22.4-50 50s50 100 50 100 50-72.4 50-100-22.4-50-50-50z"/><circle fill="#ffbf00" cx="50" cy="50" r="27.5"/><path d="m50 25c13.8 0 25 11.2 25 25s-11.2 25-25 25-25-11.2-25-25 11.2-25 25-25m0-5c-16.6 0-30 13.4-30 30s13.4 30 30 30 30-13.4 30-30-13.4-30-30-30z"/></svg>';
const container = document.getElementsByTagName('div')[0];
container.innerHTML = svgSource;
// for js manipulation:
// svgObject = container.children[0];
div {
width: 50%;
}
.st0 {
fill: red;
}
.st1 {
fill: yellow;
}
circle {
fill: green;
}
<div>
</div>

Find centre of svg path elements

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)?

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