How can I control an image's size - javascript

I am a skilled database / application programmer for the PC. I am also an ignorant html / javascript / web programmer.
I am creating some documentation about some .Net assemblies for our intranet. Ideally I would like to display an image full size if the browser window can fit it. If not then I would like to reduce it and toggle between a small version and full size version by a click. It is a dependency chart and can be different sizes for different pages. I would prefer a single function to handle this but being it is for our use none of the requirements I mentioned is set in stone. I would like to make it work well but nothing is mandatory.
I read a lot of stuff but couldn't find anything that matched what I wanted. First I tried this (after a few iterations):
<img src='Dependancy Charts/RotairAORFQ.png' width='100%' onclick='this.src="Dependancy Charts/RotairAORFQ.png";this.width=this.naturalWidth;this.height=this.naturalHeight;' ondblclick='this.src="Dependancy Charts/RotairAORFQ.png";this.width="100%";'>
It has problems. First off it enlarges a small image and it looks funny. Second I would have to put the code in every page. Third it requires a double click to restore it. I was going to live with those short commings but the double click fails. I can't figure out how to restore it.
So I tried to get fancy. I couldn't figure out how to get past problem 1, but solved 2 and 3 by creating a function in a separate file. Then I ran into what appeared to be the same problem. This was my second attempt:
function ImageToggle(Image)
{
if (ImageToggle.FullSize == 'undefined')
ImageToggle.FullSize = false;
if (ImageToggle.FullSize)
{
Image.width='100%';
ImageToggle.FullSize = false;
}
else
{
Image.width=Image.naturalWidth;
ImageToggle.FullSize = true;
}
return 0
}
And in my page:
<img src='Dependancy Charts/RotairAORFQ.png' width='100%' onclick='ImageToggle(this)'>
Can what I want be done? It doesn't sound impossible. If it is a large amount of effort would be required then alternate suggestions are acceptable.

You're probably interested in the max-width: 100% CSS property, rather than a flat-out width:100%. If you have a tiny image, it'll stay tiny. If you have a huge image, it gets resized to the width of the containing element.
For example: http://jsbin.com/kabepo/1/edit uses a small and a huge image, both with max-width:100%. As you can see, the small image is untouched, the huge image is resized to something sensible.

I would recommend that you set a the max-width: 100% CSS property for the image.
This will prevent the image's width from expanding to be greater than the container's width.
You can also do the same with max-height: 100% if you are having problems with the image overflowing vertically.
Please see this JSFiddle for an example.
(Note: If you set both a width and a height attribute on the <img> tag directly or in your CSS file your image will not be scaled proportionally.)

Does it have to be a toggle or would a mouseover work for you as well?
<style>
.FullSize { width:100px; height:auto; }
.FullSize:hover { width:90%; height:auto; }
</style>
<img src="Dependancy Charts/RotairAORFQ.png" class="FullSize">
Note: when image is made larger IN the page - the surrounding content will be displaced around it - depending on how you have set up the layout.
Also if you have any body margins or table or div paddings, using image width at 100% will make the page scroll. To check just change 90% to 100% and work your way up / down.
You could also force the image to be a specific size until the browser gets made smaller by the user / has a smaller resolution.
<style>
.FullSize {width:1000px;max-width:100%;height:auto;}
</style>
<img src="Dependancy Charts/RotairAORFQ.png" class="FullSize">
A tip: the image used must be the largest one. So minimum width of lets say 1200 pixels wide (if that is the forced image size you use). That way regardless of size it is it will remain clearer than a small image becoming a large. Since it's an intranet, file size shouldn't be an issue.

Thanks all for your help. Rob and Mike both pointed me to an excellent solution. I now have my page load with an image that fits the browser window, resizes with the browser and if the user is interested they can expand the image and scrollbars appear if necessary. I got this to work in a function so minimal code is needed for each page.
To load the image:
<p style="overflow:auto;">
<img src='Dependancy Charts/RotairAORFQ.png' width="100%" onclick='ImageToggle(this)'>
</p>
And the function:
function ImageToggle(Image)
{
if (ImageToggle.FullSize == 'undefined')
ImageToggle.FullSize = false;
if (ImageToggle.FullSize)
{
Image.style="max-width: 100%";
ImageToggle.FullSize = false;
}
else
{
Image.style="max-width: none";
Image.width=Image.naturalWidth;
ImageToggle.FullSize = true;
}
return 1
}

if you want to get current browser window size and if you want to do it on a click event so try this in jquery or javascript:
<script>
$("#myButton").click(function(){
var x = window.innerHeight; // put current window size in x (ie. 400)
});
</script>

Related

How to prevent partially loaded images from displaying?

If you have, let's say, 3MB image in img tag, it will take a few seconds to load. When the image is loading, browser is sort of "printing" it - it shows the top part first, then middle and then bottom. How do I prevent this from happening?
I'd rather have the image hidden and after second or two shown - when it is fully loaded.
One way would be to give them a class that gives them opacity: 0 so they don't show:
<img src="/path/to/image" class="loading">
And in CSS:
.loading {
opacity: 0;
}
In head, we override that if JavaScript is disabled (so we're not unfriendly to non-JavaScript visitors):
<noscript>
<style>
.loading {
opacity: 1;
}
</style>
</noscript>
...and then in code at the bottom of your page, find all your images and remove the class when they've loaded, and...(see comments):
(function() {
// Get an array of the images
var images = Array.prototype.slice.call(document.querySelectorAll("img.loading"));
// Hook their load and error events, even though they may have already fired
images.forEach(function(image) {
image.addEventListener("load", imageDone.bind(null, image));
image.addEventListener("error", imageDone.bind(null, image)); // Could handle errors differently
});
// Check to see if any images are already complete
checkImages();
function imageDone(img) {
img.classList.loading("remove");
images = images.filter(function(entry) { entry != img });
}
function checkImages() {
images.forEach(function(image) {
if (image.complete) {
imageDone(image);
}
});
if (images.length) {
// Check back in a second
setTimeout(checkImages, 1000);
}
}
})();
That's a belt-and-braces approach. It proactively checks to see if images have finished loading, and also reactively handles the load and error event of images. In theory, we shouldn't need the setTimeout, and you might do testing without it, but...
Notice how once an image is complete, we remove the class so it's visible.
Old school:
To avoid the partial display of an image as it renders, save your large images as progressive, rather than baseline jpgs.
a progressive jpg renders as a series of scans of increasing quality
a baseline jpg renders top to bottom (what you described as “printing”).
The progressive option is considered more user friendly than both the sudden appearance of the image or the slow top to bottom rendering you dislike. The progressive file variant can even be smaller than its baseline counterpart.
For more about this read: The Return of the Progressive JPEG.
I think everyone here gave you some good answers and I just want to add in. 3MB is fairly big for a web image. Don't use something that large for an image being used for logo or layout. That's a larger amount of pixel data that you should only stick with if you are loading something that is a nice, large scale real-life image you want to preserve the quality to (or providing a download to a high-quality graphic of something). Besides the above, if you do a Google search, you find tons of solutions for loading images. Something nice I would use for larger images is a jQuery/ajax solution.

Skrollr Image Flicker. Firefox preload issue

Im in the process of developing a 'flipbook-style' animation using Skrollr by triggering background image changes when the user scrolls to indicated positions on the page. The issue i'm having is that in browser the image changes are delayed, creating what can only be defined as a 'flicker' of white between the frames.
<div class="section" style="background: url('frame1.png')"
data-560-top="background-image:!url('frame1.png');"
data-440-top="background-image:!url('frame2.png');">
The HTML is simple; it basically states that at 560 pixels from the top of the div (in relation to the browser window), the background should be at frame 1, then as the user scrolls closer to the div (440 pixels from the top of the div) the background image changes to frame 2. I plan to use up to around 20 frames and the images are quite large.
I have created a JSBin here which includes a very simplified sample with images from placehold.it. This includes the Skrollr script and an example layout of a section of my project. The key difference being that the images in my project are of much larger scale.
(function($) {
var cache = [];
// Arguments are image paths relative to the current page.
$.preLoadImages = function() {
var args_len = arguments.length;
for (var i = args_len; i--;) {
var cacheImage = document.createElement('img');
cacheImage.src = arguments[i];
cache.push(cacheImage);
}
};
})(jQuery);
jQuery.preLoadImages(
'http://www.placehold.it/300x200.png',
'http://www.placehold.it/300x200.png'
);
The above snippet seems to be working on Chrome, however the flicker issue remains in Firefox. Based on research, firefox handles cached images differently from Chrome? (e.g Where an image is not considered needed by firefox at a given time, it is trashed?)
I would like to know how I could possibly force all browsers to preload the images efficiently, to potentially avoid the background image flicker upon change. I am still quite new to Javascript/JQuery.
I hope I have provided a clear explanation. All assistance appreciated.
Dan
You can preload images using CSS only, no need for JS. Check out this article for more info. Another interesting way to do it is in the comment section of the article. Basically you assign the background image to a pseudo-element so that is is cached and ready to be used whenever. See this code for an example:
#something:before {
content: url("./img.jpg");
width:0;
height:0;
visibility:hidden;
}

How do I create a div the size of the page?

Note that I'm not asking how to make a div the size of the "window" or "viewport" for which there are plenty of existing questions.
I have a web page of some height and width, and I'd like to add an empty, top-level div (i.e., not one containing the rest of the page) with a size exactly equal to the page's height and width. In practice, I also want it to be at least the size of the viewport.
I know I can do a one-time calculation of the height and width in JavaScript:
var height = Math.max(document.body.scrollHeight,
document.documentElement.clientHeight);
var width = Math.max(document.body.scrollWidth,
document.documentElement.clientWidth);
But this value can change based on images loading, or AJAX, or whatever other dynamic stuff is going on in the page. I'd like some way of locking the size of the div at the full page size so it resizes dynamically and on-demand.
I have tried something like the following:
function resetFakeBg() {
// Need to reset the fake background to notice if the page shrank.
fakeBg.style.height = 0;
fakeBg.style.width = 0;
// Get the full page size.
var pageHeight = Math.max(document.body.scrollHeight,
document.documentElement.clientHeight);
var pageWidth = Math.max(document.body.scrollWidth,
document.documentElement.clientWidth);
// Reset the fake background to the full page size.
fakeBg.style.height = pageHeight + 'px';
fakeBg.style.width = pageWidth + 'px';
}
// Create the fake background element.
fakeBg = setFakeBgStyle(document.createElement('div'));
document.body.appendChild(fakeBg);
// Keep resizing the fake background every second.
size_checker_interval = setInterval(resetFakeBg, 1000);
Limitations
This is for a Chrome extension, and I'd like to limit my modification of the page to adding this single div. This means that adding CSS to modify the height and width of the html and/or body tags is undesirable because it might have side-effects on the way the rest of the page is rendered.
In addition, I do not want to wrap the existing page in the div because that has the potential to break some websites. Imagine, for example, a site styled with the CSS selector body > div. I'd like my extension to break as few websites as possible.
WHY OH WHY WOULD I NEED TO DO THIS?
Because some people like to hold their answers hostage until they're satisfied that I have a Really Good Reason™ for wanting to do this:
This is for an accessibility-focused Chrome extension that applies a CSS filter across an entire page. Recent versions of Chrome (>= 45) do not apply CSS filters to backgrounds specified on the <html> or <body> tag. As a result, I have chosen to work around this limitation by copying the page's background onto a div with a very negative z-index value, so that it can be affected by the page-wide CSS filter. For this strategy to work, the div needs to exactly imitate the way the page background would appear to a user—by being the exact size of the document (and no larger) and at least filling the viewport.
setInterval() is your best friend in cases like this where you want the .height() and .width() of an element to be asynchronously specified all the time to something that can be dynamicly altered by user input and DOM tree changes. It is what I dub as a "page sniffer", and arguably, works better than $(document).ready if you are working in multiple languages (PHP, XML, JavaScript).
Working Example
You should get away with setting the width and height in the window resize function, you might wanna add it in a load function as well, when all data/images are loaded.
just add width=100%
e.g;-
Hello World
I think you must do it like this:
...
<body>
<script>
function height()
{var height = Math.max(document.body.scrollHeight,
document.documentElement.clientHeight);}
function width()
{var width = Math.max(document.body.scrollWidth,
document.documentElement.clientWidth);}
</script>
<div height="height()" width="width()">
</div>
</body>
...

CSS image wrap issue - depends on browser zoom level

I'm trying to create a panel of 5 images across a DIV where a jQuery animate() expands each image in succession until all 5 images consume 100% of the width of their container without wrapping
Here is the link to the problem:
The initial blockUI displays fine, but once its expires and the normal page is shown, the same five images will display perfectly under some resolutions (I use ctrl-+/- in either FF or IE to test) and others it causes the last image to wrap.
The code to animate the resizing is below, and its purpose is to resize each image up to 20% of the width of the container. I've tried to see if it had to do with rounding and have come up empty. I've looked into CSS options trying some/all of the following:
overflow:hidden;
white-space: nowrap;
display:inline-block;
$(".service_img").each(function (i)
{
// if the image in question's width is > 20% of its container then re-adjust it to be 20% so it will fit
if($('#'+this.id).outerWidth() > Math.floor((($('#services_imgs_container').outerWidth()/5)))){
$('#'+this.id).width(Math.floor(($('#services_imgs_container').outerWidth()/5)));
}
else {
$('#'+this.id).animate({width:(Math.floor(($('#services_imgs_container').outerWidth()/5)))},{duration:500, queue:false});
//$('#'+this.id).animate({width:'19.2%'},{duration:500, queue:false});
$('#'+this.id).show();
}
})
You can write a function after the resize, and check to see if #services_imgs_container is twice the height of div.service_img:eq(0). If it is reduce the size of each .service_img by one pixel at a time until the statement is no longer true.
something like this
while($('#services_imgs_container').height() >= ($('.service_img:eq(0)').height() * 1.5))
{
$('.service_img').css('width': '-=1');
}

Programmatically Clip/Cut image using Javascript

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

Categories

Resources