why I am getting image width 0 in safari? - javascript

could you please tell me why I am getting background image 0 in safari . I am getting 225px width in chrome and firefox and zero in safari
here is my code
https://codesandbox.io/s/lucid-spence-cuyf7?file=/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Static Template</title>
<style>
.img {
background: url("./download.jpeg") no-repeat left;
}
</style>
</head>
<body>
<div class="img" alt="" />
<button onclick="abc()">click</button>
<script>
function getBackgroundSize(elem) {
// This:
// * Gets elem computed styles:
// - CSS background-size
// - element's width and height
// * Extracts background URL
var computedStyle = getComputedStyle(elem),
image = new Image(),
src = computedStyle.backgroundImage.replace(
/url\((['"])?(.*?)\1\)/gi,
"$2"
),
cssSize = computedStyle.backgroundSize,
elemW = parseInt(computedStyle.width.replace("px", ""), 10),
elemH = parseInt(computedStyle.height.replace("px", ""), 10),
elemDim = [elemW, elemH],
computedDim = [],
ratio;
// Load the image with the extracted URL.
// Should be in cache already.
image.src = src;
// Determine the 'ratio'
ratio =
image.width > image.height
? image.width / image.height
: image.height / image.width;
// Split background-size properties into array
cssSize = cssSize.split(" ");
// First property is width. It is always set to something.
computedDim[0] = cssSize[0];
// If height not set, set it to auto
computedDim[1] = cssSize.length > 1 ? cssSize[1] : "auto";
if (cssSize[0] === "cover") {
// Width is greater than height
if (elemDim[0] > elemDim[1]) {
// Elem's ratio greater than or equal to img ratio
if (elemDim[0] / elemDim[1] >= ratio) {
computedDim[0] = elemDim[0];
computedDim[1] = "auto";
} else {
computedDim[0] = "auto";
computedDim[1] = elemDim[1];
}
} else {
computedDim[0] = "auto";
computedDim[1] = elemDim[1];
}
} else if (cssSize[0] === "contain") {
// Width is less than height
if (elemDim[0] < elemDim[1]) {
computedDim[0] = elemDim[0];
computedDim[1] = "auto";
} else {
// elem's ratio is greater than or equal to img ratio
if (elemDim[0] / elemDim[1] >= ratio) {
computedDim[0] = "auto";
computedDim[1] = elemDim[1];
} else {
computedDim[1] = "auto";
computedDim[0] = elemDim[0];
}
}
} else {
// If not 'cover' or 'contain', loop through the values
for (var i = cssSize.length; i--; ) {
// Check if values are in pixels or in percentage
if (cssSize[i].indexOf("px") > -1) {
// If in pixels, just remove the 'px' to get the value
computedDim[i] = cssSize[i].replace("px", "");
} else if (cssSize[i].indexOf("%") > -1) {
// If percentage, get percentage of elem's dimension
// and assign it to the computed dimension
computedDim[i] = elemDim[i] * (cssSize[i].replace("%", "") / 100);
}
}
}
// If both values are set to auto, return image's
// original width and height
if (computedDim[0] === "auto" && computedDim[1] === "auto") {
computedDim[0] = image.width;
computedDim[1] = image.height;
} else {
// Depending on whether width or height is auto,
// calculate the value in pixels of auto.
// ratio in here is just getting proportions.
ratio =
computedDim[0] === "auto"
? image.height / computedDim[1]
: image.width / computedDim[0];
computedDim[0] =
computedDim[0] === "auto" ? image.width / ratio : computedDim[0];
computedDim[1] =
computedDim[1] === "auto" ? image.height / ratio : computedDim[1];
}
// Finally, return an object with the width and height of the
// background image.
return {
width: computedDim[0],
height: computedDim[1]
};
}
function abc() {
console.log(getBackgroundSize(document.querySelector(".img")));
}
</script>
</body>
</html>
any suggestion ?
?

Like the comments suggest you need to wait for the image to load. Here I added an event listener for the image object.
And maybe the image is already in the cache, but you need to wait for the image to load into this particular object.
var onImageLoad = e => {
let image = e.target;
let ratio =
image.width > image.height ?
image.width / image.height :
image.height / image.width;
console.log(ratio);
};
function getBackgroundSize(elem) {
var computedStyle = getComputedStyle(elem),
image = new Image(),
src = computedStyle.backgroundImage.replace(
/url\((['"])?(.*?)\1\)/gi,
"$2"
),
cssSize = computedStyle.backgroundSize,
elemW = parseInt(computedStyle.width.replace("px", ""), 10),
elemH = parseInt(computedStyle.height.replace("px", ""), 10),
elemDim = [elemW, elemH],
computedDim = [];
image.addEventListener('load', onImageLoad);
image.src = src;
}
function abc() {
getBackgroundSize(document.querySelector(".img"));
}
.img {
background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwIDEwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxyZWN0IHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCIgZmlsbD0iZ3JheSIgLz4KPC9zdmc+") no-repeat left;
width: 200px;
height: 200px;
}
<div class="img"></div>
<button onclick="abc()">click</button>

Related

How do I retrieve background size value in Javascript? [duplicate]

is there an easy way to get the final height and width of a background image with Javascript or jQuery even if a background-size property was applied?
I mean, I know I can get the background image url and load it to an Image object and then get the width and height. But it is the size of the source image. If someone scaled it with CSS then the size changed
How can I find its final size?
#edit
it is different from the question marked as similar because it doesnt say how to get the size in pixels if someone changed the background-size
Using getComputedStyle, I've created this script that returns the width and height of a given element's background, in pixels. It works with:
Dimensions (width or height) set to auto, either explicitly or because no specific value was given (width and height default to auto)
Dimensions set to percentage %
Dimensions set to pixels px
Dimensions set to a combination of any of the previous. (i.e width: 100px; height: auto or width: auto; height: 32.4% or height: 100px; width: 2% or width: 21.2%)
background-size set to cover or contain
It works if background-size is set with an external CSS file, inline CSS, inline header CSS or if it is not set at all (meaning width and height are auto).
Here's a JsFiddle (with cover example)
http://jsfiddle.net/gp4e9d3z/3/
And here's StackOverflow's code snippet (with percentage auto units)
function getBackgroundSize(elem) {
// This:
// * Gets elem computed styles:
// - CSS background-size
// - element's width and height
// * Extracts background URL
var computedStyle = getComputedStyle(elem),
image = new Image(),
src = computedStyle.backgroundImage.replace(/url\((['"])?(.*?)\1\)/gi, '$2'),
cssSize = computedStyle.backgroundSize,
elemW = parseInt(computedStyle.width.replace('px', ''), 10),
elemH = parseInt(computedStyle.height.replace('px', ''), 10),
elemDim = [elemW, elemH],
computedDim = [],
ratio;
// Load the image with the extracted URL.
// Should be in cache already.
image.src = src;
// Determine the 'ratio'
ratio = image.width > image.height ? image.width / image.height : image.height / image.width;
// Split background-size properties into array
cssSize = cssSize.split(' ');
// First property is width. It is always set to something.
computedDim[0] = cssSize[0];
// If height not set, set it to auto
computedDim[1] = cssSize.length > 1 ? cssSize[1] : 'auto';
if(cssSize[0] === 'cover') {
// Width is greater than height
if(elemDim[0] > elemDim[1]) {
// Elem's ratio greater than or equal to img ratio
if(elemDim[0] / elemDim[1] >= ratio) {
computedDim[0] = elemDim[0];
computedDim[1] = 'auto';
} else {
computedDim[0] = 'auto';
computedDim[1] = elemDim[1];
}
} else {
computedDim[0] = 'auto';
computedDim[1] = elemDim[1];
}
} else if(cssSize[0] === 'contain') {
// Width is less than height
if(elemDim[0] < elemDim[1]) {
computedDim[0] = elemDim[0];
computedDim[1] = 'auto';
} else {
// elem's ratio is greater than or equal to img ratio
if(elemDim[0] / elemDim[1] >= ratio) {
computedDim[0] = 'auto';
computedDim[1] = elemDim[1];
} else {
computedDim[1] = 'auto';
computedDim[0] = elemDim[0];
}
}
} else {
// If not 'cover' or 'contain', loop through the values
for(var i = cssSize.length; i--;) {
// Check if values are in pixels or in percentage
if (cssSize[i].indexOf('px') > -1) {
// If in pixels, just remove the 'px' to get the value
computedDim[i] = cssSize[i].replace('px', '');
} else if (cssSize[i].indexOf('%') > -1) {
// If percentage, get percentage of elem's dimension
// and assign it to the computed dimension
computedDim[i] = elemDim[i] * (cssSize[i].replace('%', '') / 100);
}
}
}
// If both values are set to auto, return image's
// original width and height
if(computedDim[0] === 'auto' && computedDim[1] === 'auto') {
computedDim[0] = image.width;
computedDim[1] = image.height;
} else {
// Depending on whether width or height is auto,
// calculate the value in pixels of auto.
// ratio in here is just getting proportions.
ratio = computedDim[0] === 'auto' ? image.height / computedDim[1] : image.width / computedDim[0];
computedDim[0] = computedDim[0] === 'auto' ? image.width / ratio : computedDim[0];
computedDim[1] = computedDim[1] === 'auto' ? image.height / ratio : computedDim[1];
}
// Finally, return an object with the width and height of the
// background image.
return {
width: computedDim[0],
height: computedDim[1]
};
}
// Stuff for debugging
function updateData() {
var background = getBackgroundSize(document.body);
document.getElementById('width').innerHTML = background.width + 'px';
document.getElementById('height').innerHTML = background.height + 'px';
document.getElementById('winWidth').innerHTML = getComputedStyle(document.body).width;
document.getElementById('winHeight').innerHTML = getComputedStyle(document.body).height;
}
// Execute onload, so that the background image is already loaded.
window.onload = window.onresize = updateData;
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
background: url('http://hdwallpapersfit.com/wp-content/uploads/2015/03/images-7.jpg');
background-size: 80% auto;
}
div {
background: rgba(0, 0, 0, 0.5);
color: #fff;
}
<div id="data">
Background width: <span id="width"></span>
<br>
Background height: <span id="height"></span>
<hr>
Body width: <span id="winWidth"></span>
<br>
Body height: <span id="winHeight"></span>
</div>
Using the JSFiddle Here, I found that changing the height or width of the container forces the image to be scaled to the largest height or width. Meaning that the measurement of one edge of the background will be equal to one of the dimension of the container. Using this and some proportions we can calculate the dimensions of the image.
// let .container represent element containing the image
var image; // the image object to the background image
var dim_h, dim_w; // the height and width of the actual image
height = $(".container").height();
width = $(".container").width();
if (height >= width)
{
dim_h = height;
dim_w = (height / image.height) * image.width;
}
else
{
dim_w = width;
dim_h = (width / image.width) * image.height;
}
// dim_w and dim_h contain the width and height of the actual
// background image after scaling
The above code uses the proportion below to calculate it.
(element_height / image_height) == (element_width / image_width)
I think it should give you the answer you want.

why has my javascript canvas drawing function gone haywire?

Canvas iterator supposed to randomize a 20px^2 square between yellow and green across the canvas but for some unknown reason, the pixels are wider than squares until about halfway through the canvas, where the pixels fragment into very tall columns.
The expected result is to have a canvas filling the screen made up of 20x20pixel squares of random yellow or green color, which the canvas automatically scales to change the size and aspect ratio to accommodate window resizing.
The actual result is the canvas seems to produce a third of the screen as very short and wide pixels with the expected color pattern followed below by very tall columns, followed by the page behind all of this.
I've asked around elsewhere to no avail, and I'm looking for any solution that meets the desired goal, so I'm open to anything.
Source replit
snippet:
var has = false
var hasLoaded = false
console.log(window.innerHeight)
console.log(window.innerWidth)
console.log(window.innerWidth*1.5)
var has = false
function toggle() {
console.log("" + has.toString())
if(has){
has = false
document.getElementById('cx').classList.remove('filtered')
}else{
has = true
document.getElementById('cx').classList.add('filtered')
}
}
function resize() {
//window resize event to find canvas size
var h = window.innerHeight
var w = window.innerWidth
var p = 20
var ph = Math.floor(h/p)
var pw = Math.floor(w/p)
let refcx = document.getElementById('cx')
refcx.width = pw
console.log("resized")
dynDraw(w, h, pw, ph, p);
}
function dynDraw(w, h, pw, ph, p) {
//wha
//for drawing after resize event
console.log(w + "w, "+h+"h, "+pw+"pw, "+ph+"ph")
var c = document.getElementById("cx");
var ctx = c.getContext("2d");
ctx.imageSmoothingEnabled = false
//ctx.fillStyle = "#ff0000"
//ctx.fillRect(20, 20, 150, 100);
ctx.fillStyle = "#00ff00"
for(let row = 0; row <= ph; row++)
{ //each row accross width lines, ph stacks
for(let i = 0; i <= pw; i++)
{ //each pixel across height lines, pw stacks
Math.random() >= 0.5 ? ctx.fillStyle = "#fff000" : ctx.fillStyle = "#00ff00"
ctx.fillRect(i, row, pw, pw)
console.log(i + "," + row + "," + pw + "," + ph)
}
}
console.log("done")
}
#cx {
position: fixed;
top: 0px;
left: 0px;
height: 100vh;
width: 100vw;
z-index: -5;
}
.filtered {
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-crisp-edges;
image-rendering: pixelated;
image-rendering: crisp-edges;
}
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<meta name = "viewport" content = "width = device-width">
<title>Canvas Testing</title>
<link href = "style.css" rel = "stylesheet"></link>
<script src = "script.js"></script>
</head>
<body onload="resize();" >
<button id="buttonToDoStuff" onclick="toggle();">toggle filter</button>
<canvas id="cx" width="100" height="100">
Your browser does not support the HTML5 canvas tag.
</canvas>
</body>
</html>
This line
ctx.fillRect(i, row, pw, pw)
should probably be
ctx.fillRect(i, row, 1, 1)
instead.
You also need to set both width and height in the resize handler. You only set width.
The issue is because you've sized the canvas draw area (the context) such that each square you want is 1x1 relative to the context dimensions. The <canvas>'s width and height attributes control the canvas element and the canvas drawing context dimensions. The CSS width and height override the element dimensions but do not effect the drawing context dimensions, the drawing context is instead stretched to fit the element.
var has = false
var hasLoaded = false
console.log(window.innerHeight)
console.log(window.innerWidth)
console.log(window.innerWidth*1.5)
var has = false
function toggle() {
console.log("" + has.toString())
if(has){
has = false
document.getElementById('cx').classList.remove('filtered')
}else{
has = true
document.getElementById('cx').classList.add('filtered')
}
}
function resize() {
//window resize event to find canvas size
var h = window.innerHeight
var w = window.innerWidth
var p = 20
var ph = Math.floor(h/p)
var pw = Math.floor(w/p)
let refcx = document.getElementById('cx')
refcx.width = pw
refcx.height = ph
console.log("resized")
dynDraw(w, h, pw, ph, p);
}
function dynDraw(w, h, pw, ph, p) {
//wha
//for drawing after resize event
console.log(w + "w, "+h+"h, "+pw+"pw, "+ph+"ph")
var c = document.getElementById("cx");
var ctx = c.getContext("2d");
ctx.imageSmoothingEnabled = false
//ctx.fillStyle = "#ff0000"
//ctx.fillRect(20, 20, 150, 100);
ctx.fillStyle = "#00ff00"
for(let row = 0; row <= ph; row++)
{ //each row accross width lines, ph stacks
for(let i = 0; i <= pw; i++)
{ //each pixel across height lines, pw stacks
Math.random() >= 0.5 ? ctx.fillStyle = "#fff000" : ctx.fillStyle = "#00ff00"
ctx.fillRect(i, row, 1, 1)
console.log(i + "," + row + "," + pw + "," + ph)
}
}
console.log("done")
}
#cx {
position: fixed;
top: 0px;
left: 0px;
height: 100vh;
width: 100vw;
z-index: -5;
}
.filtered {
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-crisp-edges;
image-rendering: pixelated;
image-rendering: crisp-edges;
}
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<meta name = "viewport" content = "width = device-width">
<title>Canvas Testing</title>
<link href = "style.css" rel = "stylesheet"></link>
<script src = "script.js"></script>
</head>
<body onload="resize();" >
<button id="buttonToDoStuff" onclick="toggle();">toggle filter</button>
<canvas id="cx">
Your browser does not support the HTML5 canvas tag.
</canvas>
</body>
</html>

Scale an image to fit when replacing an image

I'm trying to implement a behaviour by which I can add an initial image to a canvas (placeholder) and then subsequently I can then choose a different image to replace that image - that new image should then scale itself to "fit" within the bounds of the old image. For example if I choose a portrait image as the "placeholder" and then choose a landscape image to replace it, Id expect the landscape image to first scale its width and maintain aspect ratio, and then vertically align itself within the boundaries of the placeholder dimensions.
Here is a jsfiddle of what I have working so far: https://jsfiddle.net/cgallagher/co8dg527/1/
and here is the code:
var canvas = new fabric.Canvas('stage');
var cw = canvas.getWidth()
var ch = canvas.getHeight()
var _currentImage;
function setProductImage(url){
var oldWidth;
var oldHeight;
var oldLeft;
var oldTop;
fabric.Image.fromURL(url, function(img) {
if (_currentImage) {
oldWidth = _currentImage.getScaledWidth()
oldHeight = _currentImage.getScaledHeight()
oldLeft = _currentImage.left
oldTop = _currentImage.top
canvas.remove(_currentImage);
}
_currentImage = img;
img.set({ 'left': oldLeft || 0 })
img.set({ 'top': oldTop || 0 })
if (oldHeight && oldHeight > img.getScaledHeight()){
img.scaleToWidth(oldWidth);
img.set({'height': oldHeight })
} else if (oldWidth > img.getScaledWidth()){
img.scaleToHeight(oldHeight);
img.set({'width': oldWidth })
}
img.selectable = true
canvas.add(img).setActiveObject(img);
});
}
function addImage(url){
setProductImage(url)
canvas.renderAll()
}
You can see that the image does scale the way I'd like but it doesn't then align itself.
I'm toying with the idea of dropping a bounding box around the image too and possibly trying to align and scale within that but I'm not sure this is even possible with fabric?
This is what I had done.
When you run scaleToWidth and scaleToHeight the scaleX andscaleY is changing and you need to adjust the oldHeight and oldWidth to the new img.scaleX/img.scalaY
I also rewrite _renderFill method from fabric.Image.prototype to create that offset effect.
Check here:https://jsfiddle.net/mariusturcu93/co8dg527/37/
Code
<html>
<head>
<title>Fabric kicking</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.0/fabric.js"></script>
<style>
#stage {
border: solid 1px #333;
}
</style>
</head>
<body>
<button onclick="addImage('https://s.hs-data.com/bilder/spieler/gross/208995.jpg')">Add image</button>
<button onclick="addImage('https://cdn.images.express.co.uk/img/dynamic/67/590x/Mateusz-Klich-883903.jpg')">add another image</button>
<canvas id="stage" width="600" height="600"></canvas>
<script>
var canvas = new fabric.Canvas('stage');
var cw = canvas.getWidth()
var ch = canvas.getHeight()
var _currentImage;
function setProductImage(url){
var oldWidth;
var oldHeight;
var oldLeft;
var oldTop;
fabric.Image.fromURL(url, function(img) {
if (_currentImage) {
oldWidth = _currentImage.getScaledWidth()
oldHeight = _currentImage.getScaledHeight()
oldLeft = _currentImage.left
oldTop = _currentImage.top
canvas.remove(_currentImage);
}
_currentImage = img;
img.set({ 'left': oldLeft || 0 })
img.set({ 'top': oldTop || 0 })
if (oldHeight && oldHeight > img.getScaledHeight()){
img.scaleToWidth(oldWidth);
img.set({'height': oldHeight/img.scaleX})
} else if (oldWidth > img.getScaledWidth()){
img.scaleToHeight(oldHeight);
img.set({'width': oldWidth/img.scaleY })
}
img.selectable = true
canvas.add(img).setActiveObject(img);
});
}
function addImage(url){
setProductImage(url)
canvas.renderAll()
}
</script>
<img src="https://s.hs-data.com/bilder/spieler/gross/208995.jpg" />
<img src="https://cdn.images.express.co.uk/img/dynamic/67/590x/Mateusz-Klich-883903.jpg" />
</body>
</html>
fabric.Image.prototype._renderFill rewrite
fabric.Image.prototype._renderFill= (function(renderFill){
return function(ctx) {
var w = this.width, h = this.height, sW = w * this._filterScalingX, sH = h * this._filterScalingY,
x = -w / 2, y = -h / 2, elementToDraw = this._element;
y = y + Math.abs((this._element.height-h)/2);
x = x + Math.abs((this._element.width-w)/2);
elementToDraw && ctx.drawImage(elementToDraw,
this.cropX * this._filterScalingX,
this.cropY * this._filterScalingY,
sW,
sH,
x, y, w, h);
}
})()

fengyuanchen Cropper - How to Fit Image into Canvas If Rotated?

I gone through documentation of cropper by fengyuanchen. I want the image to be fit by default into canvas if rotated. But I couldnt find a way to achieve this. Any idea how to achieve this functionality?
I want it to be like this to be default: link
Check issue demo here: link
I fixed this behavior but for my special needs. I just needed one rotate button which rotates an image in 90° steps. For other purposes you might extend/change my fix.
It works in "strict" mode by dynamically change the cropbox dimensions.
Here my function which is called, when I want to rotate an image. Ah and additionally the misplacement bug has also been fixed.
var $image;
function initCropper() {
$image = $('.imageUploadPreviewWrap > img').cropper({
autoCrop : true,
strict: true,
background: true,
autoCropArea: 1,
crop: function(e) {
}
});
}
function rotateImage() {
//get data
var data = $image.cropper('getCropBoxData');
var contData = $image.cropper('getContainerData');
var imageData = $image.cropper('getImageData');
//set data of cropbox to avoid unwanted behavior due to strict mode
data.width = 2;
data.height = 2;
data.top = 0;
var leftNew = (contData.width / 2) - 1;
data.left = leftNew;
$image.cropper('setCropBoxData',data);
//rotate
$image.cropper('rotate', 90);
//get canvas data
var canvData = $image.cropper('getCanvasData');
//calculate new height and width based on the container dimensions
var heightOld = canvData.height;
var heightNew = contData.height;
var koef = heightNew / heightOld;
var widthNew = canvData.width * koef;
canvData.height = heightNew;
canvData.width = widthNew;
canvData.top = 0;
if (canvData.width >= contData.width) {
canvData.left = 0;
}
else {
canvData.left = (contData.width - canvData.width) / 2;
}
$image.cropper('setCanvasData', canvData);
//and now set cropper "back" to full crop
data.left = 0;
data.top = 0;
data.width = canvData.width;
data.height = canvData.height;
$image.cropper('setCropBoxData',data);
}
This is my extended code provided by AlexanderZ to avoid cuttong wider images than container :)
var contData = $image.cropper('getContainerData');
$image.cropper('setCropBoxData',{
width: 2, height: 2, top: (contData.height/ 2) - 1, left: (contData.width / 2) - 1
});
$image.cropper('rotate', 90);
var canvData = $image.cropper('getCanvasData');
var newWidth = canvData.width * (contData.height / canvData.height);
if (newWidth >= contData.width) {
var newHeight = canvData.height * (contData.width / canvData.width);
var newCanvData = {
height: newHeight,
width: contData.width,
top: (contData.height - newHeight) / 2,
left: 0
};
} else {
var newCanvData = {
height: contData.height,
width: newWidth,
top: 0,
left: (contData.width - newWidth) / 2
};
}
$image.cropper('setCanvasData', newCanvData);
$image.cropper('setCropBoxData', newCanvData);
Not a direct answer to the question ... but i'm betting many people that use this plugin will find this helpfull..
Made this after picking up #AlexanderZ code to rotate the image.
So ... If you guys want to ROTATE or FLIP a image that has already a crop box defined and if you want that cropbox to rotate or flip with the image ... use these functions:
function flipImage(r, data) {
var old_cbox = $image.cropper('getCropBoxData');
var new_cbox = $image.cropper('getCropBoxData');
var canv = $image.cropper('getCanvasData');
if (data.method == "scaleX") {
if (old_cbox.left == canv.left) {
new_cbox.left = canv.left + canv.width - old_cbox.width;
} else {
new_cbox.left = 2 * canv.left + canv.width - old_cbox.left - old_cbox.width;
}
} else {
new_cbox.top = canv.height - old_cbox.top - old_cbox.height;
}
$image.cropper('setCropBoxData', new_cbox);
/* BUG: When rotated to a perpendicular position of the original position , the user perceived axis are now inverted.
Try it yourself: GO to the demo page, rotate 90 degrees then try to flip X axis, you'll notice the image flippped vertically ... but still ... it fliped in relation to its original axis*/
if ( r == 90 || r == 270 || r == -90 || r == -270 ) {
if ( data.method == "scaleX") {
$image.cropper("scaleY", data.option);
} else {
$image.cropper("scaleX", data.option);
}
} else {
$image.cropper(data.method, data.option);
}
$image.cropper(data.method, data.option);
}
function rotateImage(rotate) {
/* var img = $image.cropper('getImageData'); */
var old_cbox = $image.cropper('getCropBoxData');
var new_cbox = $image.cropper('getCropBoxData');
var old_canv = $image.cropper('getCanvasData');
var old_cont = $image.cropper('getContainerData');
$image.cropper('rotate', rotate);
var new_canv = $image.cropper('getCanvasData');
//calculate new height and width based on the container dimensions
var heightOld = new_canv.height;
var widthOld = new_canv.width;
var heightNew = old_cont.height;
var racio = heightNew / heightOld;
var widthNew = new_canv.width * racio;
new_canv.height = Math.round(heightNew);
new_canv.width = Math.round(widthNew);
new_canv.top = 0;
if (new_canv.width >= old_cont.width) {
new_canv.left = 0;
} else {
new_canv.left = Math.round((old_cont.width - new_canv.width) / 2);
}
$image.cropper('setCanvasData', new_canv);
if (rotate == 90) {
new_cbox.height = racio * old_cbox.width;
new_cbox.width = racio * old_cbox.height;
new_cbox.top = new_canv.top + racio * (old_cbox.left - old_canv.left);
new_cbox.left = new_canv.left + racio * (old_canv.height - old_cbox.height - old_cbox.top);
}
new_cbox.width = Math.round(new_cbox.width);
new_cbox.height = Math.round(new_cbox.height);
new_cbox.top = Math.round(new_cbox.top);
new_cbox.left = Math.round(new_cbox.left);
$image.cropper('setCropBoxData', new_cbox);
}
var photoToEdit = $('.photo_container img');
$( photoToEdit ).cropper({
autoCrop : true,
crop: function(e) {}
});
$("#rotate_left_btn").click( function () {
$( photoToEdit ).cropper('rotate', -90);
var containerHeightFactor = $(".photo_container").height() / $( photoToEdit).cropper('getCanvasData').height;
if ( containerHeightFactor < 1 ) { // if canvas height is greater than the photo container height, then scale (on both x and y
// axes to maintain aspect ratio) to make canvas height fit container height
$( photoToEdit).cropper('scale', containerHeightFactor, containerHeightFactor);
} else if ( $( photoToEdit).cropper('getData').scaleX != 1 || $( photoToEdit).cropper('getData').scaleY != 1 ) { // if canvas height
// is NOT greater than container height but image is already scaled, then revert the scaling cuz the current rotation will bring
// the image back to its original orientation (landscape/portrait)
$( photoToEdit).cropper('scale', 1, 1);
}
}
I Fixed this issue hope fully. i have added or changed the option to 0 (viewMode: 0,). Now its working well.
cropper = new Cropper(image, {
dragMode: 'none',
viewMode: 0,
width: 400,
height: 500,
zoomable: true,
rotatable: true,
crop: function(e) {
}
});
document.getElementById('rotateImg').addEventListener('click', function () {
cropper.rotate(90);
});

Getting image width on image load fails on IE

I have a image resizer function that resize images proportional. On every image load a call this function with image and resize if its width or height is bigger than my max width and max height. I can get img.width and img.height in FF Chrome Opera Safari but IE fails. How can i handle this?
Let me explain with a piece of code.
<img src="images/img01.png" onload="window.onImageLoad(this, 120, 120)" />
function onImageLoad(img, maxWidth, maxHeight) {
var width = img.width; // Problem is in here
var height = img.height // Problem is in here
}
In my highligted lines img.width don't work on IE series.
Any suggestion?
Thanks.
Don't use width and height. Use naturalWidth and naturalHeight instead. These provide the image unscaled pixel dimensions from the image file and will work across browsers.
Man, I was looking for this for 2 days. Thanks.
I'm using jQuery, but it doesnt matter. Problem is related to javascript in IE.
My previous code:
var parentItem = $('<div/>')
.hide(); // sets display to 'none'
var childImage = $('<img/>')
.attr("src", src)
.appendTo(parentItem) // sets parent to image
.load(function(){
alert(this.width); // at this point image is not displayed, because parents display parameter is set to 'none' - IE gives you value '0'
});
This is working in FF, Opera and Safari but no IE. I was getting '0' in IE.
Workaround for me:
var parentItem = $('<div/>')
.hide();
var childImage = $('<img/>')
.attr("src", src)
.load(function(){
alert(this.width); // at this point image css display is NOT 'none' - IE gives you correct value
childImage.appendTo(parentItem); // sets parent to image
});
This is how I solved it (because it's the only js on the site I didn't want to use a library).
var imageElement = document.createElement('img');
imageElement.src = el.href; // taken from a link cuz I want it to work even with no script
imageElement.style.display = 'none';
var imageLoader = new Image();
imageLoader.src = el.href;
imageLoader.onload = function() {
loaderElement.parentElement.removeChild(loaderElement);
imageElement.style.position = 'absolute';
imageElement.style.top = '50%';
imageElement.style.left = '50%';
// here using the imageLoaders size instead of the imageElement..
imageElement.style.marginTop = '-' + (parseInt(imageLoader.height) / 2) + 'px';
imageElement.style.marginLeft = '-' + (parseInt(imageLoader.width) / 2) + 'px';
imageElement.style.display = 'block';
}
It's because IE can't calculate width and height of display: none images. Use visibility: hidden instead.
Try
function onImageLoad(img, maxWidth, maxHeight) {
var width = img.width; // Problem is in here
var height = img.height // Problem is in here
if (height==0 && img.complete){
setTimeOut(function(){onImageLoad(img, maxWidth, maxHeight);},50);
}
}
var screenW = screen.width;
var screenH = screen.height;
//alert( screenW );
function checkFotoWidth( img, maxw )
{
if( maxw==undefined)
maxw = 200;
var imgW = GetImageWidth(img.src);
var imgH = GetImageHeight(img.src);
//alert(GetImageWidth(img.src).toString()); // img.width); // objToString(img));
if (imgW > maxw || (img.style.cursor == "hand" && imgW == maxw))
{
if (imgW > screenW) winW = screenW;
else winW = imgW;
if (imgH > screenH) winH = screenH;
else winH = imgH;
img.width=maxw;
img.style.cursor = "pointer";
img.WinW = winW;
img.WinH = winH;
//alert("winW : " + img.WinW);
img.onclick = function() { openCenteredWindow("Dialogs/ZoomWin.aspx?img=" + this.src, this.WinW, this.WinH, '', 'resizable=1'); }
img.alt = "Klik voor een uitvergroting :: click to enlarge :: klicken Sie um das Bild zu vergrössern";
//alert("adding onclick);
}
}
function GetImageWidth(imgSrc)
{
var img = new Image();
img.src = imgSrc;
return img.width;
}
function GetImageHeight(imgSrc)
{
var img = new Image();
img.src = imgSrc;
return img.height;
}
I'd try this:
function onImageLoad(img, maxWidth, maxHeight) {
var width, height;
if ('currentStyle' in img) {
width = img.currentStyle.width;
height = img.currentStyle.height;
}
else {
width = img.width;
height = img.height;
}
// whatever
}
edit — and apparently if I were to try that I'd learn it doesn't work :-) OK, well "width" and "height" definitely seem to be attributes of <img> elements as far as IE is concerned. Maybe the problem is that the "load" event is firing for the element at the wrong time. To check whether that's the case, I would then try this:
function onImageLoad(img, maxWidth, maxHeight) {
var width, height;
var i = new Image();
i.onload = function() {
width = i.width; height = i.height;
// ... stuff you want to do ...
};
i.src = img.href;
}
getDisplay().getImage().setUrl(imgURL);
final Image img = new Image(imgURL);
int w=img.getWidth();
int h=img.getHeight();

Categories

Resources