How to implement lazy load for an SVG image element? - javascript

Within an svg tag, there multiple image elements, showing thumbnail images. Because of the large number of images, the page loading tooks a long time. So I want to implement an easy lazy load like David Walsh’s Simple Image Lazy Load and Fade. For img elements it works fine. But for image elements of an SVG area, the load will not be done.
Example:
<div>
<img id="myimg" height="20" width="20" data-src="img1.jpg"/>
</div>
<div>
<svg width="10%">
<image id="myimage" height="20" width="20" xlink:href="img1.jpg"/>
</svg>
</div>
And the JS coding:
// This works fine
var img = jQuery("#myimg");
img.attr('src', img.attr('data-src'));
img.on("load", function () {
img.removeAttr('data-src');
});
// This doens't work, onload will not be processed, image will not be not shown
var image = jQuery("#myimage");
image.attr('xlink:href', image.attr('data-href'));
image.on("load", function () {
image.removeAttr('data-href');
});
The scripting will leave the page in this way:
<div>
<img id="myimg" height="20" width="20" data-src="img1.jpg"/>
</div>
<br>
<div>
<svg width="10%">
<image id="myimage" height="20" width="20" data-href="img1.jpg" xlink:href="img1.jpg"/>
</svg>
</div>
Why is onload not working for this SVG image element?

You have several small mistakes:
<image/> is a self-closing tag,
xlink:href should be used without xlink: prefix,
it's better to set eventListener before you changing attribute.
See the snippet:
var image = jQuery("#myimage");
image.on("load", function () {
console.log('loaded');
image.removeAttr('data-href');
});
image.attr('href', image.attr('data-href'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg>
<image id="myimage" width="150" height="150" data-href="https://pbs.twimg.com/profile_images/843090368837042176/Nl-rCb9c_400x400.jpg"/>
</svg>

Here is my solution to the same problem where I keep using the xlink:href attribute for the raster image to show inside the SVG, but still lazy-load on click. I'm using different lazy-load plugin (jquery.lazy.js) but it's very similar:
<svg>
<image id="lazy-img" class="lazy" width="" height="" data-source="myimage.jpg" />
</svg>
$('.someElement').on('click', function() {
var image = $('#lazy-img");
image.attr('xlink:href', 'myimage.jpg');
image.attr('href', 'myimage.jpg');
});
The idea is that the initial HTML markup is for the lazy-loading images and on click event we are swapping the markup back to work with SVG, after the image is lazy-loaded.

Related

How do I render and edit SVG data in React?

Let's say that I have an SVG file in my database:
<svg width="400" height="100">
<rect width="400" height="100"
style="fill:rgb(0,0,255);stroke-width:10;stroke:rgb(0,0,0)" />
</svg>
It looks like this
And in my React code I fetch the SVG file like so:
fetch('/api/picture')
.then(res => res.json())
.then(res => {
this.setState({
picture: res
})
})
So now in my state, I have a variable called picture whose value is this:
<svg width="400" height="100">
<rect width="400" height="100"
style="fill:rgb(0,0,255);stroke-width:10;stroke:rgb(0,0,0)" />
</svg>
After doing some research, the only way that I have found to render the SVG is this way:
<div>
<div dangerouslySetInnerHTML={{ __html: this.state.picture }}></div>
</div>
But I'm a little confused on whether this is the preferred and flexible way to do it.
If I want a button on my page where if I click it, the circle will turn red, how will I be able to do that with my current code? What about a button that will add another circle to the svg?
I know I have to access the rect in some way and change the style, but I cannot think of a way with the way I've set it up.
I tried looking for a solution but I can't seem to find one, so I'm under the impression that I have to render my SVG a different way. Could anyone help me figure this out? Thank you
I created https://github.com/hugozap/react-svgmt to facilitate SVG loading and manipulation:
You can load the SVG from a url or string and use SvgProxy to
update any element using a CSS selector.
<SvgLoader width="100" height="100" path="/sample1.svg">
<SvgProxy selector="rect" fill="red" />
</SvgLoader>
If you are interested I wrote an article about it sometime ago
https://medium.com/#hugozap/svg-manipulation-tools-for-react-e1d58b754c81

SVG Image xlink:href is not working with knockout

I am trying to render a svg image with knockout, but it is not showing image after I successfully bound the viewmodel.
Here is the SVG
<svg width="500" height="500" style="border: solid 1px black">
<image id="img1" width="500" height="500"
data-bind="attr:{'xlink:href': image}"></image>
</svg>
Here is the knockout bindings,
<script>
var viewModel = function(data){
var self = this;
self.image = ko.observable(data.image)
};
var data = {image: "http://2.bp.blogspot.com/-cGeVTe2XeWU/VUEiQidIJKI/AAAAAAAACwU/UYzCrcNMMAk/s1600/comic.png"};
var vm = new viewModel(data);
ko.applyBindings(vm);
</script>
Anyway I checked the page source after executing this code. So the SVG image element in page source is
<image id="img1" width="500" height="500" data-bind="attr:{'xlink:href': image}" xlink:href="http://2.bp.blogspot.com/-cGeVTe2XeWU/VUEiQidIJKI/AAAAAAAACwU/UYzCrcNMMAk/s1600/comic.png"></image>
As you can see here, it is setting xlink:href correctly, but it is not showing on svg.
Do I need to refresh DOM somehow?
Simply how can I render SVG image using knockout?
Any help will be appreciated
xlink:href attribute needs to be there even with empty value to initialize the HTML svg image.
so image tag should be like Here is a demo and more info
<image id="img1" width="500" height="500" xlink:href=""
data-bind="attr:{'xlink:href': image}"></image>
SVG elements are not added to the DOM when you use an img element to display the image, therefore knockout.js is unable to bind to those elements. The answers to this question contain some solutions that might help you:
How do you access the contents of an SVG file in an <img> element?
Note: I get this solution from Stackoverflow.

Imacros. How to save several images with changing attributes?

I need to save 4 images everytime i refresh a website, the problem is, it only has 1 attribute that is different in all these images and it changes into a randomly generated string everytime i refresh the page. the HTML of these images are:
<img alt="" width="35" height="40" src="data:image/png;base64,HJFFSYYEYGUG3r236=">
<img alt="" width="35" height="40" src="data:image/png;base64,UASFsACUYASYGU6=">
<img alt="" width="35" height="40" src="data:image/png;base64,FHJASFUYYetetgts=">
<img alt="" width="35" height="40" src="data:image/png;base64,ete6tdrte6r=">
so as you can see the only the src attribute changes. How do i save all 4 of these images every time i refresh the page?
Replace the changeable part of SRC-attribute with the wildcard * and run the macro in loop mode (with the max. loop number = 4):
TAG POS={{!LOOP}} TYPE=IMG ATTR=SRC:"data:image/png;base64,*=" CONTENT=EVENT:SAVEITEM
If it doesn’t work, try the event:
... CONTENT=EVENT:SAVE_ELEMENT_SCREENSHOT

Javascript lazy load images by id

I have a page with a very long list of images and I'm looking to lazy load them. But instead of loading the images when they appear in the viewport, I want to load them in order of id when the page is ready. Is there any way to do this?
Here is my markup. My goal would be to load realimg1, realimg2, realimg3, etc in order.
<img src="loading.png" width="300" height="200" id="id1" data-src="realimg1.png">
<img src="loading.png" width="300" height="200" id="id2" data-src="realimg2.png">
<img src="loading.png" width="300" height="200" id="id3" data-src="realimg3.png">
<img src="loading.png" width="300" height="200" id="id4" data-src="realimg4.png">
<img src="loading.png" width="300" height="200" id="id5" data-src="realimg5.png">
Right now, I'm using this plugin just lazy loading images by replacing the src with data-src when the image come into the viewport. How would I do the same thing but do it on load in order of id instead of when they appear in the viewport?
I don't think you will find the lazy loading to be of any use as it's functionality is entirely directed at loading based on images appearing in the viewport.
Check this out:
Hi, this demo might be of interest to you
http://nettuts.s3.amazonaws.com/860_preloaderPlugin/index.html
and the corresponding tutorial is here:
http://net.tutsplus.com/tutorials/javascript-ajax/how-to-create-an-awesome-image-preloader/
it uses a jQuery plugin that is called like this:
<script type="text/javascript">
$(function(){
$("#gallery").preloader();
});
</script>
Where
<ul id="gallery" class="clearfix">
<li><p><img src="images/1.jpg" /></p></li>
<li><p><img src="images/2.jpg" /></p> </li>
<li><p><img src="images/3.jpg" /></p> </li>
<li><p><img src="images/4.jpg" /></p></li>
<li><p><img src="images/5.jpg" /></p> </li>
</ul>
source: http://wpquestions.com/question/showChrono/id/7959
<script>
function lazyLoader(id){
var images = document.getElementById(id).getElementsByTagName('img');
for(prop in images){
images[prop].setAttribute('src', images[prop].getAttribute('data-src'));
}
}
// should be called after document ready or load -
lazyLoader('lazy_loader');
</script>
You can use the justlazy plugin, which prevents to use external dependencies. It can load by id. You only have to provide the images to load.
For your images you can call the library as follows:
var placeholders = document.querySelectorAll(".some-class-of-images-to-load");
for (var i = 0; i < placeholders.length; ++i) {
Justlazy.lazyLoad(placeholders[i]);
}
The placeholders have to be in the following structure:
<span data-src="default/image" data-alt="some alt text"
class="some-class-of-images-to-load">
</span>
For SEO reasons you can use any other placeholder element.

SVG in Fancybox

I need svg image in fancybox.
<div id="data">
<svg width="400" height="110">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)">
Sorry, your browser does not support inline SVG.
</svg>
<img src="http://fc03.deviantart.net/fs71/f/2011/260/e/1/circle_png_by_xdicsii-d4a2odp.png" />
<a id="inline" href="#data" style="margin-left:15px;">Full Screen</a>
</div>
I want to get full screen of the div with id "data".
When i click on "Full Screen" i'm getting full screen of div with id"data" with jpg images, but not the svg image(Which is rendered into the div)
<div style="height:inherit; width:inherit"></div>

Categories