I need to show an image in the largest size possible so I use javascript to create a square div with the maximum dimensions that fit the browser window.
I load the image and then I then change the width and height attributes to values that will make the image fit.
This works fine for 99% of images, but I have some that are shown in landscape format when they actually in portrait. I know they should be portrait because they are shown correctly in Windows explorer, Photoshop etc, and even when I right-click on the displayed image in a browser and select "show image in new window"
I have even rotated the image with PhotoShop and it is still shown landscape.
This makes me think that metadata is not being respected.
In ASPX Page_Load... imgImage.ImageUrl = "~/" & tPath
In HTML
function resizeImg() {
var windowWidth = window.innerWidth || document.documentElement.clientWidth;
var windowHeight = window.innerHeight || document.documentElement.clientHeight;
var imgMax = windowHeight - 54;
var div = document.getElementById('divImage');
div.style.width = imgMax + 'px';
div.style.height = imgMax + 'px';
var divW = div.offsetWidth;
var divH = div.offsetHeight;
var winR = divW/divH
var newImgH = imgH;
var newImgW = imgW;
if(newImgW > divW) {
newImgW=divW
newImgH = Math.floor(Math.round(divW / imgR));
}
if(newImgH > divH) {
newImgH=divH
newImgW =Math.floor(Math.round(divH * imgR));
}
img.setAttribute('width',newImgW);
img.setAttribute('height',newImgH);
img.setAttribute('hspace',(divW - newImgW)/2);
img.setAttribute('vspace', (divH - newImgH) / 2);
}
Related
I'm wrapping up a site that involves a few elements (image / text / diagonal line) that have to scale proportionately on different screens.
Because there's text that has to be resized, I'm using jQuery to calculate the measurements for all of the elements based on a ratio. This was the best solution I could think of at the time, and with a deadline approaching, I think I'm stuck with it. It's a single-page site that scrolls by the page (e.g., full pages in the viewport).
Here's a link to the demo site
The idea behind the code:
We check the height of the viewport to set the container size
Set the wrapper element height, based on the container size and necessary
margins
Set the width based on a ratio
Use these values to calculate font size, image size, and offsets
As the screen is re-sized, the element shrinks proportionately to fill the available space.
It looks kind of like this:
There are two panels like this. I re-use the same code (with different variable names, and a few sizing differences) for the second panel.
Here's my Javascript/jQuery for the first:
// Set panel height on page load & resize
$(window).on("resize", function () {
var $panelHeight = $(window).height();
var $headerHeight = $('.banner').height();
// General height for panels
$('.bg-panel').css('height', $panelHeight );
$('.bg-panel').css('padding-top', $headerHeight);
}).resize();
// We want to scale content proportionately
// First let's get some breakpoints
var $breakPoint = 768;
var $breakPointSM = 480;
// Panel 1
$(window).on("resize", function () {
// Check height of current panel
// If on single-column view, we want to measure the space between the text column and bottom of screen
// Otherwise, height of entire panel
var $windowHeight = $('.panel-test').height();
// But we need to subtract the header height, so our math is correct
var $headerHeight = $('.banner').height();
var $windowHeight = $windowHeight - $headerHeight;
// Now we have the correct height to work with
// We're at 768px or below, subtract the text element from the overall height
if ( $(document).width() <= $breakPoint) {
var $heightofDiv = $('.panel-1-text').height();
var $mobileHeight = $windowHeight - $heightofDiv;
var $windowHeight = $mobileHeight;
}
// Save the window height for calculating our margins!
var $windowHeightforMargins = $windowHeight;
// Top and bottom margins
var $marginTop = $windowHeight * (102/792); // ratio from PSD
var $marginBottom = $windowHeight * (84/792); // ratio from PSD
var $marginTotal = $marginTop + $marginBottom;
// Responsive solution
// As browser shrinks, reduce the height of panel so it produces a smaller container
if ( $(document).width() > 1200 && $(document).width() <= 1440) {
var $windowHeight = $windowHeight * 0.9;
var $marginTop = $marginTop * 2;
}
else if ( $(document).width() > 990 && $(document).width() <= 1200) {
var $windowHeight = $windowHeight * 0.8;
var $marginTop = $marginTop * 3;
}
else if ( $(document).width() > $breakPoint && $(document).width() <= 990) {
var $windowHeight = $windowHeight * 0.7;
var $marginTop = $marginTop * 3.5;
}
else if ( $(document).width() < $breakPoint) { // Ratio here goes up again because we're accounting for new height with $mobileHeight
var $windowHeight = $windowHeight * 0.8;
}
// This ratio determines the width of the container
var $ratio = 697 / 607; // from PSD
// Set container height, depending on height of panel
if ( $(document).width() <= $breakPointSM) {
var $taglinesHeight = ($windowHeight * 1.5); // Scale up for phones
}
else if ( $(document).width() > $breakPointSM && $(document).width() <= $breakPoint ){
var $taglinesHeight = ($windowHeight * 1); // Scale down for tablet
}
else {
var $taglinesHeight = $windowHeight - $marginTotal;
}
// Set container width as ratio of height
if ( $(document).width() <= $breakPoint) {
var $taglinesWidth = $taglinesHeight * $ratio
} else {
var $taglinesWidth = $taglinesHeight * $ratio
}
$('.panel-test .bg-taglines').css("width", $taglinesWidth);
$('.panel-test .bg-taglines').css("height", $taglinesHeight);
// Add top margin if above breakpoint
if ( $(document).width() > $breakPoint) { // No margin unless above 768px
$('.panel-test .bg-taglines').css("margin-top", $marginTop);
}
else {
$('.panel-test .panel-1-tagline').css("bottom", $marginTop);
}
// Set font size
var $fontSize = $taglinesWidth * 0.12;
$('.bg-panel h4').css("font-size", $fontSize);
// Set pink line origin (relative to bottom-left of frame)
var $pinkX = $taglinesWidth * (286 / 705);
var $pinkY = $taglinesHeight * (192 / 607);
$('.panel-test .animation-wrapper').css("left", $pinkX);
$('.panel-test .animation-wrapper').css("bottom", $pinkY);
// Set image size
var $imageWidth = $taglinesWidth * 0.556;
$('.panel-test .scaleable-image').css("width", $imageWidth);
// Set h3 margin from top
if ( $(document).width() >= $breakPoint) {
var $marginH3 = $windowHeight * (217/792); // ratio from PSD
$('.panel-test h3').css("margin-top", $marginH3);
} else {
// CSS
}
// Set line offset from top
var $lineOffset = $taglinesHeight * 0.7;
$('.panel-test .line-wrapper').css("top", $lineOffset);
// Set line length
var $lineLong = $taglinesWidth * 1;
$('.panel-test .pink-line').css("width", $lineLong);
}).resize();
It works: MOST of the time.
If I drag my window to resize, some of the elements get resized. Others don't.
A page refresh generally solves it, but right now, elements (mostly the images!) just aren't scaling properly and in sync with other elements.
I'm very new to jQuery and this is my first big undertaking. New to using resize as well. Hoping I just made a goof that's easy to fix.
Thanks!
LIVE SITE LINK
Other plugins in use: jQuery Scrollify (for full page scrolling) and ScrollReveal.
Guess I can answer my own question.
The issue seemed to be that the values were getting mixed up when scrolling from one full-screen panel to another.
Changing this:
$(window).on("resize", function () {
To this:
$(window).on("resize load scroll", function (e) {
... solved the issue. I'm not sure if it's the right way to do it, but the resizes are all working fine now.
My application has a large size of images to present and which should be resized for uniformly presentation with fixed width and height, to do so I write a JavaScript method in image's onload image like this:
var autoResizeImage = function(targetWidth, targetHeight, objImg) {
if (0 >= targetWidth || 0 >= targetHeight) {
// Ilegal parameters, just return.
return;
}
var img = new Image();
img.src = objImg.src;
// Calculate the width and height immediately the image is loaded.
img.onload = function() {
var hRatio;
var wRatio;
var width = img.width;
var height = img.height;
var calcWidth = width;
var calcHeight = height;
wRatio = targetWidth / width;
hRatio = targetHeight / height;
if (wRatio < hRatio) {
calcHeight = targetHeight;
calcWidth = (targetHeight / height) * width;
} else {
calcWidth = targetWidth;
calcHeight = (targetWidth / width) * height;
}
objImg.width = calcWidth;
objImg.height = calcHeight;
};
};
HTML image:
<img src='PATH' onload='autoResizeImage(100, 100, this)'>
This way works well on Chrome and Firefox except IE 6,7,8. I'm suffering on this, how can I complete this task on IE 6,7,8.
Thanks so much.
I would start by saying that if you're serving images to be displayed at a particular size, you should send them from the server at the correct size in the first place. Sending excessively large images and having the browser resize them is poor practice because it means that you're using up a lot more bandwidth than you need to. Your users may have restricted bandwidth, and may not appreciate the extra load time on your page caused by this.
However, I don't really know why you need to do this resizing exersise at all? HTML will by default scale an image to the size of the <img> tag that contains it anyway, so all you need to do is specify height and width styles for your <img> tag, and the scaling will be done automatically. There should be absolutely no need for all that messing around with Javascript.
<img src='PATH' style='width:100px; height:100px;'>
That should work in all browsers; no JS required. The image should be scaled for you.
But ideally, as I said, please try to avoid sending excessively large images to the page if you're not going to use them at full size.
Change the order of assignments. First assign onload function and then src attribute. It works for IE 8 at least.
var div = document.getElementById('div');
var img = new Image();
img.onload = function() {
var text = document.createTextNode('loaded ' + img.src);
div.appendChild(text);
};
window.setTimeout(function() {
var random = Math.random();
img.src ="http://stackoverflow.com/users/flair/450989.png?random=" + random;
}, 1000);
div.appendChild(img);
<div id="div"/>
This is what I need:
The image must completely fill 100% the area the div covers - left to
right and top to bottom.
the image must not be squashed or streched - just be cropped or
must overflow.
The image must be kept as small as possible, so whatever the resize - you
can still see either the very sides OR the very top and bottom.
The div itself will be adjusting in height and width as both are a percentage of the main window.
I have found a little bit of JavaScript here that is manipulating the image just how I want when the window is resized, but is displaying it in the whole window.
<html>
<head>
<title>test</title>
<script type="text/javascript">
function resizeImage()
{
var window_height = document.body.clientHeight
var window_width = document.body.clientWidth
var image_width = document.images[0].width
var image_height = document.images[0].height
var height_ratio = image_height / window_height
var width_ratio = image_width / window_width
if (height_ratio > width_ratio)
{
document.images[0].style.width = "100%"
document.images[0].style.height = "auto"
}
else
{
document.images[0].style.width = "auto"
document.images[0].style.height = "100%"
}
}
</script>
</head>
<body onresize="resizeImage()">
<img onload="resizeImage()" src="f/a.jpg">
</body>
</html>
Here is a demo
Please don't just answer that all I need is:
<img style="width : 100%;">
This is so much more than that.
It's not too easy to explain but check the demo and drag the corner of the window around and that'll be worth 1000 words...!
Can it (or something like it) be made to work the same way within a % sized div?
I wrote a jQuery plugin that does exactly this. Check out my blog post here and the demo here
jQuery.fn.resizeToParent = function(options) {
var defaults = {
parent: 'div'
}
var options = jQuery.extend(defaults, options);
return this.each(function() {
var o = options;
var obj = jQuery(this);
// bind to load of image
obj.load(function() {
// dimensions of the parent
var parentWidth = obj.parents(o.parent).width();
var parentHeight = obj.parents(o.parent).height();
// dimensions of the image
var imageWidth = obj.width();
var imageHeight = obj.height();
// step 1 - calculate the percentage difference between image width and container width
var diff = imageWidth / parentWidth;
// step 2 - if height divided by difference is smaller than container height, resize by height. otherwise resize by width
if ((imageHeight / diff) < parentHeight) {
obj.css({'width': 'auto', 'height': parentHeight});
// set image variables to new dimensions
imageWidth = imageWidth / (imageHeight / parentHeight);
imageHeight = parentHeight;
}
else {
obj.css({'height': 'auto', 'width': parentWidth});
// set image variables to new dimensions
imageWidth = parentWidth;
imageHeight = imageHeight / diff;
}
// step 3 - center image in container
var leftOffset = (imageWidth - parentWidth) / -2;
var topOffset = (imageHeight - parentHeight) / -2;
obj.css({'left': leftOffset, 'top': topOffset});
});
// force ie to run the load function if the image is cached
if (this.complete) {
obj.trigger('load');
}
});
}
And if you want the image to resize when the window is resized, just bind a resize handler to the window:
$(window).resize(function() {
$('img').resizeToParent();
});
Ok I've been playing around with it:
<html>
<head>
<title>test</title>
<style>
#imgarea {
position:absolute;
right:0px;
height:75%;
width:70%;
top:25%;
}
</style>
<script type="text/javascript">
function resizeImage()
{
var window_height = document.body.clientHeight
var window_width = document.body.clientWidth
var image_width = document.images[0].width
var image_height = document.images[0].height
var area_width = window_width * 0.7
var area_height = window_height * 0.75
var height_ratio = image_height / area_height
var width_ratio = image_width / area_width
if (height_ratio > width_ratio)
{
document.images[0].style.width = "100%"
document.images[0].style.height = "auto"
}
else
{
document.images[0].style.width = "auto"
document.images[0].style.height = "100%"
}
}
</script>
</head>
<body onresize="resizeImage()">
<div id="imgarea">
<img onload="resizeImage()" src="f/a.jpg">
</div>
</body>
</html>
It keeps resizing as the div resizes - as mentioned the div is
resizing with the window - this one keeps working seemlesly.
It seems to be OK across IE9, Fire Fox, Oprea, Chrome, and safari
over xp and 7
so really it answers my question perfectly, its just - now i've seen Christian's centering version i wish i had the know-how to make this do it i've tried a few things but am now stuck. Any Ideas?
P.S. if you dont know the width and height % of the div when you right the script i think it could be got with GetElementById - somehow... beyond me though;)
I'm trying to get an image that is around 1920x1200px to pan around on a 800x600px browser window.
So if my mouse is on the top-left of the browser window the image is alined so it's top-left margins are on the top-left of the browser window. The same goes for the bottum-right.
So if the mouse is in the centre of the screen the image should be centered too.
Im not sure what calculations are needed as my math is a bit rusty.
Currently I'm using a bit of javascript that just moves the image using CSS's top/left properties but without much success as it's just moving the picture around from it's top/left corner.
I'v also set the image's position to absolute in css.
function updateImgPosition( e )
{
var avatar = document.getElementById("avatar");
// Width
var windowWidth = window.innerWidth;
var mouseWidthLocation = e.x;
var percentOfWidth = (100 / windowWidth) * mouseWidthLocation;
// Height
var windowHeight = window.innerHeight;
var mouseHeightLocation = e.y;
var percentOfHeight = (100 / windowHeight) * mouseHeightLocation;
avatar.style.top = percentOfHeight + "%";
avatar.style.left = percentOfWidth + "%";
}
document.onmousemove = updateImgPosition;
This is a demo of what I have: http://jsfiddle.net/uQAmQ/1/
Fiddle: http://jsfiddle.net/uQAmQ/2/
You should not "pan" on an absolutely positioned element, because the window's width and height keep changing according to the image. A smoother solution involves using a background image. See the middle of my answer for the used logic.
Consider this JavaScript (read comments; HTML + CSS at fiddle):
(function(){ //Anonymous function wrapper for private variables
/* Static variables: Get the true width and height of the image*/
var avatar = document.getElementById("avatar");
var avatarWidth = avatar.width;
var avatarHeight = avatar.height;
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
/* Logic: Move */
var ratioY = (avatarHeight - windowHeight) / windowHeight;
var ratioX = (avatarWidth - windowWidth) / windowWidth;
function updateImgPosition( e ) {
var mouseY = e.pageX; //e.pageX, NOT e.x
var mouseX = e.pageY;
var imgTop = ratioY*(-mouseY);
var imgLeft = ratioX*(-mouseX);
document.body.style.backgroundPosition = imgLeft + "px " + imgTop + "px";
}
/* Add event to WINDOW, NOT "document"! */
window.onmousemove = updateImgPosition;
})();
The logic behind it:
Relative units cannot be used, because the image size is specified in absolute units.
The offsets should change according to a specific ratio, which is similar to: image size divided by window size.However, this ratio is not complete: The image would disappear at the bottom/left corner of the window. To fix this, substract the window's size from the image's size. The result can be found in the code at variable ratioX and ratioY.
The previous code had to be loaded at the window.onload event, because the image's size was dynamically calculated. For this reason, a HTML element was also included in the body.
The same code can be written much smaller and efficient, by specifying the size of the background in the code. See this improved code. Fiddle: http://jsfiddle.net/uQAmQ/3/
(function(){ //Anonymous function wrapper for private variables
/* Static variables: Get the true width and height of the image*/
var avatarWidth = 1690;
var avatarHeight = 1069;
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
/* Logic: Move */
var ratioY = (avatarHeight - windowHeight) / windowHeight;
var ratioX = (avatarWidth - windowWidth) / windowWidth;
function updateImgPosition( e ) {
var mouseX = e.pageX; //e.pageX, NOT e.x
var mouseY = e.pageY;
var imgTop = ratioY*(-mouseY);
var imgLeft = ratioX*(-mouseX);
document.body.style.backgroundPosition = imgLeft + "px " + imgTop + "px";
}
/* Add event to WINDOW, NOT "document"! */
window.onmousemove = updateImgPosition;
})();
If you don't mind a decreased code readability, the following code is the best solution, Fiddle: http://jsfiddle.net/uQAmQ/4/:
(function(){ //Anonymous function wrapper for private variables
/* Static variables: Get the true width and height of the image*/
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var ratioY = (windowHeight - 1069) / windowHeight;
var ratioX = (windowWidth - 1690) / windowWidth;
window.onmousemove = function( e ) {
document.body.style.backgroundPosition = ratioX * e.pageX + "px " + ratioY * e.pageY + "px";
}
})();
The code: http://jsfiddle.net/LPF85/6/
In FF, IE7, and IE9 (the only browsers I've tested that don't run WebKit), it seems that the left attribute is either always set to 0, or, in IE's case, negative.
My positioning code is all based off the dimensions of the document.
function open_img_in_face_box(id, width){
max_width = $j(document).width();
max_height = $j(document).height();
padding = 150;
passed_width = width || (max_width - (2 * padding));
var img = $j('#' + id);
dom_img = document.getElementById(id);
$j(document).bind('reveal.facebox', function() {
$j("#facebox .image img").width(passed_width);
})
// display
jQuery.facebox({
image: img.attr('src')
});
// center and adjust size
var aspect_ratio = img.width() / img.height();
var img_width = passed_width;
var img_height = passed_width / aspect_ratio;
window_center_y = max_height / 2;
window_center_x = max_width / 2;
offset_y = window_center_y - (img_height / 2);
offset_x = window_center_x - (img_width / 2);
var fbx = $j('#facebox');
fbx.css('position', 'absolute');
fbx.css('left', offset_x + 'px !important');
fbx.css('top', offset_y + 'px !important');
fbx.css('margin-left', 'auto');
fbx.css('margin-right', 'auto');
}
margin-left and margin-right don't appear to do anything here, which I'm fine with, because the left math should work across all browsers, right? (It is just math)
The goal of the facebox / lightbox, is to be centered both horizontally and vertically.
Why would you even programatically calculate the position in the first place? What if the user resizes the page? This can easily be done in pure CSS.
I don't really understand your jsFiddle (or am I not seeing the same thing?) so I'll just give you this script: http://jsfiddle.net/minitech/8U4Ke/ that can be modified however you like. It's commented. ;)
Now it's easy to hide and show - to hide, fade out .overlay. To show, fade it in. To change the contents, replace the HTML in .popup. Add close boxes and whatnot liberally.