How to add a svg to work space by click button? - svg

Maybe this is very simple for you, but not for me...
I want a simple button that which when is pressed add a svg (preference a circle) to the work space.
Something like this https://codepen.io/davecar21/pen/jYQLEO
but I don't want an animation, just a simple svg (preference circle).
$('button').click(function() { $('svg animate.anim1').attr("begin", 2); $('svg animate.anim2').attr("begin", 3); })

document.getElementById('draw').addEventListener('click', function(){
document.getElementById('here').innerHTML =
'<svg height="100" width="100">' +
'<circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="rgba(130,130,130,0.6)">' +
'</svg>';
});
<button id="draw">Draw Circle</button>
<div id="here"></div>

Related

Hitting a break wall with SVG

Why a light colored rectangle background showed up on the area behind xlink every time it is touched or clicked?
Here is my SVG code:
<svg version="1.1" viewBox="0 0 147.86 258.44" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g class="bglyr" fill="none" transform="translate(-30.575,-20.926)">
<a xlink:href="https://google.com">
<path id="link1" fill="none" onmouseover="change(this)" onmouseout="unchange(this)" d="m104.43 242.44 11.742 6.1664 57.094 29.884-137.62 0.0617z" />
<a />
</g>
</svg>
JavaScript:
function change(item) {
item.style.fill = "#42d46b";
item.style.opacity = "1.0";
}
function unchange(item) {
item.style.fill = "none";
item.style.opacity = "0.0";
}
Just in case your question is actually about why your example code doesn't work, then I can explain that for you.
Mouse events won't be triggered if your <path> has nothing to hover over. When the fill is "none" or the opacity is 0. No mouse events will be triggered. To fix this, use fill="transparent" instead. This behaves the same way, but is detected as if it was any other non-transparent fill colour.
function change(item) {
item.style.fill = "#42d46b";
}
function unchange(item) {
item.style.fill = "transparent";
}
<svg version="1.1" viewBox="0 0 147.86 258.44" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g class="bglyr" fill="none" transform="translate(-30.575,-20.926)">
<a xlink:href="https://google.com">
<path id="link1" fill="transparent" onmouseover="change(this)" onmouseout="unchange(this)" d="m104.43 242.44 11.742 6.1664 57.094 29.884-137.62 0.0617z" />
</a>
</g>
</svg>

How to create an svg element programmatically in an svg document?

I know that we can use the document.createElementNS("http://www.w3.org/2000/svg","line"); to create a svg element embeded in a html page.
But, this method doesn't seems to work in a standalone svg document.
Actually, I am trying to draw the national flag of India in svg, but, drawing the 24 spokes in the wheel of the flag would be very time consuming. So, I thought of drawing them programmatically through JavaScript.
Any help on how to create elements programmatically in a standalone svg document will be appreciated.
You can use javascript inside an svg element. I've done only the center of the flag.
Please observe the viewBox="-50 -50 100 100". The point {x:0,y:0} is in the center of the SVG canvas.
svg{border:1px solid; width:90vh;}
<svg viewBox="-50 -50 100 100" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<g id="center" fill="blue" stroke="blue">
<circle r="5" />
<circle id="outline" stroke-width="4" fill="none" r="48" />
<polygon id="spoke" points="0,0 20,1.5 48,0 20,-1.5 0,0" fill="blue" stroke="none" />
<circle id="dot" r="2.5" cx="46" transform="rotate(7.5)" />
</g>
<script>
<![CDATA[
const SVG_XLINK = "http://www.w3.org/1999/xlink";
const SVG_NS = 'http://www.w3.org/2000/svg';
// a function that creates a new `<use>` element and rotates it around the origin of the SVG canvas
function reuse(used,parent,i) {
let use = document.createElementNS(SVG_NS, 'use');
use.setAttributeNS(SVG_XLINK, 'xlink:href', used); use.setAttributeNS(null,"transform" ,`rotate(${360*i/24})`);
parent.appendChild(use);
}
// a loop that creates 24 use elements
for(let i = 0;i < 24; i++ ){
reuse("#spoke",document.querySelector("#center"),i);
reuse("#dot",document.querySelector("#center"),i);
}
]]>
</script>
</svg>
You can't do what you're trying to do since Javascript shouldn't be included in, and isn't understood or processed inside a SVG file.

Dragging wrong riot component

I'm creating a draggable riot js based SVG element.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g name="green" data-is="r-rect" x="30" y="230" width="256" height="64" rx="5" ry="5" draggable="true" fill="green"></g>
<g name="blue" data-is="r-rect" x="10" y="110" width="256" height="64" rx="5" ry="5" draggable="true" fill="blue"></g>
</svg>
r-rect.tag
<r-rect>
<rect ref="rect" onmousedown={hold} />
<script>
tag = this;
tag.hold = hold;
tag.x= Number.parseInt(opts.x);
tag.y= Number.parseInt(opts.y);
tag._name= opts.name;
tag.on("mount", function(e) {
tag.refs.rect.setAttribute("x", opts.x);
tag.refs.rect.setAttribute("y", opts.y);
tag.refs.rect.setAttribute("width", opts.width);
tag.refs.rect.setAttribute("height", opts.height);
opts.rx && (tag.refs.rect.setAttribute("rx", opts.rx) );
opts.ry && (tag.refs.rect.setAttribute("ry", opts.ry) );
})
function hold(e){
console.log(tag._name)
}
</script>
</r-rect>
I add 2 r-rect tags. Try to drag blue rectangle. But mousedown event of green rectangle triggers always .
http://jsfiddle.net/1k2gacy1/1/
I found the issue. It was happening because I was assigning the tag instance in global variable. So I've changed this line tag = this; to var tag = this;. And it solved the issue.

Dart SvgSvgElement does not respond to keyboard events [duplicate]

I have a svg and I can draw multiple shapes on this svg. Now my requirement is I want to listen keyboard events like ctrl+C, ctrl+V, ctrl+D, Esc, Delete so that I can copy, paste , duplicate selected shape. But I have no idea about listening keyboard events on SVG . I tried following code but no luck !!
mySVG.on("keydown", function () {
//code to handle keydown
});
Any help ? Thanks in advance.
Because SVG is not an input-type, listen for the event on the window instead:
$(window).on('keypress', function (evt){ ... })
Add tabindex="0" attribute to the <svg> and it will work:
const svgElement = document.querySelector('svg');
svgElement.addEventListener('keydown', event => {
console.log('svg keydown: ', event.key);
});
<svg tabindex="0" width="300" height="200">
<rect width="100%" height="100%" fill="#555" />
<text x="50%" y="50%" font-size="20" text-anchor="middle" fill="white">
Click me and start typing
</text>
</svg>
The tabindex attribute allows you to control whether an element is
focusable, and ...
See MDN docs for more info.

SVG: dynamic size based on text, merging objects

<div style="float: left; padding: 10px; border: 1px solid;
background: #ccc">random text</div>
Is there a way to achieve something like this in SVG? I mean to have a rectangle and a text and:
a) rectangle's width and height are dynamic, so when I change the text, the rectangle adjust its size
b) when I move the rectangle, the text goes with it
And would it be easier to achieve something like this in <canvas>?
EDIT:
<defs>
<text id="text1" x="90" y="100" style="text-anchor:start;font-size:30px;">
THIS IS MY HEADER</text>
</defs>
<filter x="0" y="0" width="1" height="1" id="background">
<feFlood flood-color="gray"/>
<feComposite in="SourceGraphic"/>
</filter>
<use xlink:href="#text1" fill="black" filter="url(#background)"/>
Erik Dahlström proposed something like this. How to put padding to the background, how to add eg. shadow or border to the rectangle? And, this doesn't work in IE9, so I cannot accept it. I could just use <foreignObject> if there was a support for it in IE.
And I just figured out the answer for b) point of my question. You have to put both elements in the group:
<g>
<rect x="0" y="0" width="100" height="100" fill="red"></rect>
<text x="50" y="50" font-size="14" fill="blue" text-anchor="middle">Hello</text>
</g>
And then you can move the group using transform param:
<g transform="translate(x, y)">
Seems to work correct in every browser.
You can use JavaScript to adjust the box:
<svg xmlns="http:/www.w3.org/2000/svg" onload="init()" height="100" width="200">
<style type="text/css">
rect {
stroke:black;
stroke-width:1;
fill:#ccc;
}
</style>
<script type="text/javascript">
var text, rect
var padding = 10
function init() {
text = document.getElementsByTagName("text")[0]
rect = document.getElementsByTagName("rect")[0]
adjustRect()
}
function adjustRect() {
var bbox = text.getBBox()
rect.setAttribute("x",bbox.x - padding)
rect.setAttribute("y",bbox.y - padding )
rect.setAttribute("width",bbox.width + 2*padding)
rect.setAttribute("height",bbox.height + 2*padding)
}
</script>
<g>
<rect x="0" y="0" width="100" height="100" fill="red"></rect>
<text x="50" y="50" font-size="14" fill="blue" text-anchor="middle">Hello</text>
</g>
</svg>
<div>
<button onclick="text.textContent='Goodbye';adjustRect()">change text</button>
</div>
Use an svg filter to draw the background, that will adapt to the size and position of the text. See this answer for a full example.

Resources