Im trying to work out how to make an image that is way bigger than the browser window (2000x2800px) scale when initializing jquery.panzoom. I need the image to resize itself so it will fit within the height of the container.
Check out this jsFiddle: http://jsbin.com/raxejirubayu/1/edit?html,css,js,output
Anyone with any experience using panzoom able to help me out? Virtual beers and highfives given in return.
I've fixed this issue by writing this javascript code, it basically calculates the zoom and pan parameters according to the image size and container size and applies transformations such that the image is stretched to the container boundary.
Javascript file
$(document).ready(function(){
$panzoom = $(".cimage").panzoom();
//Wait for the image to load
$('.cimage').load(function(){
//Get container and image
var image = $('.cimage');
var container = $('.image-container');
//Get container dimensions
var container_height = container.height();
var container_width = container.width();
//Get image dimensions
var image_height = image.height();
var image_width = image.width();
//Calculate the center of image since origin is at x:50% y:50%
var image_center_left = image_width / 2.0;
var image_center_top = image_height / 2.0;
//Calculate scaling factor
var zoom_factor;
//Check to determine whether to stretch along width or heigh
if(image_height > image_width)
zoom_factor = container_height / image_height;
else
zoom_factor = container_width / image_width;
//Zoom by zoom_factor
$panzoom.panzoom("zoom", zoom_factor, {animate: false});
//Calculate new image dimensions after zoom
image_width = image_width * zoom_factor;
image_height = image_height * zoom_factor;
//Calculate offset of the image after zoom
var image_offset_left = image_center_left - (image_width / 2.0);
var image_offset_top = image_center_top - (image_height / 2.0);
//Calculate desired offset for image
var new_offset_left = (container_width - image_width) / 2.0;
var new_offset_top = (container_height - image_height) / 2.0;
//Pan to set desired offset for image
var pan_left = new_offset_left - image_offset_left;
var pan_top = new_offset_top - image_offset_top;
$panzoom.panzoom("pan", pan_left, pan_top);
});
});
HTML file
<div class="image-container">
<img class='cimage' src="abc.jpg'/>
</div>
It is stretched along width or height, depending upon image orientation (portrait or landscape) but if you want to stretch only along height then you need to replace
if(image_height > image_width)
zoom_factor = container_height / image_height;
else
zoom_factor = container_width / image_width;
with
zoom_factor = container_height / image_height;
but I would recommend against it because it would not be able to handle landscape images.
Related
How can I delay the size of the image after scrolling 300 from the top.
Is it possible to do with var.
I am not sure how to delay it so it animates when a certain distance from the top.
I'm using this script:
Img001Size = function () {
// Get the real width of the logo image
var theImg1 = $("#theImg1");
var newImage = new Image();
newImage.src = theImg1.attr("src");
var imgWidth = newImage.width;
// distance over which zoom effect takes place
var maxScrollDistance = 1300;
// set to window height if larger
maxScrollDistance = Math.min(maxScrollDistance, $(window).height());
// width at maximum zoom out (i.e. when window has scrolled maxScrollDistance)
var widthAtMax = 500;
// calculate diff and how many pixels to zoom per pixel scrolled
var widthDiff = imgWidth - widthAtMax;
var pixelsPerScroll =(widthDiff / maxScrollDistance);
$(window).scroll(function () {
// the currently scrolled-to position - max-out at maxScrollDistance
var scrollTopPos = Math.min($(document).scrollTop(), maxScrollDistance);
// how many pixels to adjust by
var scrollChangePx = Math.floor(scrollTopPos * pixelsPerScroll);
// calculate the new width
var zoomedWidth = imgWidth - scrollChangePx;
// set the width
$('.Img001').css('width', zoomedWidth);
});
}
Img001Size();
I am working with fabricjs for an application. On mobile I need to scale the whole canvas down so it can fit the screen.
The issue is that on the canvas there are 10 objects in total, between images, texts and fabric js background objects.
I tried scaling the whole canvas using CSS transform and it seems to work, but the whole area gets smaller, as in this picture
The original canvas is the entire picture, but when I apply the transform, the canvas becomes the red area, and when moving objects with fabricjs, they get clipped when outside the red area.
Is there any way to fix this in CSS ?
edit
Basically I need to scale everything inside the canvas, but the canvas itself needs to always be 100% in height and with of the current window.
Or is there any way to resize the whole canvas with all the objects ? I also tried fabric js setZoom() method, but it gets even more messed up.
Thank you
The best way is find a scale ratio that fit your screen (is unclear how you plan to fit a square canvas on a long screen).
Then leave the css untrasformed. ratio is the scale ratio that fit the canvas in screen;
resize the canvas to actual screen dimensions:
canvas.setDimensions({ width: originalWidth * ratio, height: originalHeight * ratio });
canvas.setZoom(ratio)
This should give you a smaller canvas with everything in place.
Possible Duplicate: Scale fabric.js canvas objects
It seems Fabric.js doesn't support this natively... at least, I haven't found the options to do it.
Until Fabric.js provides this, the best way may be to iterate through the objects and scale them manually to match the new screen size based on the ratio of the previous screen size. For example...
const canvas = new fabric.Canvas({});
let prevScreenWidth = window.innerWidth;
let prevScreenHeight = window.innerHeight;
window.addEventListener('resize', handleResize());
/*********************************************************
* Get the new screen size ratio in relation to the previous screen size
* to determine the scale factor.
*********************************************************/
function handleResize() {
// Error Handling: Make sure the scale ratio denominator is defined.
prevScreenWidth = prevScreenWidth || window.innerWidth;
prevScreenHeight = prevScreenHeight || window.innerHeight;
// Get the current/new screen width and height (scale ratio numerator).
const currScreenWidth = window.innerWidth;
const currScreenHeight = window.innerHeight;
// Determine width and height scale ratios
const widthRatio = currScreenWidth / prevScreenWidth;
const heightRatio = currScreenHeight / prevScreenHidth;
// Get the average of the width and height scale ratios
const scaleFactor = (widthRatio + heightRatio) / 2;
// Scale the objects with the screen size adjustment ratio average as the scale factor
scaleObjects(scaleFactor);
// Record the current screen sizes to be used for the next resize.
prevScreenWidth = window.innerWidth;
prevScreenHeight = window.innerHeight;
}
/*********************************************************
* Iterate through each object and apply the same scale factor to each one.
*********************************************************/
function scaleObjects(factor) {
// Set canvas dimensions (this could be skipped if canvas resizes based on CSS).
canvas.setDimensions({
width: canvas.getWidth() * factor,
height: canvas.getHeight() * factor
});
if (canvas.backgroundImage) {
// Need to scale background images as well
const bi = canvas.backgroundImage;
bi.width = bi.width * factor; bi.height = bi.height * factor;
}
const objects = canvas.getObjects();
for (let i in objects) {
const scaleX = objects[i].scaleX;
const scaleY = objects[i].scaleY;
const left = objects[i].left;
const top = objects[i].top;
const tempScaleX = scaleX * factor;
const tempScaleY = scaleY * factor;
const tempLeft = left * factor;
const tempTop = top * factor;
objects[i].scaleX = tempScaleX;
objects[i].scaleY = tempScaleY;
objects[i].left = tempLeft;
objects[i].top = tempTop;
objects[i].setCoords();
}
canvas.renderAll();
canvas.calcOffset();
}
See this previous answer for more information on the scaleObjects() method... Scale fabric.js canvas objects
When i run my application it gives me several errors:
the first one is:
SyntaxError: class is a reserved identifier in the class thumbnail
code:
const MAXHEIGHT = 170;
const MAXWIDTH = 320;
import {Subcategory} from './subcategory'
//import {Category} from './category'
import {bootstrap} from 'angular2/platform/browser'
class Thumbnail {
width: number;
height: number;
constructor(element: HTMLImageElement) {
this.height = element.height;
this.width = element.width;
}
resize(oImage: HTMLImageElement) {
var maxWidth = 100; // Max width for the image
var maxHeight = 100; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = oImage.width; // Current image width
var height = oImage.height; // Current image height
// Check if the current width is larger than the max
if (oImage.width > MAXWIDTH) {
ratio = MAXWIDTH / width; // get ratio for scaling image
oImage.width=MAXWIDTH; // Set new width
oImage.height=height * ratio; // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if (height > MAXHEIGHT) {
ratio = MAXHEIGHT / height; // get ratio for scaling image
oImage.height= MAXHEIGHT; // Set new height
oImage.width= width * ratio; // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
height = height * ratio; // Reset height to match scaled image
}
// Check if current height is smaller than max
if (height < MAXHEIGHT) {
ratio = MAXHEIGHT / height; // get ratio for scaling image
oImage.height = MAXHEIGHT; // Set new height
oImage.width = width * ratio; // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
height = height * ratio; // Reset height to match scaled image
}
// Check if the current width is smaller than the max
if (oImage.width < MAXWIDTH) {
ratio = MAXWIDTH / width; // get ratio for scaling image
oImage.width = MAXWIDTH; // Set new width
oImage.height = height * ratio; // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
document.body.appendChild(oImage);
console.log(oImage.height);
console.log(oImage.width);
}
};
window.onload = () => {
var oImage = new Image();
var oImage2 = new Image();
// var category = new Category(1, "string");
var subcategory = new Subcategory("teste",1,2);
oImage.src = 'AngularJS.png';
oImage.setAttribute('class','img-responsive');
oImage2.src = 'ts.jpg';
var thumbnail = new Thumbnail(oImage);
var thumbnail2 = new Thumbnail(oImage2);
thumbnail.resize(oImage);
thumbnail2.resize(oImage2);
console.log(oImage.height);
console.log(oImage.width);
};
The second error is:
GET http://localhost:51580/app
301 Moved Permanently
The configuration of angular is:
<script>
System.config({
packages: {
TypeScriptHTMLApp1: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app')
.then(null, console.error.bind(console));
</script>
I already tried to create a folder named app and moved the file for that folder but the error persists. I need help with this, I lost several hours and can't resolve anything. I attach one image with the file structure and another one with the firebug errors. Thanks in advance.
as suggested by #Eric in comment
Classes aren't supported in Firefox version < 45 according to this article
. instead try same use case in the chrome.
posted as answer may helpful to someone.
I'm using FileReader to display in a <div> a file uploaded with an input type file. When the file is dropped in the field, I need to compressed the file and resize him. I used this code :
var width = source_img_obj.naturalWidth;
var height = source_img_obj.naturalHeight;
var quality = 90;
var maxWidth = 2000; // Max width for the image
var maxHeight = 2000; // Max height for the image
var ratio = 0; // Used for aspect ratio
// Check if the current width is larger than the max
if (width > maxWidth){
ratio = maxWidth / width; // get ratio for scaling image
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if (height > maxHeight){
ratio = maxHeight / height; // get ratio for scaling image
width = width * ratio; // Reset width to match scaled image
height = height * ratio; // Reset height to match scaled image
}
var cvs = document.createElement('canvas');
cvs.width = width;
cvs.height = height;
var ctx = cvs.getContext("2d").drawImage(source_img_obj, 0, 0, width, height);
var newImageData = cvs.toDataURL(mime_type, quality/100);
var result_image_obj = new Image();
result_image_obj.src = newImageData;
EDIT : FULL code is here
The finished file compressed is saved in result_image_obj, but before display this base64 image, I need to check the size of the final picture. So if the size is larger than 500kb I need to compress again the picture.
Is there a way to get the size (b, kb, mb..) of a base64 picture generated by canvas ?
Another question : Can we get the orientation of the picture uploaded with FileReader ? Because with some device portait picture are displayed in landscape orientation.
Thanks
You can find rough image size using:
var size = newImageData.length * 3 / 4; // size in bytes
if (size > 500 * 1024) { // more than 500 kb
// do something
}
Look here for more info:
Base64 length calculation?
In Three.js I'm using this formulas to calculate visible width & height
var vFOV = camera.fov * Math.PI / 180; // convert vertical fov to radians
var height = 2 * Math.tan( vFOV / 2 ) * dist; // visible height
var aspect = window.width / window.height;
var width = height * aspect; // visible width
And with that I calculate the camera zoom required for object to fit exactly into render area by WIDTH
var zoom = (ObjectHeight/aspect) / (2*Math.tan(vFOV/2)) + ObjectDepth;
How do I calculate the camera zoom required for object to fit exactly into render area by HEIGHT?
Thanks to GuyGood, I found the solution:
var zoom = (ObjectHeight/2) / Math.tan(vFOV/2) - ObjectDepth;
I am doing the following which is based on the boundingSphere radius:
geometry.computeBoundingSphere();
radius = geometry.boundingSphere.radius;
distanceFactor = Math.abs( aspect * radius / Math.sin( fov/2 );
This is based on this stuff right here and I hope i interpreted it the right way:
http://www.flipcode.com/forums/thread/4172
This distanceFactor is the factor you need to move the camera along its viewing direction to fit it correctly. At the moment i am not sure if it is by height or width but maybe it helps you figure it out. :)