I am getting svg data by api call and appending it to div in a DOM. There are 13-14 svg elements I am getting and appending it to a single div. I want to display all this svgs in a row. If I give width: 5.5%; to svg elements, all the svgs display in a row. But when I resize window or monitor size is small, all svgs overlap each other. I've created an example in jsfiddle. Please find this fiddle
I tried with preserveAspectRatio and viewBox in svg but it's not working.
Update: I've updated fiddle. In a default size of resule in jsfiddle, overlapping is visible. I want it to be responsive.
How do I make these svgs responsive so that it doesn't overlap each other?
For these purpose better to use img tag:
<img src="path_to_svg" style="width: 5.5%" />
And in the svg file you should add attribute such as
<svg width="100%" height="100%"> .... </svg>
In this case image will resize as you want.
Related
This question already has answers here:
How can I change the color of an 'svg' element?
(40 answers)
How to change color of SVG image using CSS (jQuery SVG image replacement)?
(18 answers)
Closed last year.
This post was edited and submitted for review last year and failed to reopen the post:
Original close reason(s) were not resolved
I am writing an SVG editor program. I am trying to implement highlighted feel for when an element (<image>, not <img>) is clicked. I have implemented this for other elements like <circle>, by setting stroke, stroke-width, and stroke-dash-array. But setting the presentation attributes of the <image> tag, either by setting the attributes directly or through CSS styling, is not taking effect. I also tried the border style but it's not working. How can I achieve this?
According to MDN , <image> is meant to have have global attributes, including presentation, which ultimately means this should work. If you also inspect <image> with a browser you will see it will highlight like it follows box model.
<svg viewBox="0 0 1370 1170" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="128" height="128" x="617.9207153320312" href="data:some-valid-link" style="stroke-width: 3px; stroke-dasharray: 7px;" stroke="#3aa2c2"></image>
</svg>
I don't think that you can set stroke on an image.
Usually those attributes are used to 'draw' vector image. Here you're trying to put a stroke on a raster image.
If you want to put lines around a square image you could use a border to achieve it.
If you want to put lines around a complicated shape, I don't think it's possible to do that in CSS. You would need to add that in graphics software.
You cannot restyle an external SVG, if you load it in an <img> tag.
Instead, you could paste the <svg> code directly into your HTML, and apply styles like this (source svg):
svg {
width: 500px;
}
svg path,
svg polygon {
stroke-width: 10px;
stroke-dasharray: 10px;
}
<svg height="210" width="500">
<polygon points="100,10 40,198 190,78 10,78 160,198" style="fill:lime;stroke:purple;stroke-width:5;fill-rule:nonzero;"/>
Sorry, your browser does not support inline SVG.
</svg>
You would need and SVG with a more specific code targeting all the vectors and not just a tag. Then you could make groups of the parts of the image/draw you want to style. You can do this by using illustrator, then after grouping the parts, your code will have a 'g' tag: <g id="group_to_style" > with an ID that you have named when doing the groups. Then using CSS you can target the groups of the SVG and style or even animate. Like gru said, with an you cant style or animate anything.
I'm using D3.js to render g SVG elements, each containing a foreignObject so that I can attach a styled div text. The HTML looks like this:
<g class=node ...>
<circle ...></circle>
<clipPath ...>
<circle ...></circle>
</clipPath>
<image ...></image>
<foreignObject ...>
<div ...>...</div>
</foreignObject>
</g>
There are 60 of these elements contained in a parent g element which is translated with transform: translate(...) when the user scrolls.
Here, the foreignObject has height=1 and width=1 with overflow: visible. This allows the contained div to be sized based on the text it contains.
This works fine on Chrome and Edge (and Safari if I remember correctly), however on Firefox, the div element inside foreignObject gets 'clipped' when I call translate on the parent g element. The image below shows the correct rendering:
And the image below shows the rendering during translate.
I suspect this has something to do with the width and height of the g elements (i.e. node class) because the clipping occurs outside the boundary of g. How would I fix this? I've thought of using JavaScript to modify the width and height of g, but these attributes are based on the rendering which I don't know in advance.
Any help is appreciated!
Turns out this is fixed by setting the width and height properties of foreignObject to 100%.
I am placing an angular directive inside a dynamically-sized element. The directive itself consists of an SVG which is computed based on the element size. I am trying to make the SVG auto-resize and redraw based on the size of the container.
I initially tried something like this:
my-directive.js
angular
.module('myModule')
.directive('myDirective', function () {
return {
templateUri: 'path/to/my-directive-template.html',
...
};
});
my-directive-template.html
<svg style="width: 100%; height: 100%; max-width: 100%; max-height: 100%">
...
</svg>
Note the style attributes on that SVG element. This resizes correctly in Chrome, but fails to work in Firefox. Also, I still don't have a hook to recalculate the SVG contents.
I've also tried adding an onresize handler to the element in the link function, However, JQLite supports onresize only on the main window. I cannot use window.onresize, because my window size does not change.
I've tried to use the answers here: AngularJS - bind to directive resize, but they don't give the required results either.
In short, here's what I am trying to do:
Resize the SVG element inside the directive when the parent element resizes.
Re-calculate the SVG contents by calling some handler function when this happens.
I would prefer not to add a JQuery dependency at this point in the project.
This behavior can be achieved using the viewBox and preserveAspectRatio attributes of the <svg> tag.
First, set the viewBox attribute to a normalized bounding box for your SVG image. Your entire drawing should be scaled to fit inside this view box. For example,
viewBox="0 0 100 100"
will set up a coordinate system with the origin at (0, 0) and having the dimensions 100 units x 100 units.
Next, set the resizing behavior using the preserveAspectRatio attribute.
The first part of the value determines the alignment of the SVG with respect to the parent element. This includes left/right/center horizontal alignment and top/bottom/middle vertical alignment. For example,
preserveAspectRatio="xMidYMid ..."
will align the SVG centrally in its container.
The second part of the value determines how the SVG fills the container. For example,
preserveAspectRatio="... meet"
will scale the SVG such that it just fits within the container without cropping.
So the complete example becomes:
<svg viewBox="0 0 64 64" preserveAspectRatio="xMidYMid meet">
...
</svg>
Because the image scales automatically with the container, there is no need to recalculate the positions of the content elements. It is handled automatically by the SVG tag.
Given an SVG like the one from this Google Visualization Example, there are circles drawn on the svg like this:
<circle cx="448.0843694002127" cy="236.6677163333033" r="12" stroke="#cccccc" stroke-width="1" fill="#0000ff"/>
I tried using firebug to manually replace that with a sample image at the same x/y coordinates, so for instance replacing the above code with:
<img width="50px" height="50px" cy="135.71439117815066" cx="343.43783232923863" xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Flag_of_Fukuyama%2C_Hiroshima.png/320px-Flag_of_Fukuyama%2C_Hiroshima.png">
But that doesn't work (nothing seems to render properly). I thought perhaps using cx/cy was the issue, so I tried switching those to just regular x/y properties:
<img width="50px" height="50px" xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Flag_of_Fukuyama%2C_Hiroshima.png/320px-Flag_of_Fukuyama%2C_Hiroshima.png" x="343.43783232923863" y="135.71439117815066">
Again, no-go.
I tried the technique used here:
Does SVG support embedding of bitmap images?
But again, it didn't render the image in the SVG.
I checked all over Stack Overflow, but found information only on how to tile a circle with an image:
Add a background image (.png) to a SVG circle shape
This has its own set of images as the pattern just tiles and can't be resized for each shape.
Is there any reliable way of doing this? Ideally, I want to loop through each circle and replace it with an image that will be sized to the circle it replaces.
I downloaded the SVG and added the image manually, but I get the following error:
XML Parsing Error: prefix not bound to a namespace
Location: (removed
for privacy)
Line Number 2, Column 1:<image width="50px"
height="50px" y="135.71439117815066" x="343.43783232923863"
xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Flag_of_Fukuyama%2C_Hiroshima.png/320px-Flag_of_Fukuyama%2C_Hiroshima.png">
^
The element you want is <image> not <img>.
And the attributes cx and cy are meaningless on <image> elements. You can use x and y instead (like in your second attempt), and note that you are required to specify a non-zero width and height on the <image> element (again like in your second attempt). See the svg spec for the details.
Just create a mask using an image. The draw the circle or any other graphics referencing the mask.
I have a resizable div. It has two inner divs. One of the inner divs has an svg element in it.
In the svg element I am adding and removing the content dynamically such that each time I add something in my svg. I increase its height by adding 20px to it and when I remove I subtract the height by 20px. When my svg height become greater than its parent div a scroll bar appears in the parent div. Similarly scroll bar is removed when svg height is less than parent div.
The problem starts when I do the resizing. I have added a viewbox option in my svg for resizing. But when I increase the size some of my svg elements are not visible.
And when I decrease the size my svg get placed at a lower position leaving empty space.
Its all messed up in my mind that how to deal svg position/height with viewbox property.
I have tried to make a fiddle to simulate the behavior somehow. But here elements in svg are not adding dynamically and the svg height is constant.
Link to my code
Any help will be appreciated
LATEST UPDATE:
Most important if you're going to use SVG it is better to be acquainted with spec or read a definite guide like "SVG Essentials" by J. Eisenberg, cause it is not such a trivial thing you might think at first.
Then if I understood you right, there is another approach jsFiddle.
First, set correctly the value of the viewBox attribute. In your current example in should be viewBox="0 0 130 220" so that all you content be visible (you have to specify at least 220 as the last number cause your last group <g> is translated i.e. it's coordinate system moved down to 200 units, if you don't do that your content will be not visible cause it is far beyond the outmost y-point of your viewbox, which in your jsfiddle is set to 70).
Second, specify the correct value for preserveAspectRatio which should be preserveAspectRatio="xMinYMax meet", which means (courtesy of the "SVG Essentials" by J. Eisenberg):
Align minimum x of viewBox with left corner of
viewport.
Align maximum y value of viewBox with bottom
edge of viewport.
meet means meet the content, not slice it, if it doesn't fit.
Third, if you are going to add elements to the bottom of your svg you have to change the viewBox value accordingly, cause if you will insert into it smth like:
<g transform="translate(0, 300)">
<text>text 55 </text>
</g>
it will occur beyound your viewBox, which has a max y-point at 220 (if you would set it as I said earlier)
For now hope that helps, let me know.
OLD STUFF
remove style="height:200px" from your svg
Then if you need height, you can dynamically change the height of your svg
var $wrapper = $('#resize'),
$svg = $('#svg2');
$wrapper.resizable({
handles: 'se',
aspectRatio: 400/200,
resize: function(ev, ui) {
$svg.css('height', ui.size.height);
}
});
'#resize' - is the id of the wrapper of the svg
I'm now very confused of what you want. You specified viewbox attr on the svg. That means that only a part of your svg will be visible. Try to remove viewbox and see whether result looks satisfactory for you.
It then be all visible and normally adjusted to parent div