AFAIK, to resize a loaded image in HTML5 canvas would be done like this:
var img = new Image();
img.onload = function () {
ctx.drawImage(img, 0, 0, 300, 200); // resizes image to 300px wide, 200px high
}
img.src = 'images/myimage.jpg';
But then I realised that the image wouldn't be proportionally correct. So then I tried using one parameter only (just like in HTML) but I found that didn't work either.
How do I proportionally resize the image?
Get the img.width and img.height, then calculate the proportional height according to what width you're sizing to.
For example:
ctx.drawImage(img, 300, 0, 300, img.height * (300/img.width));
I wrote a blog article on this topic last last year. You can read it here. Basically it provides a function for scaling an image with a proper aspect ratio. It includes supporting both landscape and portrait orientations and sizing between the two. You can even choose between "letterbox" and "pan and scan (zoom)" mode.
It was written with div positioning in mind, but could be easily be understood for canvas.
Near the bottom of the page is the "ScaleImage" function. That might be what you want. Then you can apply it as follows:
var img = new Image();
img.onload = function () {
var result = ScaleImage(img.width, img.height, 300, 200, true);
ctx.drawImage(img, result.targetleft, result.targettop, result.width, result.height); // resizes image to a target size of 300x200 using letterbox mode
}
img.src = 'images/myimage.jpg';
You can replace result.targetleft and result.targettop with "0" if you don't want the image centered.
Related
I'm having a problem with loading image into canvas - the image is somehow scaled.
Background: I've got several canvases on my web page, I want to load images into them. When constructing, I'm not sure about the dimension, because the size depends on the screen size.
So I create div and canvas, use css to have it in the size that I want it to have and print an image onto the canvas. There would couple more things to do with the image (i.e. decide based on the ratio if I need to center it vertically or horizontally), but those are not really important at this point. The problem is that the image is rendered "zoomed".
Example: the javascript piece is here:
$("canvas").each(function() {
var context = $(this)[0].getContext('2d');
var img = new Image;
img.src = 'http://i67.tinypic.com/n38zdv.jpg';
$(img).load(function() {
context.drawImage(this, 0, 0);
});
//img will print 400 (correct, thats the width of the img)
//canvas will print based on the screen size (correct)
//img displayed in the canvas shows 300px out of 400px, it's zoomed (not correct)
$(this).parent().append(
'img width: '+img.width+
', canvas width: '+$(this).width());
});
I put the whole example with HTML and CSS to https://jsfiddle.net/7zdrfe58/11/.
I'm trying on Mac. Safari and Chrome work the same (i.e. with the zoom).
I would very appreciate help with this!! Thanks a lot
drawImage lets you specify the width and height of the image. You can get the canvas width like so:
$("canvas").each(function() {
var canvas = this;
var context = canvas.getContext('2d');
var img = new Image;
img.src = 'http://i67.tinypic.com/n38zdv.jpg';
$(img).load(function() {
context.drawImage(this, 0, 0, canvas.width, canvas.height);
});
});
Check out your working code here:
https://jsfiddle.net/ucxdLsq9/
The documentation of the drawImage signatures can be found here:
https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/drawImage
Give proper width and height to drawImage.
context.drawImage(this, 0, 0 ,300 ,160);
Updated Fiddle
When using the HTML5 drag and drop API, it would appears though the .width property on has no impact on the width of an image being used as an icon for dragging. Take this fiddle for example: http://jsfiddle.net/cnAHv/7/. You can set dragIcon.width to anything you want, and it will not change the actual width of the icon.
Most of the resources on the web seem to arbitrarily set dragIcon.width to 100. Is this just a matter of people copying eachother's code without checking functionality?
So...
Is the width property on an image variable actually something that setDragImage() will accept?
If not, how would you set the width of the icon without manually changing sizing the image in a program like photoshop?
When you use an <img> in setDragImage Javascript will just use the actual image bitmap data, ignoring other attributes like width. Check the specs.
However if you do something like this:
function handleDragStart(e) {
var dragIcon = document.createElement('img');
dragIcon.src = 'http://jsfiddle.net/favicon.png';
dragIcon.width = '100';
var div = document.createElement('div');
div.appendChild(dragIcon);
document.querySelector('body').appendChild(div);
e.dataTransfer.setDragImage(div, -10, -10);
}
http://jsfiddle.net/cnAHv/9/
You will see the drag shadow now contains the bigger image. It occurs because when we use other visible HTML elements (that's why I appended the DIV to the body), the browser will use its rendered view as a drag image.
This answer might be a bit late but you can also use a canvas to scale your original image.
function handleDragStart(e) {
var dragIcon = document.createElement('img');
dragIcon.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC';
var width = 100;
var height = width * (3/4); // The height must be set explicitly. I'm assuming the image is 4:3 for this example
var c = document.createElement("canvas");
c.width = width;
c.height = height;
var ctx = c.getContext('2d');
ctx.drawImage(dragIcon,0,0,width,height);
dragIcon.src = c.toDataURL();
e.dataTransfer.setDragImage(dragIcon, -10, -10);
}
http://jsfiddle.net/cnAHv/138/
The only downside to this is that the canvas may be tainted if the image doesn't come from the same origin. More on tainted canvases here
I have an image to be drawn on an html5 canvas. I want to resize this image to a certain height and width before being drawn onto the canvas. My code currently consists of:
img = new Image();
img.src = "vivo.jpg";
// calcuate new height and width
img.height = newheight;
img.width = newwidth;
$("#cnvs").attr({
"height" : newheight,
"width" : newwidth
});
context.drawImage(img, 0, 0);
The code only works if I include the width and height parameters in the context.drawImage() function itself. But what I don't understand is, why the image isn't resized already before the context.drawImage() function accesses it.
I have also printed alert statements to check "img.height" and "img.width" and it is indeed set to the values of newheight, newwidth. Why would the context.drawImage() access the old values of height and width?
Edit - Additionally, when I display the image on the webpage (not on the canvas, but just the webpage), the resized image is shown. But the canvas does not show the resized image. I don't understand why
The reason why it isn't working is because you are changing the properties of the <img> HTML node. These properties are layouting instructions how the node is displayed in the document (which are obsolete, by the way. Use CSS for layouting). The width and height of the image material displayed in the image-element is independent from this.
I am trying to write my first game in JavaScript and HTML5 but I am stuck. I want to only draw a image into HTML canvas which has set background-image but the image is still magnified and additionally bad positioned and I don't know why. Let's show my code.
In HTML file in body I have only canvas #gameCanvas, that's all.
And this is JavaSript code.
function prepare()
{
var canvas = $('#gameCanvas');
var context = canvas[0].getContext('2d');
$('#wrapper').css({"width": "704"});
canvas.css({"width": "704",
"height": "672",
"backgroundImage": "url(./images/map.png)"});
var player1 = new Image();
player1.src = "./images/player1.png";
player1.onload = function() {
context.drawImage(player1, 0, 0, 26, 36, 100, 100, 26, 36);
};
}
$(function(){
prepare();
})
And that's my weird result -> 1.result
I find out that when I remove setting of css properties width and height of canvas it draws image correct but canvas has only default size of according to browser. -> 2.result
I am totally confused.
You are using CSS to set the size of the canvas. This will only enlarge the default 300x150 sized canvas to the size you set with CSS (like if it was an image) (and besides, for CSS to work with other values than 0 you need to specify a unit - but ignore this for a moment).
You need to set the size explicitly using the canvas properties (attributes) width and height.
canvas[0].width = 704; // no unit required for the attributes
canvas[0].height = 672;
I've got the following piece of code:
HTML
<img src="http://hollywoodteenonline.com/wp-content/uploads/2011/12/justin_bieber_someday_fragrance_dree_hemingway.jpg" id="imagem"/>
<canvas id="mycanvas">
CSS
#mycanvas{
height:200px;
width: 200px;
border: solid;
color: black;
}
#imagem{
height:200px;
width: 200px;
}
Javascript
var canvas = document.getElementById("mycanvas"),
ctx = canvas.getContext("2d"),
img = document.getElementById("imagem");
ctx.drawImage(img,0,0);
As you can see, the canvas doens't follow up the resize of the original image. As the code is written it "should" show all of the source but resized to de designated canvas. Is there any way to go around this?
Issues
First issue is that you don't set a size for your canvas element by using its properties. This is the only way you can affect the content of the canvas and not settings it means it will default to 300 x 150 pixel no matter what you set as CSS rule for it.
Second issue is that you are using CSS to the set size. This will affect the element itself, not the content of the canvas. Technically this isn't wrong in case you want to scale the canvas as an image, but it won't do anything for the canvas and the result is that you just scale the 300x150 pixels around.
The third issue, if the image is of different size than 300x150 it won't fit the canvas (too small or get cropped if too big).
Solutions
One solution is to set the size of the canvas to the size of the image and paint the image in:
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
Now you can resize the canvas (as an image using CSS) if you want.
Or you can scale the image using the size of the canvas (remove the CSS rule; and you still need to set a size for canvas):
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
LIVE DEMO HERE
You also need to take care in how you invoke your script. For images to work with canvas they need to be loaded. As they load asynchronous you need to handle load events one way or another (ie. inside a window.onload in this case).