Changing the size of the SVG image using JavaScript? - javascript

I have a .svg file that has the following code:
<svg version="1.1" x="0" y="0" width="256" height="256" viewBox="0 0 335 394">
plus a ton more code (namespaces etc) that is unnecessary to this situation, but the problem I have is that I need to somehow alter that width and height (from 256px to arbitrary size) using JavaScript. The .svg is being used like this:
<html>
<body>
<div style="background: url(example.svg);"></div>
</body>
</html>
I would really need to accomplish this somehow. Any ideas?
Update: I need this because I want a user to be able to set the base size for my user interface via a JavaScript control.

How about putting an <img> tag inside the div, and setting the width and the height on that?
<html>
<body>
<div>
<img src="example.svg" width="10px" height="10px" />
</div>
</body>
</html>
This will allow your browser to automatically scale the image based on the given dimensions.

Related

SVG text line height displays differently within img tag

I have created an SVG image which I am using within our website.
The SVG is displayed by inserting the XML into the HTML file, however, when loaded like this the SVG displayed differently compared with being displayed within an img tag.
<img src="http://elbrus.ecommercesuite.co.uk/Customisation Tool/SVG Templates/Bookmark.svg" />
I am just trying to reduce the line height within the following SVG:
https://jsfiddle.net/fahc2vvq/
I have to load in the XML version to edit the SVG within the website, Any ideas?
If you want a <foreignObject> to function correctly, you need to include a <body> element.
Note: I've removed the image from this demo to make it smaller.
<img src="http://elbrus.ecommercesuite.co.uk/Customisation Tool/SVG Templates/Bookmark.svg" />
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="73mm"
height="150mm"
viewBox="0 0 73 150"
version="1.1"
id="svg4523">
<g
id="layer1"
transform="translate(0,-147)">
<foreignObject
x="15"
y="150"
width="40"
height="60">
<body>
<p id="credit-card-text" style="font-size: 4px;text-align:center;text-anchor:middle;fill-opacity:1;font-weight:bold;line-height: 1;">Customise with your own message here.</p>
</body>
</foreignObject>
</g>
</svg>

SVG element width and height set in html but appearing as 0 0 in inspector

I have an svg rect like this:
<svg class="legend-square">
<defs>
<pattern id="pattern1" width="3"
height="3" patternunits="userSpaceOnUse" patterntransform="rotate(-45)">
<rect width="2" height="3" transform="translate(0,0)" fill="purple"></rect>
</pattern>
</defs>
<rect width="12" height="12" fill="url(#pattern1)"></rect>
</svg>
When I inspect the second rect with Chrome it has no width and height. There are no CSS rules applying to it. Why doesn't it get affected by width and height?
One of the reasons why SVG file is rendered on front-end with zero height and width is missing <svg> tag attributes "height" and "width".
Incorrect:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 49 30">
Correct:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 49 30" width="49" height="30">
It works fine.
If the snippet works individually but size of div containing it in you code appears 0x0 then look into : Why is my div's height zero
Its usually caused when float is set.
<div>
<svg class="legend-square">
<defs>
<pattern id="pattern1" width="3" height="3" patternunits="userSpaceOnUse" patterntransform="rotate(-45)">
<rect width="2" height="3" transform="translate(0,0)" fill="purple"></rect>
</pattern>
</defs>
<rect width="12" height="12" fill="url(#pattern1)"></rect>
</svg>
</div>
You really haven't provided enough information. For instance, what is the parent element of your SVG?
Just because your <rect> has a width and hight, it doesn't mean your SVG does. SVG is not like HTML, where elements expand to fit their children. SVG is like the <canvas> element. You have to make sure it either explicitly (or implicitly) has a size.
You have not specified width or height attributes for your <svg> element, so they are both defaulting to "100%". What they are 100% of depends on what size the SVG's parent element is. Hence my first question above.
For an 'inline' SVG element you have to apply the styles, inside the svg element itself.
inside the <defs></defs> tags. Since it has its Own DOM[Document Object Model], Css Apllied to it from Outside, will have no effect.
You have Several different options for embeding an SVG, You can use it inline as in your example where you declare the <svg></svg> inside of your html/php document or you can use one of the many other methods listed below;
embed an: ..............................................<img src="../pathtoyourSvg"></img>
embed as an img with a fallback option: <img src="logo.png" srcset="logo.svg" alt="My logo">
use an: ....................................................<object type="image/svg+xml" data="image.svg">
<!-- Your fall back here -->
<img src="image.svg" />
</object>
use: .........................................................<embed type="image/svg+xml" src="image.svg" />
use an: ....................................................<iframe></iframe>
embed the Svg inside of a canvas element using Javascript:
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "path2your.svg";
You may Also Embed the Svg using Css Background image,
ie:
.mySvgContainer{
background-image:url('PathToMySvg');
}
But from the comments & Questions I have read, this need to be either Url or Base64 encoded, which seems a bit Hacky and not very convenient.
each of them have their own advantages and disadvantages.
Because of security reasons, some SVG embedding methods will block access to external resources including CSS, fonts and javascript. Especially when we have multiple images, ideally our embedding method should be able to refer to a single CSS, font or javascript file (to save resources) and be able to manipulate our embedded SVG.
Also worth mentioning that if you have display:flex; attached to an elemnet or its parent then the width and height values will have no effect on the flex items. So It may appear as 0, 0, in the console.
Some Useful Information & related questions:
Svg Coords & Units w3.org
Svg Width - Height
Applying Styles to an embedded Svg
You can wrap your svg element inside the html5 object element.
<style type="text/css">
object{
width:300px;
height:200px;
}
object svg{
width:100%;
height:100%;
}
</style>
<object>
<svg class="legend-square">
<defs>
<pattern id="pattern1" width="3"
height="3" patternunits="userSpaceOnUse" patterntransform="rotate(-45)">
<rect width="2" height="3" transform="translate(0,0)" fill="purple"></rect>
</pattern>
</defs>
<rect width="12" height="12" fill="url(#pattern1)"></rect>
</svg>
</object>
You can set height and width on the object element just link any other html element while you can set height width to 100% for SVG element. It will work. But first, test your SVG by opening the file directly in chrome.

Modifying SVG after it has been loaded

How would I modify an SVG file after it has been loaded by the browser, preferably through jquery? A simple example would be pressing a button and the color of the SVG element changes. Any documentation would help as well.
EDIT: This link helped a great deal:
w3.org/Graphics/SVG/IG/resources/svgprimer.html#SVG_in_HTML
You can't "modify" SVG files (except by changing them on the server). SVG files define a collection of SVG objects, each of which can be identified with an ID, if you wish. These objects can be manipulated with JavaScript like you would any DOM element (e.g. setAttribute, etc). Check http://www.w3.org/TR/SVG11/types.html#BasicDOMInterfaces for the DOM interfaces. Notice that SVGElement extends Element, which is the basic DOM element type.
EDIT: simple example:
<html>
<body>
<input type="button" onclick="doSVGThing()" value="change">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect id="aRect" x="10" y="10" height="100" width="100"
style="stroke:#ff0000; fill: #9999ff"></rect>
</svg>
<script type="text/javascript">
function doSVGThing() {
var r = document.getElementById('aRect');
r.setAttribute('style', 'stroke: #00ff00; fill: #99ff99');
}
</script>
</body>
</html>

Combining SVG, HTML and Javascript

I have an HTML file that looks somehow like this:
<html>
<div id="test"> ... </div>
<object data="pic.svg" [...]></object>
</html>
Inside pic.svg, I have an element, let's say, a circle, and I want to realize something like that:
<circle onClick="doSomething()" [...]>
Now, in the js function doSomething() (i.e. when someone clicks on the circle) I want to change my "test"-div. How to do this?
You can access the parent document (and consequently the elements there) from inside the svg like this:
var divInParentDocument = window.parent.document.getElementById('test');
Here's a (slightly more complex) example showing how to call a function in the parent html document from inside an svg.
If you want the SVG to live in the same DOM as the HTML, best to use an embedded <svg> element. It's pretty well supported.
Something like
<svg id="svgroot" width="600" height="600"
version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<script type="text/ecmascript">//<![CDATA[
function doSomething() {
document.getElementById('test').appendChild(...);
}
//]]></script>
<circle onClick="doSomething()" />
</svg>

How to overlay data on an image

I am a rookie web developer and I am looking to put data points over an image that can be interacted with when hovered over, similar to most common map applications.
From my current understanding, using the Canvas in Javascript seems to be the best way to go, does anyone have any recommendations on how to do this and maybe point me in the right direction?
Does not require canvas although canvas can be used.
Shortest coding would be make a div with a background image being the image you want to place points on.
If it is not an image then you would need to make two divides on the overlay divide (the first one in the HTML code) use position:absolute to place it on top with the same width and height -- then the image content divide that follows will be layered under your absolute positioned divide.
<div style="background:url(image.jpg); width:100px; height:100px">
... material here is on top of the image ...
</div>
or
<div style="position:absolute; width:100px; height:100px">
... material here is on top of the image ...
</div>
<div style="width:100px; height:100px">
... place object here which picks up your map or whatever ...
</div>
The ... material here is on top of the image ... can be a canvas but SVG would be less coding as it has links supported
<div style="background:url(image.jpg); width:100px; height:100px">
<object data="yourOverlay.svg" width="100" height="100" >
</object>
</div>
Here is a sample SVG file posted at http://tutorials.jenkov.com/svg/a-element.html
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<a xlink:href="/svg/index.html">
<text x="10" y="20">/svg/index.html</text>
</a>
<a xlink:href="/svg/index.html" xlink:show="new">
<text x="10" y="40">/svg/index.html
(xlink:show="new")</text>
</a>
<a xlink:href="/svg/index.html" xlink:show="replace">
<text x="10" y="60">/svg/index.html
(xlink:show="replace")</text>
</a>
<a xlink:href="/svg/index.html" target="_blank">
<text x="10" y="80">m/svg/index.html
(target="_blank")</text>
</a>
<a xlink:href="/svg/index.html" target="_top">
<text x="10" y="100">/svg/index.html
(target="_top")</text>
</a>
</svg>
Depending on your application you may want to consider straight HTML for "... material here is on top of the image ..." so it will work in older browsers.
And FYI you could code the background into the SVG and just have a object tag in the html page and use googles "SVGWEB" http://code.google.com/p/svgweb/ to support nearly every browser.
Good resource here: http://dev.opera.com/articles/view/html5-canvas-painting/
But for what you're doing, you don't really need a canvas, imo. If you have an image, and you know where stuff is that you want to overlay (pixel offset), you can provide the pixel offsets from each data point in JSON or XML to your client script, and then just have it use absolute positioning to place them where they need to be on the image.
Another possible solution is to just use an SVG image which i believe supports links ect directly

Categories