I have some issues with page speed depended on images that I get from server and just want to know if it is possible to get different file according to screen that page is displayed on. I found
if( typeof( window.innerWidth ) == 'number' ) {
//Non-IE
xx = window.innerWidth;
yy = window.innerHeight;
} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
//IE 6+ in 'standards compliant mode'
xx = document.documentElement.clientWidth;
yy = document.documentElement.clientHeight;
} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
//IE 4 compatible
xx = document.body.clientWidth;
yy = document.body.clientHeight;
}
That is possibly providing variable for later use, mainly I am focused on aspect if it is possible to get different img size througt
{php} $x=1; $this->assign('varX',$x); {/php}
{foreach from=$offer->GetPhotos() item=photo}
{if $varX ==1}
{assign var="fotourl" value=$photo->GetImgSrc('253_161', false, false, false)}
<div class="item active">
<a href="oferta.html?id={$offer->GetId()}">
<img alt="Front view of the house." class="lazyload img-responsive wp-post-image" data-original="{$photo->GetImgSrc('253_161', false, false, false)}" height="161" src="{$photo->GetImgSrc('253_161', false, false, true)}" width="253"></a>
</div>
{else}
<div class="item lazy-load-item">
<a href="oferta.html?id={$offer->GetId()}">
<img alt="Luxury Villa In Rego Park" class="img-responsive" data-lazy-load-src="{$photo->GetImgSrc('253_161', false, false, true)}"></a>
</div>
{/if}
{php} $x=$x+1; $this->assign('varX',$x); {/php}
{/foreach}
I want to achieve moment when I can get different size of photo for desktop and mobile
Thank You in advance
What you're looking for is called 'responsive design'; that is, as site where the page adapts to the size of the browser window. It's a very common requirement, and involves a lot more than just adapting the image sizes. But image size is one aspect of it.
In today's internet, you should not need to do any server-side scripting at all in order to achieve a good responsive design.
Page layout can adapt dynamically to screen size by the use #media blocks in your CSS. This is the most common thing people think of when talking about responsive design.
Image file sizes (the bit you're asking about) can be made responsive by use of two relatively new HTML features: scrset and the picture element.
scrset is a new attribute for the existing <img> tag. It allows you to specify different image files for the element, and for the browser to chose the most appropriate one based on the screen size. You would use it like so:
<img src="default-size.jpg" srcset="medium-size.jpg 1000w, large-size.jpg 2000w">
You can read more about srcset here.
The picture element is more complex. It does much the same thing, but allows the developer much more control over exactly which image is displayed, rather than leaving it to the browser. An example:
<picture>
<source srcset="smaller-image.png" media="(max-width: 800px)">
<img src="default-image.png">
</picture>
In this example, you are telling the browser to use the smaller image when the page is viewed in a small browser window less than 800 pixels wide, eg maybe on a mobile device. You're being more explicit about it than the plain srcset example.
Find out more about the picture element from MDN.
Note that both of these HTML features are relatively new, and thus may not be supported on older browsers. However they have been supported long enough to be in place for the majority now, and both of them have a graceful fallback of defaulting to the main image in the <img> tag if they aren't supported by the browser. Thus your IE9 user will just see the original base image regardless of his screen size; but it will at least work for him at that level.
So in summary, you should not need any PHP code for this, nor any JavaScript code. Just learning a few new bits of HTML.
[Edit] Regarding the browser support point I mentioned above, #FodorZoltán suggested that I link to the compatibility tables:
http://caniuse.com/#search=picture
http://caniuse.com/#search=srcset
This can be only handled on client-side by javascript: (the second aproach is cleaner)
Get your different sized image paths from PHP into JS
var images = { 'image1ID' : {large: '{$image1largepath}', small: '{..}', ..}, 'image2ID': .. };
On document load get the size of the screen in JS
Loop the images array above, get the element by id(which is the key in the array), and update src attribute according to the screen size
Another way would be by setting attributes on your images: img-dynamic, large-src='', small-src='' etc. and runing a function in JS that would get the size of the screen, get all img elements with this img-dynamic and set their src attributes value to the large-src or small-src value according to size.
var windowH = 800, windowW = 1000;
/* First get window sizes */
function setDynamicImagePaths(to){
var imgs = document.querySelectorAll('img[img-dynamic]');
for(var i = 0, l = imgs.length; i < l; i++){
imgs[i].src = imgs[i].getAttribute(to);
}
}
/*
When your sure that the img elements are loaded
ex: onload or at the end of the body
call this
*/
window.onload = function(){
if(windowH > 700 && windowW > 900)
setDynamicImagePaths('src-large');
else
setDynamicImagePaths('src-small');
}
<img img-dynamic width='100' height='100' src-small='noimgpath' src-large='https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg'/>
Related
I'm working on a responsive website where all viewport versions share the same HTML/CSS. The problem is that I don't need all images from the desktop version displayed on the mobile version. I hide those elements with display: none in my CSS.
Nevertheless the browser downloads those images because the HTML gets parsed before CSS layout happens. But I just want to download the images which I need for the mobile version so I can reduce HTTP requests and the overall download size.
A solution for me was to use the <picture> element like this:
<picture>
<source srcset="image.jpg" media="(min-width: 992px)">
<img src="" alt="an image">
</picture>
The image will not download when the browser window width < 992px because I let the fallback source attribute empty src="". Unfortunately Safari doesn't support it yet. Therefore I don't want to use it.
Now I came up with my own JavaScript/JQuery stuff but I'm not sure if it's a good idea.
HTML:
<img src="" alt="img" data-device="mobile" data-src="img-mobile.jpg">
<img src="" alt="img" data-device="tablet" data-src="img-tablet.jpg">
<img src="" alt="img" data-device="desktop" data-src="img-dektop.jpg">
JavaScript:
function loadImages() {
var mobile = window.innerWidth < 768;
var tablet = window.innerWidth >= 768 && window.innerWidth < 992;
var desktop = window.innerWidth >= 992;
if(mobile) {
$('[data-device]').each(function() {
if($(this).attr('data-device') === 'mobile') {
$(this).attr('src', $(this).attr('data-src'));
}
}); // end each
} else if(tablet) {
$('[data-device]').each(function() {
if($(this).attr('data-device') === 'tablet') {
$(this).attr('src', $(this).attr('data-src'));
}
}); // end each
} else if(desktop) {
$('[data-device]').each(function() {
if($(this).attr('data-device') === 'desktop') {
$(this).attr('src', $(this).attr('data-src'));
}
}); // end each
}
}
$(document).ready(function() {
loadImages();
});
$(window).resize(function() {
loadImages();
});
The browser parses the HTML with empty src attributes. After the page finished loading, loadImages() will be called.
For example, if the browser width is < 768px. The function iterates through all elements with a data-device attribute. It will check the data-device value and if it's mobile it will take the value from the data-src attribute and puts it as a value to the actual image src attribute.
This means that the browser will just download and display the images for the mobile version of my site.
However, I don't like this. It looks like hacked together to get around this problem somehow. I mean there must be another solution to this because I'm sure that everybody who works with responsive sites will soon or later run into the same issue. I have googled this problem a lot but I haven't found a satisfying solution yet. Everybody is saying something different.
How you guys are tackling this problem? What is the best practice?
I must say that your idea to workaround the issue looks good.
Just another idea, how about replacing the img element for a div element and load a background-image using the #media styles in css for each device? That will load one or another image depending on which device is used, and I believe that is something lots of developers use these days.
Hope that helps!
I have function that is supposed to wait till background image is loaded and then add image's ratio to it's container and fade background image container in. It seems to work in Chrome, but fails in Internet explorer 8 and 9, and not always works in 10. In ie8 it doesn't seem to understand jquery on('load') event. In ie 9 and 10 it not always finds width of background image. How can I make it work in ie8+ and other major browsers?
js:
$('.item').each(function(index) {
var thisItem = $(this);
var image_url = thisItem.find('.img').css('background-image');
var img = new Image();
img.src = image_url.replace(/(^url\()|(\)$|[\"\'])/ig, '');
if (image_url){
//initialize only when background img is loaded
var $img = $('<img>').attr('src', img.src).on('load', function(){
//don't allow img to be larger than it is
if(img.width < thisItem.width()){thisItem.css({'max-width':img.width+'px'});}
var ratio = img.height/img.width;
thisItem.find('.item_ratio').css({'padding-bottom':ratio*100+'%'});
thisItem.find('.img').fadeIn(800);
});
}
});
html:
<div class="item">
<div class="img" style="background-image:url('some_url'); width: 100%; background-size: cover;"></div>
<div class="item_ratio"></div>
<!-- Some other not important html ->
</div>
The load event on images has been shown to be unreliable/absent, which is why there's a well-known jQuery plugin to help smoothen things out cross-browser. I'd recommend having a look at that instead rather than trying to figure out the browser issues and edge cases like missing load events when browsers fetch images from cache etc.
Edit: code sample to make it work with a dangling <img/> (untested)
//initialize only when background img is loaded
var $img = $('<img>').attr('src', img.src).prependTo(thisItem).hide().imagesLoaded(function() {
//don't allow img to be larger than it is
//... [your code]
});
I used this approach here. (The thumbs on the left are a single background image sprite, I animate those in once the image has loaded).
As an aside, you may also be able to use background-size: contain in CSS. Doing that might be more performant in newer browsers (if images are large) and much simpler since you don't need any code. It's unsupported in IE8 though, which you can test if you're using Modernizr. That would probably be my preferred approach, but I normally include Modernizr anyway. YMMV.
I've got couple of lines of JavaScript using jQuery to resize images to thumbnails.
var thumb = $(this);
thumb.load(function() {
var ratio = thumb.height() / config.maxHeight;
var newWidth = Math.ceil(thumb.width() / ratio);
thumb.height(config.maxHeight);
// this line matters
thumb.width(newWidth);
});
Fotunately this works fine. But if I replace the last line with:
thumb.width(Math.ceil(thumb.width() / ratio));
It changes width of images that hasn't got explicitly defined dimensions badly (too narrow). To me, it seems like totally equivalent ways - via a variable or directly - but obviously they're not.
I tried casting the ceil() result to a Number or Integer and it behaved opposite way - images with undefined dimension were OK but the rest was too wide (width of original image).
Although I the first solution works I guess there's something fundamental I'm missing. So I want to avoid it in the future.
Thank you!
I would guess that the <img> element you are manipulating does not have declared height or width attributes. If that is the case, then the issue is how browsers intelligently resize images given only one constraint.
If you have an image that is 1000px wide, and 1000px tall, and you write an IMG tag like this:
<img src="big_image.gif" width="10" />
Modern browsers will render the huge image resized down to 10 by 10px.
So, on the line where you alter the height:
thumb.height(config.maxHeight);
the browser goes ahead an also alters the width. If you subsequently read the width (i.e. thumb.width(Math.ceil(thumb.width() / ratio))), you are going to be reading the new width, not the width it had before being given a new height.
var someImg = new Image();
someImg.src = <theURLofDesiredImage>
alert(someImg.width + " : " + someImg.height);
This is not Jquery but its vanilla JS and its a true way to determine "an unloaded" (not cached!) image. Add a query string to the URL url + "?asdasdasdadads" will allow you to circumvent the browser caching the image. This will result in a longer "image load time" but you will ALWAYS and more importantly, PREDICTABLY, resolve the dynamically loaded image.
I'm working on a script uses jQuery's data() function and HTML5 data attributes to dynamically switch an image's src attribute based on a media query. The idea behind this is to serve a lo-fi image by default (optimized for mobile), and serve a hi-fi image for larger screens. (This is not necessarily limited to images.) The script works 100% in Chrome/Opera/Safari/iOS but not completely in FF and IE.
<img src="ex1_lo-res.png" data-websrc="ex2_hi-res.png" alt="example">
<img src="ex2_lo-res.png" data-websrc="ex2_hi-res.png" alt="example">
A live example of this in use is responsetheme.com, where above 480px wide, the image should be pink, and below 480px wide, it should be yellow. I know that both data() and Modernizr.mq are supported in FF and IE—I tested them without the resize() function. So I think the issue has something to do with the trigger or the each() or resize() function. Any idea on what I'm missing?
jQuery(document).ready(function($) {
/* get elements that have a data-websrc attribute */
$websrc = $('[data-websrc]');
$websrc.each(function() {
/*
Set data-osrc equal to element's original src value.
This allows us the ability to access the original src
(even after we replace the attribute).
*/
var $this = $(this);
$this.data('osrc', $this.attr('src'));
});
$(window).resize(function() {
/*
Check breakpoint.
(Modernizr.mq checks the media query and returns boolean.)
*/
airsrcWEB = Modernizr.mq('screen and (min-width:480px)');
/*
Replace src with data-websrc (if above breakpoint).
Otherwise fallback to data-osrc (original src).
*/
$websrc.each(function() {
var $this = $(this);
var src = ( window.airsrcWEB ) ? $this.data('websrc') : $this.data('osrc');
$this.attr('src', src);
});
}).resize(); // trigger resize handlers
});
Also, I wasn't sure as to whether I have the functions in the most efficient way as far as which was inside which, so I'd also like to hear any tips for speeding this up. =)
Update 1: I also tried with the ternary like this and still the same issue:
var src = ( airsrcWEB ) ? $this.data('websrc') : $this.data('osrc');
Update 2: I figured out the issue with FF. Apparently a FF6 window won't resize below about 556px wide. I tested the script with a breakpoint above that and the switch worked. (Even the examples on mediaqueri.es won't shrink below 556px wide in FF6.)
You already found out that FF has a minimal window size. I don't know the exact value, but I believe it's a percentage of the initially available viewport width.
This is a restriction of XUL, the language in which FF was written.
The question is, is this really a problem in your case? The only persons that fiddle around with the window size are (front-end) webdevelopers. Normal users just load a page and stick with it, so basically I'm thinking that you might not really need to attach this functionality to a resize event.
Furthermore, this is only an issue when users are shrinking the window, not when expanding. If they already loaded the hi-res image, why bother loading the low-res aswell?
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