I have an interactive SVG - displayed at full window size. I want to add some buttons to it. Is it possible to add normal <button> elements inside <svg> tag?
I think not, but I'm asking if there is something similar for SVG.
From some drawing I get bad results like this:
https://jsfiddle.net/pvxr6g8k/1/
<svg version="1.1" id="svg9723" height="768" width="1268">
<g style="fill:#e6e6e6" id="g3332-7" transform="matrix(0.27404175,0,0,-0.447665,86.580009,508.16151)">
<g style="fill:#e6e6e6" clip-path="url(#clipPath3336-0-0)" id="g3334-7">
<g style="fill:#e6e6e6" transform="translate(992.5469,164.3086)" id="g3340-6">
<path inkscape:connector-curvature="0" id="path3342-2" style="fill:#e6e6e6;stroke:#241a5d;stroke-width:4.48957968;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" d="m 0,0 c -6.937,0 -12.58,5.645 -12.58,12.58 l 0,63.277 c 0,6.937 5.643,12.581 12.58,12.581 l 279.488,0 c 6.936,0 12.58,-5.644 12.58,-12.581 l 0,-63.277 C 292.068,5.645 286.424,0 279.488,0 L 0,0 Z"></path>
</g>
</g>
</g>
<text transform="scale(0.9324557,1.072437)" id="text3390-1" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:11.87269115px;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Bold';writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" x="413.18262" y="390.15326">
<tspan style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Arial;-inkscape-font-specification:'Arial Bold'" y="390.15326" x="413.18262" id="tspan3392-0" sodipodi:role="line">BUTTON</tspan>
</text>
</svg>
The problem is not the visual appearance, but the structure, which not allow me to bind event or interact with it using JS. Not to mention the visual click effect of button "press" is harder to achieve like that.
So what is the solution for buttons in interactive SVG? Any good element like button in HTML?
I don't have to embed html button, any good button replacement would be fine
<button> is an HTML element, and therefore can't go (directly) in an SVG element.
However, you can consider using
<foreignObject position attributes>
<html:button>Button1</html:button>
</foreignObject>
Just make sure you properly declare the namespace, for instance on your root <svg> element, with xmlns:html="http://www.w3.org/1999/xhtml"
This works in most browsers. Internet Explorer doesn't support it, but Microsoft Edge does.
Alternatively, you could just draw your own button-like <rect> and attach a click event handler to it, that'll work just fine too.
You can insert at least a link (and style it afterwards like a button). I put the link with Illustrator in the SVG. Maybe a button is possible too. But you can see working links on our site http://www.kleinefische.com
In the svg it looks like:
<a xlink:href="http://www.kleinefische.com" >
<polygon fill="none" points="162,263.3 251.6,256 252.7,273.3 163,280.5"/>
<text transform="matrix(0.9967 -8.087198e-02 8.087198e-02 0.9967 162.7812 272.6545)"
fill="#FFFFFF" font-family="'TradeGothicLT-Bold'" font-size="12.9937">
/AGENTUR
</text>
</a>
You can use <foreignObject> for that. SVG allows inclusion of elements from foreign namespaces anywhere with the SVG content. In general, the SVG user agent will include the unknown elements in the DOM but will otherwise ignore unknown elements.
foreignObject
You could add an onclick property to your svg object, something like:
onclick='window.location =("http://...");'
You could try out D3JS.
See documentation here on handling mouse events: https://github.com/d3/d3-selection/blob/master/README.md#handling-events
And an example: Unable to get click event in D3 JavaScript library
Related
Good day all, I've a page in which I inject some svg elements, they look like this:
<svg>
<path fill="#FFFFFF" d='....'></path>
<path d='....'></path>
<path d='....'></path>
<path d='....'></path>
</svg>
I cannot alter the svg files that are injected using a javascript library, and I'd like to change their background color on the fly, is there a way to target the only path that has the fill attribute setted to something?
you can use hasAttribute whether element have a particular or not
document.querySelectorAll('.svg path').map( o=>
if(!o.hasAttribute('fill')) {
o.setAttribute('fill', '#eee')
}
);
I've made a cut down version of the issue I'm having in the JSFiddle here.
I use d3.js to dynamically add SVG path elements with class symbol to the group with id grouped-shapes in the following defs tag:
<defs>
<g id="grouped-shapes">
...
</g>
</defs>
I then use this definition twice, once directly and once via a reference to the first use tag:
<g id="first-triangle">
<use xlink:href="#grouped-shapes" transform="translate(100, 100)"/>
</g>
<g id="second-triangle">
<use xlink:href="#first-triangle" transform="translate(200, 200)
rotate(30)"/>
</g>
(In this example case I could easily avoid the problem by working out everything as a transformation of the original grouped-shapes instead of doing this indirect transformation, but in my real use case this would be more complicated.)
I then set up an event listener to remove paths with class symbol on clicking the container div:
document.getElementById("kaleidoscope-container")
.addEventListener("click", function( event ) {
d3.selectAll(".symbol").remove();
}, false);
In Chrome, both groups update on clicking, but in Firefox only the first one does.
Which of these behaviours is correct? I'm looking to be able to update in both instances, as in Chrome - what is the correct way of going about this?
Say I want to programmatically insert an additional <tspan> in the <text> element in the following SVG:
<svg width="300" height="500">
<text x="50" y="100">
<tspan x="50">one</tspan>
<tspan x="50" dy="20">two</tspan>
<tspan x="50" dy="20">three</tspan>
</text>
</svg>
This can be done with, among other things, pure JavaScript (.appendChild), jQuery (.append), and d3.js (.append). However, although all three methods successfully insert the element, I can only seem to get it to actually display when it's inserted by d3.js:
See reduced case in this fiddle: http://jsfiddle.net/2NLJY/.
The behaviour is consistent across the browsers I've tested: Firefox, Chrome, and Safari (all OS X 10.8).
What is going on here?
You can't use createElement to create SVG elements. SVG elements must be created in the SVG namespace so you need to write
document.createElementNS("http://www.w3.org/2000/svg", "tspan");
There is a jquery plugin which adds functionality to jquery allowing svg elements to be created.
I understand that it is a grouping for transformations. I have also looked through the documentation and have found nothing regarding this, but was wondering whether it is possible.
Fill it with a <rect width="whatever the <g> width is" height="whatever the <g> height is"/> and make the <rect> clickable. The rect can be transparent check out the pointer-events property for how to configure clicability of the <rect>.
You can find the <g> height and width by calling getBBox.
Assign id to element, and listener.
Ex.
<g id="clickg"><circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/><g>
$("#clickg").on("click",function () {
alert("click");
});
Super old question but it helped me out so I want to expand on one of the answers with a little more of a step-by-step guide and some more details. This is the method I made when my group was several disconnected items and I wanted the whole area including the blank areas in between to be clickable.
Get the x/y/width/height of the <g> element, you can do this easily in chrome dev tools by selecting the <g> element and entering $0.getBBox() in the console.
Create a new element as a child of your <g> like so: <rect x="TODO" y="TODO" width="TODO" height="TODO" style="pointer-events: all" />
Replace the TODO above with the info from getBBox
I'm trying to create (what I thought would be!) a simple re-usable bit of SVG to show three lines of text, with a background colour - to simulate a 'post-it' note.
I have found some useful code here to get the Bounds of the Text http://my.opera.com/MacDev_ed/blog/2009/01/21/getting-boundingbox-of-svg-elements which I am using.
So: I'm creating an group of text elements like this in the 'defs' section of my SVG:
<svg id="canvas" width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="post_it">
<text x="0" y="30" id="heading" class="heading">My Heading</text>
<text x="0" y="45" id="description" class="description">This will contain the description</text>
<text x="0" y="60" id="company" class="company">Very Big Company Ltd.</text>
</g>
And I'm displaying the text with a 'use' element like this:
<use id="12345" class="postit" xlink:href="#post_it" onclick="showId(this);"/>
I'm using the onclick to trigger a call to the following javascript function (defined in 'defs' section):
function showId(elem) {
post_it_rect=getBBoxAsRectElement(elem);
document.getElementById('canvas').appendChild(post_it_rect);
}
(The 'getBBoxAsRectElement(elem)' is from the link I posted).
As this stands; this works just fine - however if I change my 'use' element to position the text in a different place like this:
<use x="100" y="100" id="12345" class="postit" xlink:href="#post_it" onclick="showId(this);"/>
Now, the text displays in the correct place, but the resultant 'background-color' (actually a 'rect' element with opacity of 0.5) still shows on the top-left of the svg canvass - and the function used to calculate the rect is returning '-2' rather than '100' ('-98'?) as I need (I think).
What do I need to do to line up the 'rect' elements and the text elements ?
The author of the (very helpful article btw) script provides a more advanced script to draw a box round any 'bb' in an SVG, but I couldn't get this to work (missing 'transform' functions?).
I'm using Firefox 7.x to render the SVG ; and I'm loading a .svg file (ie, not embedded in html etc) straight from disk to test this).
Yes, you may need to compensate yourself for the x and y attributes on the <use> element for the time being, I'll try to find some time to update the blogpost and script.
Here's a draft SVG 1.1 test that among other things checks that the effect of the x and y attributes are included in the bbox. The line starting [myUse] is the one that tests this case, if it's red then that subtest failed. Chromium and Opera Next both pass that subtest, while Firefox nightly and IE9 doesn't. Note that the test itself has not gone through full review yet, and that it may still change.