Loading large images into svg component - html

I created an svg pattern which I feel with image. The thing is that the image is quite large (over 2mb) and it takes long to load (I keep it in assets folder in my app). However I checked that it works similarly with images that are large and downloaded from the web.
Is there a way to make big images load faster (so that this yellow svg pattern behind the image is not visible, while images did not finish loading) in svg?
<pattern id="pattern0" patternContentUnits="userSpaceOnUse" width="100%" height="100%">
<image xlink:href="https://images.hdqwalls.com/download/blue-light-buildings-architecture-8k-dv-7680x4320.jpg" x="0" y="0" width="100%" />
</pattern>
Example provided here
https://codepen.io/pokepim/pen/bGeMmNB
So as you can see the image laods slowly and the yellow black gradient is clearly visible at the beginning when page is loading.

One or more things you could do:
Reduce the resolution. 7680x4320 is way larger than you need for typical screen sizes.
Approx 15-20% of the image at the bottom is never visible. It could be trimmed.
Increase the compression ratio.
Just by reducing the size to 1600x700 (steps 1 & 2), I was able to reduce the file size to 250k, even with minimum JPEG compression.
Other things you could do:
Embed the image in the SVG as a Data URI (data://), so that the image loads as part of the SVG
Display a low resolution version of the image while the larger image is loading (eg BlurHash)

You can make the SVG hidden during the load and display it when finished loading with javascript.
You will need to add and reference ID to the SVG and make it hidden.
Then on image loaded, change to display block.
Here and example (not elegant one, don't use in production)
<svg
id="image-bg"
style="display: none;"
...
>
...
<pattern ...>
<image
...
onload="document.getElementById('image-bg').style.display='block'"/>
</pattern>
...
</svg>

https://css-tricks.com/illustrator-to-svg/
Here is a good website with some details.
Saving the svg with the image "embedded" in the svg as data rather than referencing it like that in the svg will vastly improve your load times.

Related

How to improve svg blur performance (in safari)?

I'm using feGaussianBlur on multiple spinning slotmachine reels to blur images. As the weels speed up, the stdDeviation is increased accordingly. This results in a very high CPU usage and laggs in the safari browser. Is there a way to improve performance? I read about css blur in some articles but they summarized, that the performance is the same.
Edit:
I tested css blur and the performance was even worse.
Blur, by its nature, produces partially transparent results. These need to be blended with the background. In the context of an animation, this can lead to high performance costs. I can see three ways to counteract this. They all aim at ensuring the browser does not need to compute a pixel-by-pixel blending operation but can simply copy image buffers into the area of the animation:
Use blur on elements that sit on a completely transparent background. That means, no colors at all in any background layer. Admitedly, this is not a very realistic scenario.
Make sure there is no partially transparent object on top of the animated object.
If it is not needed outside the opaque area of an object, restrict the blur filter region to the object area.
The third one sounds as if it could be applicable to your problem.
If the area that is blurred is rectangular, you could change the filter region itself. As a default, filters are computed for a region that goes 10% beyond the bounding box of the element it is applied to. To restrict this, set it differently:
<filter id="blur" x="0" y="0" width="100%" height="100%">
<feGaussianBlur stdDeviation="5" />
</filter>
But if your element has a different outline, you would have to set a clip-path to make sure the filter remains invisible outside.
Both approaches could probably benefit from setting the CSS property will-change: contents. But be sure to read the warnings about its usage: use it as a last resort, and use it sparingly.

Centred texts with different sizes in responsive SVG image

How can one get a scalable SVG image with texts with different sizes, all centred both vertically and horizontally?
What I would like to achieve:
What I have tried so far (JSFiddle demo):
<text x="50" y="30"
style="text-anchor: middle;alignment-baseline:middle"
fill="black" font-family="'Arial'" font-size="20">
H1 HEADLINE</text>
<text x="50" y="45"
style="text-anchor: middle;alignment-baseline:middle"
fill="black" font-family="'Arial'" font-size="15">
H2 HEADLINE</text>
Thanks in advance for any tips :) I cannot use JavaScript.
From section 10.1 of SVG 1.1:
SVG performs no automatic line breaking or word wrapping. To achieve the effect of multiple lines of text, use one of the following methods:
The author or authoring package needs to pre-compute the line breaks and use multiple ‘text’ elements (one for each line of text).
The author or authoring package needs to pre-compute the line breaks and use a single ‘text’ element with one or more ‘tspan’ child elements with appropriate values for attributes ‘x’, ‘y’, ‘dx’ and ‘dy’ to set new start positions for those characters which start new lines. (This approach allows user text selection across multiple lines of text -- see Text selection and clipboard operations.)
Express the text to be rendered in another XML namespace such as XHTML [XHTML] embedded inline within a ‘foreignObject’ element. (Note: the exact semantics of this approach are not completely defined at this time.)
As such, you need to either manually calculate the vertical location to get vertical centering, or use <foreignObject> to embed HTML+CSS within your SVG (at the correct location) which can perform vertical centering, e.g. using display:table-cell; vertical-align:middle.

Canvas Blur background

I'm a newbie regarding canvas and I've searched and tried alot, but never accomplished to find the right solution to use this one: http://www.quasimondo.com/BoxBlurForCanvas/FastBlurDemo.html
I want to use it with a image for a fixed background, so I can put the same non-blurred image on top, while having a changeable page, that changes design when exchanging the image.
I know I'm able to use CSS3 Filters for this but it doesnt work on Firefox and the performance of such a blurred big image is terrible...
Thanks!
"I know I'm able to use CSS3 Filters for this but it doesnt work on Firefox ..."
Firefox can do CSS blurring:
First, include an SVG file containing the desired blur in the web page
<svg xmlns:svg="http://www.w3.org/2000/svg">
<filter id="gaussian">
<feGaussianBlur id="myBlur" stdDeviation="5" />
</filter>
</svg>
Next, get a reference to the canvas element in the normal way, eg:
var canvas = document.getElementById('myCanvas');
... and apply the filter to it:
canvas.style.webkitFilter = 'url(#gaussian)';
canvas.style.filter = 'url(#gaussian)';
To change the blur value, you need a handle to the gaussian blur element itself:
var blurFilter = document.getElementById('myBlur');
Use the setStdDeviation(stdDeviationX, stdDeviationY) method to change the blur. Both arguments are numbers, not strings:
blurFilter.setStdDeviation(5, 5);
(Seems to work OK in latest versions of Firefox and Chrome - though Chrome doesn't like it when the blur values are set to 0 ...)

Embed SVG into HTML

I need to embed a SVG file into HTML file, the SVG's dimensions are bit larger. so, I need the SVG to be re-sized to the screen resolution. Is there any way to do that? Thanks.
If you want an SVG file to fit in a container the first thing to do is to set a viewBox attribute and remove width and height attributes from the root <svg> element:
<svg viewBox="0 0 100 200" ... >
The values of a viewBox are: x y width height. Read more in the SVG specification.
I dont know how complex is that SVG, but at least you can put whole description under one group , and then use transform="scale(SF)" whereas "SF" stands for scaling factor. Default is 1 (100%), so use little script:
TransFrm = "scale(" + SF + ")";
yourElement.setAttributeNS(null, "transform", TransFrm);
Or if you mean resizing by viewBox then <rect x="0" y="0" width="100%" height="100%"/>.
Or if you mean something else take a look at: http://janistoolbox.typepad.com/blog/2009/12/svgauto-resize-svg-on-an-html-page.html
Good luck.

best/shortest way to draw 1px grid in SVG

I need to draw a 1px grid (10px spacing) using the SVG canvas embedded within a webpage. There are many SVG tags to choose from and I was hoping someone could suggest what tags would be best suited for the job and produce the least amount of code.
For instance, is there a shorter alternative to plotting the path using the <path> tag? Perhaps by defining a square 10px x 10px then somehow repeating it accross the canvas.
Anyway, open to suggestions please.
Thanks
You can make a <pattern> (essentially the tile in your question) and fill any shape with that.
Here's an example of that technique.
I'm not an expert (day 3!), but I do know that Google uses rects to do this on Google charts, with either a width or a height equal to 1. Nothing fancy, just write the grid with lots of stuff like this:
<rect x="86" y="61" width="1" height="198" stroke="none" stroke-width="0" fill-opacity="1" stroke-opacity="1" stroke-dasharray="0" fill="#cccccc"></rect>
Why do they do this? Don't know. Their graphics are good, so someone has presumably thought about it. My own inclination is to do this with paths, using 'h' and 'v' for relative horizontal and vertical lines. It's more compact, but the output may not be so good.