How to insert multiline text in a svg element - javascript

As a primer in svg and javascript I've been trying for a while to make this code work with no avail.
My problem is that I'm not able to take the text from a text element (class="texts") and put it into another one (MySpeechBoxText1) maintaining it's multiline formatting.
Here is my code:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="594mm" height="420mm" id="svg58064"
viewBox="0 0 2245.0393 1587.4016">
<style>
.bar {
fill: #a9a9a9;
opacity: 0.6;
}
</style>
<g class="miogruppo">
<rect class="bar" x="50" y="60" width="80" height="120"/>
<text class="texts" x="0" y="50" font-family="Verdana" font-size="35" fill="blue" display='none'>
<tspan x="20" dy="1.2em">test 1</tspan>
<tspan x="20" dy="1.2em">test 1</tspan>
</text>
</g>
<g class="miogruppo">
<rect class="bar" x="180" y="80" width="80" height="170"/>
<text class="texts" x="0" y="50" font-family="Verdana" font-size="35" fill="blue" display='none'>
<tspan x="20" dy="1.2em">test 2</tspan>
<tspan x="20" dy="1.2em">test 2</tspan>
</text>
</g>
<g id="group1" display='none'>
<title>Tester 2</title>
<path id="test1"
d="M15,0 H150 V150 H15 L15,90 L0,90 L15,75 Z15 "
style="stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;
stroke-dasharray:none;stroke-miterlimit:4;stroke-opacity:1;fill-opacity:0.5;fill:#ffffff"
inkscape:connector-curvature="0"/>
<text id="MySpeechBoxText1" x="60" y="60" > </text>
</g>
<script><![CDATA[
var bars = document.getElementsByClassName('bar');
var texts = document.getElementsByClassName('texts');
var mySpeechBox = document.getElementById("group1");
var MySpeechBoxText1 = document.getElementById("MySpeechBoxText1");
for (var i = 0; i < bars.length; i++) {
bars[i].addEventListener('mouseover', mouseOverEffect);
bars[i].addEventListener('mouseout', mouseOutEffect);
bars[i].addEventListener('mousemove', mousemoveEffect(i));
}
for (var i = 0; i < texts.length; i++) {
texts[i].addEventListener('mouseover', mouseOverEffect);
texts[i].addEventListener('mouseout', mouseOutEffect);
texts[i].addEventListener('mousemove', mousemoveEffect(i));
}
function mouseOverEffect() {
mySpeechBox.style.display='block';
}
function mouseOutEffect() {
mySpeechBox.style.display='none';
}
function mousemoveEffect(a) {
return function() {
var myX = +bars[a].getAttribute("x");
var myY = +bars[a].getAttribute("y");
var myWidth = +bars[a].getAttribute("width");
var myHeight = +bars[a].getAttribute("height");
var MySumX =myX + myWidth/2;
var MySumY =myY + myHeight/2 - 90;
mySpeechBox.setAttribute("transform", 'translate(' + MySumX + ',' + MySumY + ')');
//MySpeechBoxText1.style.whiteSpace = "pre";
MySpeechBoxText1.textContent = texts[a].textContent; //here the text should be multiline
}
}
]]></script>
</svg>

Instead of textContent, use innerHTML.
const text1 = document.querySelector('.text1');
const text2 = document.querySelector('.text2');
text2.innerHTML = text1.innerHTML;
<svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
<style>
.small { font: italic 13px sans-serif; }
.heavy { font: bold 30px sans-serif; }
/* Note that the color of the text is set with the *
* fill property, the color property is for HTML only */
.Rrrrr { font: italic 40px serif; fill: red; }
</style>
<text class="text1" x="0" y="5" font-family="Verdana" font-size="10" fill="blue" >
<tspan x="20" dy="1.2em">test 1</tspan>
<tspan x="20" dy="1.2em">test 1</tspan>
</text>
<text x="25" y="25" class="text2"></text>
</svg>

Related

Transform origin on SVG pattern not working on Firefox/Safari

I made a hexagonal grid with an SVG pattern.
To zoom in, I used transform's scale function, and to keep it scaling from the center I set transform-origin to the center of the page.
This is perfectly working on Chrome but not on Safari and Firefox.
How can I make it work on all browsers?
Here's what I made so far:
const pattern = document.getElementById('hexagons');
const center = {
x: window.innerWidth / 2,
y: window.innerHeight / 2
};
const transformOrigin = `${center.x}px ${center.y}px`;
let zoom = 1;
const formatPatternTransform = (zoom) => `rotate(90) scale(${zoom})`;
function animate() {
if (zoom > 3)
return;
zoom += .005;
pattern.setAttribute('patternTransform', formatPatternTransform(zoom));
requestAnimationFrame(animate);
}
pattern.setAttribute('transform-origin', transformOrigin);
animate();
* {
margin: 0;
padding: 0;
}
svg {
background: #0a0a0a;
height: 100vh;
width: 100vw;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
why not simply scaling the whole SVG:
* {
margin: 0;
padding: 0;
}
svg {
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
background: #0a0a0a;
animation:zoom 3s ease-out forwards
}
#keyframes zoom {
to {
transform:scale(3);
}
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
To avoid the lag you can keep you JS code:
let s = document.querySelector('svg');
let zoom = 1;
function animate() {
if (zoom > 3)
return;
zoom += .005;
s.style.transform = "scale(" + zoom + ")";
requestAnimationFrame(animate);
}
animate();
* {
margin: 0;
padding: 0;
}
svg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0a0a0a;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
You can easily zoom out too:
let s = document.querySelector('svg');
let zoom = 1;
function animate() {
if (zoom < 0.2)
return;
zoom -= .005;
s.style.transform = "scale(" + zoom + ")";
requestAnimationFrame(animate);
}
animate();
* {
margin: 0;
padding: 0;
}
svg {
position:fixed;
top:-300%;
left:-300%;
width:700%;
height:700%;
background: #0a0a0a;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
This is an alternative solution. Instead of using transform-origin you can center the <rect id="mosaic" around the origin of the svg canvas. In this case you will need a viewBox attribute: viewBox="-250 -250 500 500" and preserveAspectRatio="xMidYMid slice"
"xMidYMid (the default) - Force uniform scaling.
Align the midpoint X value of the element's viewBox with the midpoint X value of the viewport.
Align the midpoint Y value of the element's viewBox with the midpoint Y value of the viewport."
"slice - Scale the graphic such that:
aspect ratio is preserved
the entire viewport is covered by the viewBox
the viewBox is scaled down as much as possible, while still meeting the other criteria"
And this is the rectangle filled with the pattern:
<rect id="mosaic" x="-250" y="-250" width="500" height="500" fill="url(#hexagons)" />
Next comes a working example:
const pattern = document.getElementById('hexagons');
const center = {
x: window.innerWidth / 2,
y: window.innerHeight / 2
};
//const transformOrigin = `${center.x}px ${center.y}px`;
let zoom = 1;
const formatPatternTransform = (zoom) => `rotate(90) scale(${zoom})`;
function animate() {
if (zoom > 3)
return;
zoom += .005;
pattern.setAttribute('patternTransform', formatPatternTransform(zoom));
requestAnimationFrame(animate);
}
//pattern.setAttribute('transform-origin', transformOrigin);
animate();
* {
margin: 0;
padding: 0;
}
svg {
background: #0a0a0a;
height: 100vh;
width: 100vw;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-250 -250 500 500" preserveAspectRatio="xMidYMid slice">
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" x="-250" y="-250" width="500" height="500" fill="url(#hexagons)" />
</svg>

SVG Input Field

I'm trying to make one of my SVG text fields accept input from the user when they press on it. Is there any way of doing that?
const wrapper = document.getElementById('wrapper');
const text = document.getElementById('Username');
const inputWrapper = document.getElementById('input-wrapper');
const input = document.getElementById('input');
const button = document.getElementById('button');
text.addEventListener('click', () => {
text.classList.toggle('hide');
inputWrapper.classList.toggle('hide');
input.focus();
});
button.addEventListener('click', () => {
text.classList.toggle('hide');
inputWrapper.classList.toggle('hide');
});
input.addEventListener('change', (e) => {
text.innerText = e.target.value;
});
.cls-1 {
clip-path: url(#clip-Login_page);
}
.cls-2 {
opacity: 0.67;
fill: url(#pattern);
}
.cls-3 {
fill: #d9d9d9;
}
.cls-3, .cls-5 {
stroke: #0d0d0d;
}
.cls-4 {
fill: url(#pattern-2);
}
.cls-5 {
fill: #f2f2f2;
}
.cls-6, .cls-7 {
fill: #707070;
font-family: Georgia;
}
.cls-6 {
font-size: 25px;
}
.cls-7 {
font-size: 20px;
}
.cls-8 {
stroke: none;
}
.cls-9 {
fill: none;
}
.cls-10 {
fill: #fff;
}
.cls-11 {
filter: url(#Rectangle_5);
}
.cls-12 {
filter: url(#Amcan_logo);
}
.cls-13 {
filter: url(#Rectangle_2);
}
.hide {
display: none;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 375 667">
<defs>
<pattern id="pattern" preserveAspectRatio="none" width="100%" height="100%" viewBox="0 0 1920 1080">
<image width="1920" height="1080" xlink:href="img/Amcan.gif"/>
</pattern>
<filter id="Rectangle_2" x="11" y="178" width="354" height="63" filterUnits="userSpaceOnUse">
<feOffset dy="5" input="SourceAlpha"/>
<feGaussianBlur stdDeviation="3" result="blur"/>
<feFlood flood-opacity="0.161"/>
<feComposite operator="in" in2="blur"/>
<feComposite in="SourceGraphic"/>
</filter>
<pattern id="pattern-2" preserveAspectRatio="none" width="100%" height="100%" viewBox="0 0 593 186">
<image width="593" height="186" xlink:href="img/Amcan_logo.png"/>
</pattern>
<filter id="Amcan_logo" x="13" y="28" width="349" height="123" filterUnits="userSpaceOnUse">
<feOffset dy="10" input="SourceAlpha"/>
<feGaussianBlur stdDeviation="3" result="blur-2"/>
<feFlood flood-opacity="0.161"/>
<feComposite operator="in" in2="blur-2"/>
<feComposite in="SourceGraphic"/>
</filter>
<filter id="Rectangle_5" x="77" y="369" width="222" height="63" filterUnits="userSpaceOnUse">
<feOffset dy="5" input="SourceAlpha"/>
<feGaussianBlur stdDeviation="3" result="blur-3"/>
<feFlood flood-opacity="0.161"/>
<feComposite operator="in" in2="blur-3"/>
<feComposite in="SourceGraphic"/>
</filter>
<clipPath id="clip-Login_page">
<rect width="375" height="667"/>
</clipPath>
</defs>
<g id="Login_page" data-name="Login page" class="cls-1">
<rect class="cls-10" width="375" height="667"/>
<rect id="Amcanerino" class="cls-2" width="510" height="667" transform="translate(-71)"/>
<g class="cls-13" transform="matrix(1, 0, 0, 1, 0, 0)">
<g id="Rectangle_2-2" data-name="Rectangle 2" class="cls-3" transform="translate(20 182)">
<rect class="cls-8" width="336" height="45"/>
<rect class="cls-9" x="0.5" y="0.5" width="335" height="44"/>
</g>
</g>
<g class="cls-12" transform="matrix(1, 0, 0, 1, 0, 0)">
<rect id="Amcan_logo-2" data-name="Amcan_logo" class="cls-4" width="331" height="104" transform="translate(22 28)"/>
</g>
<g id="Rectangle_3" data-name="Rectangle 3" class="cls-5" transform="translate(20 250)">
<rect class="cls-8" width="336" height="45"/>
<rect class="cls-9" x="0.5" y="0.5" width="335" height="44"/>
</g>
<g id="Rectangle_4" data-name="Rectangle 4" class="cls-5" transform="translate(20 311)">
<rect class="cls-8" width="336" height="45"/>
<rect class="cls-9" x="0.5" y="0.5" width="335" height="44"/>
</g>
<g class="cls-11" transform="matrix(1, 0, 0, 1, 0, 0)">
<g id="Rectangle_5-2" data-name="Rectangle 5" class="cls-3" transform="translate(86 373)">
<rect class="cls-8" width="204" height="45"/>
<rect class="cls-9" x="0.5" y="0.5" width="203" height="44"/>
</g>
</g>
<text id="SUBMIT" class="cls-6" transform="translate(139 405)"><tspan x="0" y="0">SUBMIT</tspan></text>
<text id="Login" class="cls-6" transform="translate(156 214)"><tspan x="0" y="0">Login</tspan></text>
<div id="wrapper">
<text id="Username" class="cls-7" transform="translate(142 280)"><tspan x="0" y="0">Username</tspan></text>
<div id="input-wrapper" class="hide">
<input id="input" type="text" value="Username"/>
<button id="button">Submit</button>
</div>
</div>
<text id="Password" class="cls-7" transform="translate(145 341)"><tspan x="0" y="0">Password</tspan></text>
</g>
</svg>
This is the amended code as suggested by Solo.
<tspan> and <text> are not html elements, but svg elements with their own attributes. The property contenteditable doesn't exist on tspan (you can console.log document.querySelector("#myTspan").isContentEditable, it will return undefined.
However, it can inherit properties from its parents. So in case of an inline svg in a HTML file, wrapping your svg in an editable element will work in some browsers, but all you texts are then editable.
<div contenteditable="true">
<svg>
<text id="Username" class="cls-7" transform="translate(142 20)"><tspan x="0" y="0">Username</tspan></text>
</svg>
</div>
In a standalone SVG, you have no way to have contenteditable working since it's part of HTML specification, not that of SVG.
You have to go for a script as other answers suggest, but read carefully (since you didn't mentionned at first that it was a standalone svg) : Including JavaScript in SVG
Yes and no, you can't edit the text directly, but you can put an input overtop of it. See the code below:
.input-real {
background: rgba(255, 255, 255, 0);
color: transparent;
padding: 0;
border: 0 none transparent;
line-height: 0;
}
.input-real:focus {
background: rgba(255, 255, 255, 1);
color: #333;
}
.input-real,
.input-mimic {
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
<svg viewBox="0 0 375 667">
<text id="Username" class="input-mimic" x="50" y="50" alignment-baseline="hanging">Username</text>
<foreignObject width="50" height="23" x="50" y="46">
<input id="input" class="input-real" type="text" value="Username"/>
</foreignObject>
</svg>
use contenteditable on tspan
see more here - https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content
How does it work?
All you have to do is set the contenteditable attribute on nearly any HTML element to make it editable.
function toggleEdit() {
var text = document.getElementById('Username');
var tspan = text.firstElementChild;
tspan.setAttribute('contenteditable', true);
}
<text id="Username" class="cls-7" transform="translate(142 280)"><tspan x="0" y="0">Username</tspan></text>
<div><button onclick="toggleEdit();">Edit input</button></div>
Thank you very much for your help guys! I have found out that I can just use JavaScript 'prompt' form to achieve this. All I had to do was to implement the following:
<script>
function changeUsername()
{
document.getElementById('Username').textContent = prompt("Please enter your Username");
}
</script>
<rect onclick="changeUsername()" class="cls-8" width="336" height="45"/>
I completely forgot that the prompt form existed! Again, thank you all :)
No need of jquery or JS,
Just add contenteditable="true" to that text element and you're done...
<text contenteditable="true" id="Username" class="cls-7" transform="translate(142 280)"><tspan x="0" y="0">Username</tspan></text>

Draw Svg to canvas including images embedded in svg

<html
><svg width="960" height="500" id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg"><g class="linz"><line class="bluelink" x1="480" y1="250" x2="334.8434764825239" y2="275.78849826638145"></line><rect x="397.42173824126195" y="252.89424913319073" width="20" height="20" style="fill: black; stroke: skyblue;"></rect><text class="link-label" font-family="Arial, Helvetica, sans-serif" fill="white" dy=".35em" text-anchor="middle" x="407.42173824126195" y="262.8942491331907">101</text></g><g class="linz"><line class="bluelink" x1="480" y1="250" x2="619.1894601470176" y2="200.9990683994202"></line><rect x="539.5947300735088" y="215.4995341997101" width="20" height="20" style="fill: black; stroke: skyblue;"></rect><text class="link-label" font-family="Arial, Helvetica, sans-serif" fill="white" dy=".35em" text-anchor="middle" x="549.5947300735088" y="225.4995341997101">2</text></g><g class="linz"><line class="bluelink" x1="480" y1="250" x2="434.983433226373" y2="390.53065260546134"></line><rect x="447.4917166131865" y="310.26532630273067" width="20" height="20" style="fill: black; stroke: skyblue;"></rect><text class="link-label" font-family="Arial, Helvetica, sans-serif" fill="white" dy=".35em" text-anchor="middle" x="457.4917166131865" y="320.26532630273067">2</text></g><g class="linz"><line class="bluelink" x1="480" y1="250" x2="585.5868329731418" y2="353.5574331993295"></line><rect x="522.7934164865709" y="291.7787165996648" width="20" height="20" style="fill: black; stroke: skyblue;"></rect><text class="link-label" font-family="Arial, Helvetica, sans-serif" fill="white" dy=".35em" text-anchor="middle" x="532.7934164865709" y="301.7787165996648">119</text></g><g class="linz"><line class="bluelink" x1="480" y1="250" x2="499.47384868808143" y2="103.87072365281172"></line><rect x="479.73692434404074" y="166.93536182640585" width="20" height="20" style="fill: black; stroke: skyblue;"></rect><text class="link-label" font-family="Arial, Helvetica, sans-serif" fill="white" dy=".35em" text-anchor="middle" x="489.73692434404074" y="176.93536182640585">2</text></g><g class="linz"><line class="bluelink" x1="480" y1="250" x2="373.73145030208514" y2="147.4006224017257"></line><rect x="416.86572515104257" y="188.70031120086287" width="20" height="20" style="fill: black; stroke: skyblue;"></rect><text class="link-label" font-family="Arial, Helvetica, sans-serif" fill="white" dy=".35em" text-anchor="middle" x="426.86572515104257" y="198.70031120086287">5</text></g><g class="node" transform="translate(334.8434764825239,275.78849826638145)"><circle r="10.392304845413264" style="fill: white;"></circle><image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="images/call.png" x="-17" y="-17" height="30" width="30"></image><text dy="2.6em">111</text></g><g class="node" transform="translate(619.1894601470176,200.9990683994202)"><circle r="10.392304845413264" style="fill: white;"></circle><image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="images/call.png" x="-17" y="-17" height="30" width="30"></image><text dy="2.6em">999</text></g><g class="node" transform="translate(434.983433226373,390.53065260546134)"><circle r="10.392304845413264" style="fill: white;"></circle><image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="images/call.png" x="-17" y="-17" height="30" width="30"></image><text dy="2.6em">222</text></g><g class="node" transform="translate(585.5868329731418,353.5574331993295)"><circle r="10.392304845413264" style="fill: white;"></circle><image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="images/call.png" x="-17" y="-17" height="30" width="30"></image><text dy="2.6em">XXX</text></g><g class="node" transform="translate(499.47384868808143,103.87072365281172)"><circle r="10.392304845413264" style="fill: white;"></circle><image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="images/call.png" x="-17" y="-17" height="30" width="30"></image><text dy="2.6em">444</text></g><g class="node" transform="translate(373.73145030208514,147.4006224017257)"><circle r="10.392304845413264" style="fill: white;"></circle><image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="images/call.png" x="-17" y="-17" height="30" width="30"></image><text dy="2.6em">333</text></g><g class="node" transform="translate(480,250)"><circle r="10.392304845413264" style="fill: white;"></circle><image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="images/target.png" x="-17" y="-17" height="30" width="30"></image><text dy="2.6em">Main</text></g></svg>
On Coverting to Canvas using given code
var svgText = document.getElementById("myViewer").outerHTML;
var myCanvas = document.getElementById("canvas");
var ctxt = myCanvas.getContext("2d");
function drawInlineSVG(ctx, rawSVG, callback) {
var svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"}),
domURL = self.URL || self.webkitURL || self,
url = domURL.createObjectURL(svg),
img = new Image;
img.onload = function () {
ctx.drawImage(this, 0, 0);
domURL.revokeObjectURL(url);
callback(this);
};
img.src = url;
}
// usage:
drawInlineSVG(ctxt, svgText, function() {
console.log(canvas.toDataURL()); // -> PNG
alert("see console for output...");
});
no links or images are shown on canvas though images and links are shown on svg.
How to do it and add jpg/svg/print/pdf functionality?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/akhilsahu/saveSvgAsPngJpgSvg/master/svg.js"></script>
saveSvAsPngJpgSvg.js
https://github.com/akhilsahu/saveSvgAsPngJpgSvg
It is too easy to use.
Easy functions can be called to do so.
svgAsPngUri(document.getElementById(svgid), {}, function(uri)
{
document.querySelector('#png-container').innerHTML = '<img id="getimg" style="display:none" src="'+uri+'"/>';
var sampleImage = document.getElementById("getimg"),
canvas = convertImageToCanvas(sampleImage);
// Actions
document.getElementById("canvasHolder").appendChild(canvas);
});
The canvas is added.You can't see as its hidden.
Fiddle hereclick
Here are some tests:
http://jsfiddle.net/MxHPq/140/
Looks like only images that are embedded in the SVG as Data URIs can be drawn on the canvas (the red dot in this example):
<svg id="example1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="100" >
...
<image id="embedded" x="80" y="70" width="20" height="20" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>
</svg>
Here is an online tool which converts images to Data URIs:
http://duri.me/

How to find the coordinates of a text in an svg?

I have one svg which is haveing some shapes and some text. what i want is the coordinates and id of the specific text. like:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1010px" height="750px" viewBox="0 0 1010 750" preserveAspectRatio="xMidYMid meet" zoomAndPan="disable" >
<rect x="104" y="85" stroke="black" id="e1_rectangle" style="stroke-width: 1px; vector-effect: non-scaling-stroke;" width="145" height="209" fill="red"/>
<text fill="black" x="346" y="147" id="e2_texte" style="font-family: Arial; font-size: 20px;" transform="matrix(1 0 0 1 -217 -80)">rectangle</text>
<circle id="e5_circle" cx="407" cy="166" stroke="black" style="stroke-width: 1px; vector-effect: non-scaling-stroke;" r="83.0963296422" fill="green"/>
<text fill="black" x="387" y="62" id="e6_texte" style="font-family: Arial; font-size: 20px;" >circle</text>
</svg>
now if i want to know the x,y coordinates of text : "rectangle" how can i do the same?
Thanks
You can do it like this using (since its tagged) d3.
//filter all the texts
var texts = d3.selectAll("text")[0].filter(function(r) {
return d3.select(r).text() == "rectangle"
})
//map all the x and y of filtered texts
var coordinates = texts.map(function(t){
return {x: d3.select(t).attr("x"), y : d3.select(t).attr("y")}
})
console.log(coordinates)
working code here

Why isn't my svg's embedded javascript working in an html document?

I have the following code for an svg:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="470px" height="260px" version="1.1" onload="addEvents()" xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink">
<image xlink:href="baby.jpg" x="0" y="0" height="260px" width="470px">
</image>
<g transform="translate(100,50)">
<circle class="circle" id="tip1" cx="20" cy="0" r="10" stroke="" stroke-width="0" fill="rgb(143, 124, 184)" />
<g transform="translate(10,15)">
<polygon class="baby-tip tip1 arrow" points="0,10 10,0, 20,10" style="fill: rgb(143, 124, 184)" />
</g>
<rect class="baby-tip tip1" x="0" y="25" height="70" width="220" rx="5" ry="5" style="fill: rgb(143, 124, 184)"/>
<text class="baby-tip tip1" x="10" y="45">Here is a whole bunch of text.</text>
<text class="baby-tip tip1" x="10" y="60">Clearly this should wrap, but it</text>
<text class="baby-tip tip1" x="10" y="75">doesn't. What will we do?</text>
</g>
<g transform="translate(150,160)">
<circle class="circle" id="tip2" cx="20" cy="0" r="10" stroke="" stroke-width="0" fill="rgb(143, 124, 184)" />
<g transform="translate(10,15)">
<polygon class="baby-tip tip2 arrow" points="0,10 10,0, 20,10" style="fill: rgb(143, 124, 184)" />
</g>
<rect class="baby-tip tip2" x="0" y="25" height="70" width="220" rx="5" ry="5" style="fill: rgb(143, 124, 184)"/>
<text class="baby-tip tip2" x="10" y="45">Here is a whole bunch of text.</text>
<text class="baby-tip tip2" x="10" y="60">Clearly this should wrap, but it</text>
<text class="baby-tip tip2" x="10" y="75">doesn't. What will we do?</text>
</g>
<style>
.baby-tip {
font-size: 14px;
font-family: "MuseoSans100", Arial, Helvetica, sans-serif;
fill: white;
opacity: 0;
}
</style>
<script>
var log = console.info;
function addEvents() {
var dots = document.getElementsByClassName("circle");
var i = dots.length;
while(i--) {
toggleTips(dots[i]);
}
}
function closeOtherTips(otherTips) {
var l = otherTips.length;
while (l--) {
otherTips[l].style.opacity = 0;
}
}
function toggleTips(dot, l) {
window.dot = dot;
dot.addEventListener("click", function() {
var className = dot.id;
var tips = document.getElementsByClassName(className);
var otherTips = document.querySelectorAll('text:not(.' + className + '), rect:not(.' + className + '), polygon:not(.' + className + ')');
var t = tips.length;
closeOtherTips(otherTips);
while (t--) {
tips[t].style.opacity != 0 ? tips[t].style.opacity = 0 : tips[t].style.opacity = 1;
}
});
}
</script>
</svg>
When I save this content as test.svg, and view it in a browser, it runs beautifully - I should see two purple dots, and when I click each one I get a little tool tip, and only one displays at a time.
However, if I create the following html document:
<!DOCTYPE html>
<html>
<body>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<img class="baby-dot-svg" src="test.svg" />
<img class="baby-dot-bg" src="baby.jpg" />
</body>
</html>
Two things change:
1) the tooltip / all js functionality is lost - nothing happens when I click on the dots.
2) the link to baby.jpg no longer works - despite baby.jpg and the svg residing in the same directory, the background of the svg is blank.
See http://images.agoramedia.com/wte3.0/gcms/web_view_svg_test2.html to view this in action.
Why is this breaking?
There are mulitple ways to embed SVG files, but the <img> approach doesn't allow it to be interactive.
Try:
<object data="test.svg" type="image/svg+xml">
<img src="baby.jpg" />
</object>
For more information, see this answer.

Categories

Resources