I’m quite new to jQuery and JS and been asked to write a script that will be loading background-image progressively - I mean that low quality image should appear immediately and when full size image is loaded should replace the small one.
I found some tips how to do something similar by layering <img /> on top of background-image however in my case i have to deal with background-image only, so I have made this:
$('.img-loader').each(function(){
var box = this;
var smallImg = $(this).attr('style');
var bigImg = smallImg.replace('.jpg)', 'big.jpg)');
var imgUrl = bigImg.replace('background-image: url', '');
var imgUrlS = imgUrl.replace(/[{()}]/g, '');
console.log(imgUrlS);
$('<img/>').attr('src', imgUrlS).load(function(){
$(this).remove();
$(box).attr('style', bigImg);
});
})
The script basically does the job but in that moment when the image gets replaced there is a quite noticeable ‘shake’.
Any ideas how to make transition smoother or anyone knows what causing this 'shake'?
Edit: As suggested I'm adding a markup snipped of where script has to be applied.
<div class="about__section__bgimage img-loader"
style="background-image: url(<?php echo $contentBlock->imageurl ?>)"></div>
I suggest you create two separate elements with the same size, overlapping each other, with position: absolute; make one of them visible with the original bg image (using opacity: 1). The second one invisible (using opacity:0)
Once the higher quality image is completely loaded, set the opacity of the original image to 0 and the new image to 1.
use a css transition on the opacity property to make the opacities change smoothly.
you have to use animation for this. Use any of them according to your scenario enjoy it !!!
https://daneden.github.io/animate.css/
Related
I am using the basic jquery parallax plugin: parallax from Nike World
The standard way to call the basic jquery parallax is $('.parallax').parallax("50%", speed, height). I want to add one more argument 'img'. So: $('.parallax').parallax("50%", speed, height, img)
I am setting the vars as follows:
$('.parallax').each(function(){
var speed = $(this).data('speed');
var height = $(this).data('height');
var img = $this.data('img');
$('.parallax').parallax("50%", speed, height, img);
});
This should be pretty straight forward. Then in the parallax gist you can see that I added the arg in the fn.parallax call. Then I use it on line 63. The issue is that the image won't show. The background-position is the only rule output to the div.
Its poor mans debugging but I have console.log(img) all throughout the parallax.js and it shows the right image url.
What am I missing?
Per OP's request, here is my original suggestion in answer form:
At line 63, you add no-repeat on the end of the background-image declaration, which I think is incorrect. Have you tried removing no-repeat and assigning that property separately (using background-repeat)?
I'm applying a repeated background image from a canvas to a div via javascript like this:
var img_canvas = document.createElement('canvas');
img_canvas.width = 16;
img_canvas.height = 16;
img_canvas.getContext('2d').drawImage(canvas, 0, 0, 16, 16);
var img = img_canvas.toDataURL("image/png");
document.querySelector('#div').style.backgroundImage = 'url(' + img + ')';
I have to update it quite frequently. The problem is it flickers upon change, it doesn't appear to happen in Chrome but it's really bad in Firefox and Safari. Is it possible to stop this? I didn't think it would happen since it's a dataurl and therefore doesn't need to be downloaded.
Solution:
// create a new Image object
var img_tag = new Image();
// when preload is complete, apply the image to the div
img_tag.onload = function() {
document.querySelector('#div').style.backgroundImage = 'url(' + img + ')';
}
// setting 'src' actually starts the preload
img_tag.src = img;
Try to preload the image resource to the device storage by including the image in DOM like in the following HTML-Code. Maybe the error comes up because the image resource need to be loaded which takes some time (flickering).
<img src="imageToPreload.png" style="display:none;" alt="" />
You may prefer to use sprites-images. By using sprites your application will need less HTTP-Requests to load all ressources into your page. Also add the following CSS styles if you are using css animations. It will prevent background flickering on mobile devices:
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
Preload your image like this, no need to include a <img> with display: none
<link rel="preload" href="/images/bg-min.png" as="image">
Try adding this css to your background element:
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
It should help with flickering..
You can also "force" hardware acceleration by adding this to your background element:
-webkit-transform: translate3d(0, 0, 0);
Another option is to use image instead of DIV and change only the image url.
I struggled with this for a bit, tried preloading, appending the image to the document, etc.
In the end, I resaved the JPEG without the "Progressive" option.
That fixed the rolling flicker when the img src was swapped.
In my case changing height: 1080px; (background height) to height: fit-content;
I think that preloading all the images is essential in any case. What I found is that the way the browsers behave while changing the background image dynamically is different from one another. In Firefox for example it flickers when the change is frequent however in Chrome and Safari it doesn't.
The best solution I came up with so far is drawing the image inside a child canvas that fills the space of the whole parent div.
In all cases, the images you are using must be optimized as it affects the rendering performance.
My javascript code that works now, looks like this
const pic = new Image();
const pic2 = new Image();
pic.src="../images/settings_referrals_anim.gif";
pic2.src="../images/settings_referrals_still.png";
I don't actually reference that code in the query, for example, i use
document.querySelector(".button_Settings_referrals").addEventListener("mouseover", function() {
myDiv.style.backgroundImage = "url('../images/settings_referrals_anim.gif')";
But it seems to work. If I replace the long URL with const pic for example it doesn't work, and if I include the image object declaration and location at first time in the assignment, then the flickering stops.
This does not address all of the specifics noted by the OP, but might be useful for others. Tested in Chrome 97, Firefox 96, Android 11, iOS 15.
I have a div that includes these CSS parameters...
#div_image {
background-image: url( [Path to low-res image] );
background-size: cover;
}
I have a corresponding class that looks like this...
.div_image_highres {
background-image: none !important;
}
The corresponding class has a pseudo-element defined as follows:
.div_image_highres::before {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
content: " ";
background-image: url( [Path to highres image] );
background-repeat: no-repeat;
background-position: 50% 0;
background-size: cover;
opacity: 1;
display: block;
}
I have an img element that also points to the high-res image...
<img id="img_highres_preload" src=" [Path to high-res image ] ">
The img element has a corresponding style which allows the image to be displayed (ensuring that image file loads) but not seen...
#img_highres_preload {
width: 1px;
height: 1px;
}
Two notes: (1) I realize a lot of people use other methods of pre-loading (e.g., programmatically), but I have a personal preference for this method. (2) See the addendum about the reliability of the load event.
Last but not least, I have some Javascript (jQuery) that adds the "high-res" class to "div_image" once the high-res file is loaded...
$(document).ready(function() {
$("#img_highres_preload").off().on("load", function() {
$("#div_image").addClass("div_image_highres");
});
});
This could easily be vanilla JS, but since I use jQuery throughout my code, I like having a consistency.
Here's a summary of what's happening...
Presumably, the low-res image is loaded first and becomes the background image for the div. Even if that does not occur, everything will work as intended (i.e., the high-res image will be displayed).
When the high-res image loads into the img element (i.e., Javascript confirms that the high-res file is loaded), the "div_image_highres" class is applied to "div_image".
As result, the div switches to the high-res image without flashing. In my experience, if anything, it shifts a little to the left; but that often doesn't occur and, if it does, it's not inelegant.
And here's the primary reason I use this approach when required: In my application, there are multiple panels the user can navigate, which results in one panel sliding out of view and the new one into view. If I don't use a pseudo-element (as described above) for displaying a high-res image, the image flickers when its div is hidden and re-displayed. With the above-described technique, I can slide the div in and out of view without any flickering.
Regarding the Load Event
You can't depend on the load event firing. For instance, it typically does not fire when the browser has cached an image. So to make a long post even longer, here's the enhancement I have in my code to accommodate that reality...
I modify the document.ready event (shown above) to look like this:
$(document).ready(function() {
positionOnPage(true);
$("#img_highres_preload").off().on("load", function() {
checkImage();
});
});
checkImage = function() {
var image = $("#img_highres_preload")[0];
if (!image.complete || (typeof image.naturalWidth != "undefined" && image.naturalWidth == 0)) {
console.log("Waiting for high-res image.");
}
else if (!$("#div_home").hasClass("div_home_highres")) {
$("#div_home").addClass("div_home_highres");
$("#img_highres_preload").remove();
}
}
The checkImage function examines the image element to see whether an image has in fact been loaded. In this code example, it is a little redundant — that is, the img element has confirmed the load, so there's usually no need to check it (unless there is some reason to believe the file is being misloaded).
I might do it as shown because I also call checkImage from other places in my code, so if I have more of a programmatic response (unlike the simple version shown), I want all of that code in the same place and written just once. The checkImage function might be called when triggered by a timer or when the section displaying the intended image is about to be displayed. Perhaps something like this...
if (sectionName == "[whatever]" && $("#img_highres_preload").length === 1) {
checkImage();
}
In this example, I look for the presence of the preload img element because I know that my previous function removes the element after it has fulfilled its purpose.
This post has a stripped-down version to illustrate the concept. As written above, it only accommodates a single known img element, so the code could be extended to call checkImage with some parameters (e.g., the name of an image or the element itself) and checkImage could look for the existence of the preload element, so that check occurs in one place. It can be fairly fancy, so I went with the simplest example for this post.
In many cases, this stripped-down version is all I need because typically I only use a high-res photo for a window background image. I either start with the display of a low-res image and switch it out as soon as the high-res file is loaded, or I have some animation that gets triggered after I confirm the presence of the high-res image.
A good case for a more generalized version is when I need a series of images loaded at the outset and don't want to start until all of them are ready. In those cases, the web page might begin with some welcome text that stays displayed until all images have been confirmed.
Hey Guys I know this has been an older question but if you are still flickering after all this you can simply put the final version behind you background div. That flicker is seeing behind the image you currently have so if its the final image it will be smooth.
I need to add a Transparent image on top of all images on a page. The goal is if a user were to do a simple right click and save of an image, they would save the transparent image.
I do realize this is not a guaranteed method and that none exist to prevent image theft but simply a measure that a client wants added to prevent your average non tech person from saving images.
Using JavaScript I would like to find all images or all images within a certain Div.
Apply a new image overlay on top of these images that will have the same width and height of the image they are covering
I am not sure how to do this with JavaScript and was hoping someone would have a quick fix or example. I was unable to find anything so far on Google or SO. Appreciate any help
I have this JS which gets all images on a page so far...
// Get all images on a Page
function checkimages() {
var images = document.images;
for (var i=0; i<images.length; i++){
var img =images[i].src;
// Add new transparent image on top of this image
alert(img);
}
}
I would advise you to work with jQuery (or similar library) to keep things easier. I would even write a small jquery extension to make it easy to recycle the code, and apply it on any div (or other wrapper), wich child images you want to be overlayed.
My code would look something like this:
// jquery plugin to create overlays
// src is the url of the overlay image
// apply to any container that contains images to be overlayed
$.fn.overlayImages = function(src) {
// loop trough the images
$(this).find('img').each(function() {
// cache some variables
var $img = $(this);
var $parent = $img.parent();
// make the parent relative, if not yet absolute or fixed, for easy positioning
if ($parent.css('position') !== 'fixed' && $parent.css('position') !== 'absolute') {
$parent.css('position', 'relative');
}
// get the position of the image
var position = $img.position();
// clone the image
var $overlay = $img.clone();
// set the styling, based on the img, for exact positioning
$overlay.css({
top: position.top,
left: position.left,
position: 'absolute',
width: $img.width(),
height: $img.height()
});
// change the src attribute for the overlay
$overlay.attr('src', src);
// insert the overlay to the DOM
$overlay.insertAfter($img);
});
}
// when the DOM is loaded (not just ready, the images need to be there to copy their position and size)
$(window).load(function() {
// apply the overlay plugin to the wrapper of the images
$('#replace-images').overlayImages("http://www.riptideinnovations.com/images/watermark.png");
});
I added the step by step explanation inside the code as comments, but do feel free to ask if you want any further explanation.
I set up a small fiddle to demonstrate: http://jsfiddle.net/pP96f/6/
I don't know if this would help, but you could make your images all div's with backgrounds like this:
<div style="background-image: url('<your_image>');"></div>
I need to change my background div with some other images.
I want that first, myDiv load the first background image on css style, and then within 2/3 seconds of delay add a fade effect change the background image.
If it's possible, I need to do this with jQuery.
You cannot do fade or any other transitions directly on the background image. You can however add another div with second image as its background and fadeOut() the original one.
Does this do what you you want?
http://jqueryfordesigners.com/image-loading/
EDIT: A bit more Googling - this sounds like what you are trying to do...
http://www.magneticwebworks.com/jquery-rotating-page-background/
Edit: another go - THis? http://css-tricks.com/forums/discussion/9621/solved-is-it-possible-to-add-jquery-cycle-to-background-imagess/p1
this is not fade effect but you can delay and change background image like this.
function changebackground(){
$('#divID').css("background-image", "url(/myimage.jpg)");
}
setTimeout(function() { changebackground();}, 3000);
this might be good workaround
http://jquery.malsup.com/cycle/
after you position on top divs with cycle it can be your background - cycle.js give's you lot of options.
if you want only rotate image's in bacground you must first preload that image and second you must put it in other div so that both divs can animate.
There is no support for this, even if you add all the functionality of jQuery UI.
You could append a temporary image, absolutely positioned inside the div for which u want to change background. Let the image fade in, and once it's fully opaque, swap background image for the div. This will be problematic if you have a repeated background, however.
var im1 = 'picture1.png';
var im2 = 'picture2.png';
$('#divID').css({'background-image': 'url("'+im1+'")', 'position': 'relative'});
$('#divID').on('click', function() {
var img = $('<img />', {
src: im2,
}).css({
position: 'absolute',
top: 0,
left: 0
}).hide();
$(this).append(img);
img.fadeIn('slow', function() {
$(this).parent().css('background-image', 'url("'+im2+'")');
$(this).remove();
});
});
Of course, you should move the CSS I included in my script to a .css file, and use a class instead, for more readable code.
Are there any documents/tutorials on how to clip or cut a large image so that the user only sees a small portion of this image? Let's say the source image is 10 frames of animation, stacked end-on-end so that it's really wide. What could I do with Javascript to only display 1 arbitrary frame of animation at a time?
I've looked into this "CSS Spriting" technique but I don't think I can use that here. The source image is produced dynamically from the server; I won't know the total length, or the size of each frame, until it comes back from the server. I'm hoping that I can do something like:
var image = getElementByID('some-id');
image.src = pathToReallyLongImage;
// Any way to do this?!
image.width = cellWidth;
image.offset = cellWidth * imageNumber;
This can be done by enclosing your image in a "viewport" div. Set a width and height on the div (according to your needs), then set position: relative and overflow: hidden on it. Absolutely position your image inside of it and change the position to change which portions are displayed.
To display a 30x40 section of an image starting at (10,20):
<style type="text/css">
div.viewport {
overflow: hidden;
position: relative;
}
img.clipped {
display: block;
position: absolute;
}
</style>
<script type="text/javascript">
function setViewport(img, x, y, width, height) {
img.style.left = "-" + x + "px";
img.style.top = "-" + y + "px";
if (width !== undefined) {
img.parentNode.style.width = width + "px";
img.parentNode.style.height = height + "px";
}
}
setViewport(document.getElementsByTagName("img")[0], 10, 20, 30, 40);
</script>
<div class="viewport">
<img class="clipped" src="/images/clipped.png" alt="Clipped image"/>
</div>
The common CSS properties are associated with classes so that you can have multiple viewports / clipped images on your page. The setViewport(…) function can be called at any time to change what part of the image is displayed.
In answer to :
Alas, JavaScript simply isn't capable of extracting the properties of the image you'd require to do something like this. However, there may be salvation in the form of the HTML element combined with a bit of server-side scripting.
...
< ? (open php)
$large_image = 'path/to/large_image';
$full_w = imagesx($large_image);
$full_h = imagesy($large_image);
(close php) ? >
This can be done in Javascript, just google a bit :
var newimage = new Image();
newimage.src = document.getElementById('background').src;
var height = newimage.height;
var width = newimage.width;
This generates a new image from an existing one and captures this way in java script the original height and width properties of the original image (not the one id'ed as background.
In answer to :
The width/height properties of the document's image object are read only. If you could change them, however, you would only squish the frames, not cut the frames up like you desire. The kind of image manipulation you want can not be done with client-side javascript. I suggest cutting the images up on the server, or overlay a div on the image to hide the parts you do not wish to display.
...
var newimage = new Image();
newimage.src = document.getElementById('background').src;
var height = newimage.height;
var width = newimage.width;
newimage.style.height = '200px';
newimage.style.width = '200px';
newimage.height = '200px';
newimage.width = '200px';
and if wanted :
newimage.setAttribute('height','200px');
The doubled newimage.style.height and newimage.height is needed in certain circumstances in order to make sure that a IE will understand in time that the image is resized (you are going to render the thing immediately after, and the internal IE processing is too slow for that.)
Thanks for the above script I altered and implemented on http://morethanvoice.net/m1/reader13.php (right click menu... mouseover zoom lent) correct even in IE , but as you will notice the on mousemove image processing is too fast for the old styled IE, renders the position but only once the image. In any case any good idea is welcome.
Thanks to all for your attention, hope that the above codes can help someone...
Claudio Klemp
http://morethanvoice.net/m1/reader13.php
CSS also defines a style for clipping. See the clip property in the CSS specs.
The width/height properties of the document's image object are read only. If you could change them, however, you would only squish the frames, not cut the frames up like you desire. The kind of image manipulation you want can not be done with client-side javascript. I suggest cutting the images up on the server, or overlay a div on the image to hide the parts you do not wish to display.
What spriting does is essentially position a absolutely-positioned DIV inside another DIV that has overflow:hidden. You can do the same, all you need to do is resize the outer DIV depending on the size of each frame of the larger image. You can do that in code easily.
You can just set the inner DIV's style:
left: (your x-position = 0 or a negative integer * frame width)px
Most JavaScript Frameworks make this quite easy.
Alas, JavaScript simply isn't capable of extracting the properties of the image you'd require to do something like this. However, there may be salvation in the form of the HTML <canvas> element combined with a bit of server-side scripting.
PHP code to go about extracting the width and height of the really large image:
<?php
$large_image = 'path/to/large_image';
$full_w = imagesx($large_image);
$full_h = imagesy($large_image);
?>
From here, you'd then load the image into a <canvas> element, an example of which is documented here. Now, my theory was that you may be able to extract pixel data from a <canvas> element; assuming that you can, you would simply make sure to have some form of definite divider between the frames of the large image and then search for it within the canvas. Let's say you found the divider 110 pixels from the left of the image; you would then know that each "frame" was 110 pixels wide, and you've already got the full width stored in a PHP variable, so deciphering how much image you're working with would be a breeze.
The only speculative aspect to this method is whether or not JavaScript is capable of extracting color data from a specified location within an image loaded into a <canvas> element; if this is possible, then what you're trying to accomplish is entirely feasible.
I suppose you want to take a thumbnail for your image. You can use ImageThumbnail.js that created from prototype library in this way:
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript" src="ImageThumbnail.js"></script>
<input type="file" id="photo">
<img src="empty.gif" id="thumbnail" width="80" height="0">
<script type="text/javascript">
<!--
new Image.Thumbnail('thumbnail', 'photo');
//-->
</script>
for more information
try use haxcv library haxcv js by simple functions
go to https://docs.haxcv.org/Methods/cutImage to read more about his library
var Pixels = _("img").cutImage (x , y , width , height );
_("img").src (Pixels.src);
// return cut image
but try to include library first