If i had an image with a url such as img/160x180.jpg how using this alone in jquery/javascript can i get the width and height of it. i have tried
alert($('<img src="img/160x180.jpg"/>').naturalWidth)
in the example below it returns undefined.
http://jsfiddle.net/D7dx6/
Updated:
alert($('<img src="http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif"/>')[0].width);
edit — that doesn't really make sense; it needs to be in an event handler:
$('<img/>', {
'load': function() { alert(this.width); },
'src': 'http://static.jquery.com/files/rocker/images/logo_jquery_215x53.gif'
});
That code, it should be noted, might have problems on IE because it sometimes drops the ball if the "src" is set and the image is found in cache before the "load" handler is established. In that case, you can do this:
$('<img/>', { 'load': function() { alert(this.width); } }).prop('src', 'http://...');
There's no "naturalWidth" property.
Though it's pretty much irrelevant overhead in this case, you can do this without jQuery like this:
var img = new Image();
img.onload = function() {
alert(img.width);
};
img.src = "http://placekitten.com/300/400";
Now one thing to watch out for is that if you're looking at actual page elements (that is, <img> tags on the page), they might have "width" attributes that override the true size. Fetching the image again will generally pull it out of cache, though there's some potential pain there for huge images on mobile devices.
(edit — Graham points out that there is a "naturalWidth", but it's not well-supported at this time.)
naturalWidth and naturalHeight aren't well supported yet: see https://developer.mozilla.org/en/DOM/HTMLImageElement.
The pure-JavaScript way to determine the original dimensions of an image, whether or not it currently exists in the DOM, is to use the Image object.
var img = new Image();
img.src = 'path/to/img.jpg';
// you'll probably want to use setTimeout to wait until the imh.complete is true
console.log(img.width);
Related
Is it possible to bind an onload event to each image, declaring it once? I tried, but can't manage to get it working... (this error is thrown: Uncaught TypeError: Illegal invocation)
HTMLImageElement.prototype.onload = function()
{
console.log(this, "loaded");
};
P.S: I also tried returning this, but doesn't seem to be the issue here... any suggestions / explanations on why my current code isn't working?
You can't set a handler on the prototype, no.
In fact, I'm not aware of any way to get a proactive notification for image load if you haven't hooked load on the specific image element, since load doesn't bubble.
I only two know two ways to implement a general "some image somewhere has loaded" mechanism:
Use a timer loop, which is obviously unsatisfying on multiple levels. But it does function. The actual query (document.getElementsByTagName("img")) isn't that bad as it returns a reference to the continually updated (live) HTMLCollection of img elements, rather than creating a snapshot like querySelectorAll does. Then you can use Array.prototype methods on it (directly, to avoid creating an intermediary array, if you like).
Use a mutation observer to watch for new img elements being added or the src attribute on existing img elements changing, then hook up a load handler if their complete property isn't true. (You have to be careful with race conditions there; the property can be changed by the browser even while your JavaScript code is running, because your JavaScript code is running on a single UI thread, but the browser is multi-threaded.)
You get that error because onload is an accessor property defined in HTMLElement.prototype.
You are supposed to call the accessor only on HTML elements, but you are calling the setter on HTMLImageElement.prototype, which is not an HTML element.
If you want to define that function, use defineProperty instead.
Object.defineProperty(HTMLImageElement.prototype, 'onload', {
configurable: true,
enumerable: true,
value: function () {
console.log(this, "loaded");
}
});
var img = new Image();
img.onload();
Warning: Messing with builtin prototypes is bad practice.
However, that only defines a function. The function won't be magically called when the image is loaded, even if the function is named onload.
That's because even listeners are internal things. It's not that, when an image is loaded, the browser calls the onload method. Instead, when you set the onload method, that function is internally stored as an event listener, and when the image is loaded the browser runs the load event listeners.
Instead, the proper way would be using Web Components to create a custom element:
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {
var img = document.createElement('img');
img.src = this.getAttribute('src');
img.addEventListener('load', function() {
console.log('loaded');
});
this.appendChild(img);
};
document.registerElement('my-img', {prototype: proto});
<my-img src="/favicon.ico"></my-img>
There is not much browser support yet, though.
This provides a notification for any image loading, at least in Opera (Presto) and Firefox (haven't tried any other browser). The script tag is placed in the HEAD element so it is executed and the event listener installed before any of the body content is loaded.
document.addEventListener('load', function(e) {
if ((!e.target.tagName) || (e.target.tagName.toLowerCase() != 'img')) return;
// do stuff here
}, true);
Of course, by changing the filtering on tagName it will also serve to respond to the loading of any other element that fires a load event, such as a script tag.
I've written something similar some time ago to check if an image is loaded or not, and if not, show a default image. You can use the same approach.
$(document).ready(function() {
// loop every image in the page
$("img").each(function() {
// naturalWidth is the actual width of the image
// if 0, img is not loaded
// or the loaded img's width is 0. if so, do further check
if (this.naturalWidth === 0) { // not loaded
this.dataset.src = this.src; // keep the original src
this.src = "image404.jpg";
} else {
// loaded
}
});
});
I've read numerous posts and articles and tried both the JS-only onLoad method and using JQuery's .load(function() { way of going about things, but I can't find a good way to load an image quietly in the background and then do something once I know its actual width.
At this point I've got it all the way down as simple as I can get it, and it still returns "0":
bgImg = new Image();
bgImg.src = "./img/car-and-truck.gif";
bgImg.onload = imageLoaded();
function imageLoaded() {
alert(bgImg.width);
}
Use this instead:
bgImg.onload = imageLoaded;
You are calling imageLoaded immediately which you do not want to do.
I want to track changes that are made to the src property of an HTMLImageElement while it is not yet attached to the document. My goal is to modify the image URL to force the usage of a certain proxy server using an inserted script. The scripts that use the Image object mainly for preloading are external (3rd party) ones, so I cannot just search & replace any occurence of instance.src = value to anything else. I can control the document the scripts are embedded in, but cannot control the scripts themselves.
I already tried to define getter/setter on the Image element
Object.defineProperty(
Image.prototype,
"src",
{ get : function(){...}, set : function(val){...}}
);
But this does not seem to have any effect at all. When creating a new Image just like
var img = new Image();
img.src = "foo.png";
alert(img.src);
neither the setter nor the getter is called.
Do you have any idea what else I might try to get notified when the src property is modified without modifying the original source where the property is set?
Thanks in advance!
I retested my previous answer with your example code - no dice. So, I'll go with Andrei's suggestion instead - don't do this :P Instead, work with methods attached to the prototype through more "conventional" means:
Image.prototype.setSrc = function(src) {
// your code affecting this.src
// from what I can tell in your use-case, you only need this setter
};
Image.prototype.getImage = function() {
// but, in case you want to do anything before getting the image
// you can call this method
};
var img = new Image();
img.setSrc("foo.png");
// snip
document.body.appendChild(img.getImage());
In Firefox 8.0 on ubuntu 11.10, the onload function, draw, is called although img.complete is false. I managed to solve it somewhat with the setTimeout hack, but it's not pretty.
I tried setting the img.onload before setting img.src. Although I always get img.complete as true this way, img.width is zero, and img.src si also empty, so it doesn't work.
Any ideas how to implement this properly?
var draw=function(img,ctx,x,y)
{ if(!img.complete)
{ setTimeout(function(){draw(img,ctx,x,y);},50);
}
else
{
ctx.drawImage(img,x,y);
}
}
for(i=0;i<9;i++)
{ img=new Image();
img.src="/media/"+url[i];
img.onload=(draw)(img,ctx,tile.x*offset[i].x,tile.y*offset[i].y);
}
The complete property is buggy in Firefox. Once it's true, it's always true (even if you change the image).
I got around it by testing a new Image object.
new Image for every .complete doesn't work, either.
Try checking img.width for greater than zero instead.
function loader(img) {
var imgH = img.height;
var imgW = img.width;
console.log(imgH, imgW);
};
img = new Image();
img.src ='../images/pic1.jpeg';
img.onLoad = loader(img);
So, It is exepeted, that I'll get image's size, but I got "0 0" in console. And size of image is 500X700. What's wrong with this code?
This makes no sense:
img.onLoad = loader(img);
you want to pass the actual function to the event:
img.onload = loader;
and use this instead of img within the function.
Also you need to assign the event before changing the image's src property.
Also note that there are numerous problems with the load event on images. From the jQuery manual on load():
Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load() shortcut is to execute a function when an image (or collection of images) have completely loaded. There are several known caveats with this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Try this:
function loader(){
var imgH = this.height;
var imgW = this.width;
console.log(imgH, imgW);
}
var img = new Image();
img.onload = loader;
img.src ='../images/pic1.jpeg';
I used this way:
img.onload = function(){//here wrote everything from loader};
And it was the only working solution I have found.
I found the best way is to let the computer do the scaling first.
and declaring the onload = "some_function()" in the body.
<body onload="some_function()">
and then getting the sizing afterward in the script.
some_function(){
var image1 = document.getElementsByClassName('main')[0];
var computedStyle_image1 = window.getComputedStyle(image1);
var image_width = computedStyle_image1.getPropertyValue('width');
}
I noticed with google chrome you need to make sure you call the onload="function" within the body div otherwise the image values arn't set and it pulls in 0px for width and height.