I want to draw an image from jpg file on canvas.
My code:
var canvas = document.getElementById('my_canvas');
var ctx = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 0, 0);
};
imageObj.src = 'img/my_image.jpg';
The problem is that the image on canvas is much bigger than in file. Why? How can I draw image real size?
UPDATE:
result: http://jsfiddle.net/AJK2t/
This is your problem:
<canvas style="width: 700px; height: 400px;" id="konf"></canvas>
You are setting the visual size of your canvas, but not the number of pixels. Consequently the browser is scaling the canvas pixels up.
The simplest fix is:
<canvas width="700" height="400" id="konf"></canvas>
The width and height parameters control the number of pixels in the canvas. With no CSS styling, the default visual size of the canvas will also be this size, resulting in one canvas pixel per screen pixel (assuming you have not zoomed the web browser).
Copy/pasting from my answer to a related question:
Think about what happens if you have a JPG that is 32x32 (it has exactly 1024 total pixels) but specify via CSS that it should appear as width:800px; height:16px. The same thing applies to HTML Canvas:
The width and height attributes of the canvas element itself decide how many pixels you can draw on. If you don't specify the height and width of the canvas element, then per the specs:
"the width attribute defaults to 300, and the height attribute defaults to 150."
The width and height CSS properties control the size that the element displays on screen. If the CSS dimensions are not set, the intrinsic size of the element is used for layout.
If you specify in CSS a different size than the actual dimensions of the canvas it must be stretched and squashed by the browser as necessary for display. You can see an example of this here: http://jsfiddle.net/9bheb/5/
Working Example: http://jsfiddle.net/jzF5R/
In order to scale an image you need to provide the scaled width and height you want to ctx.drawImage():
// x, y, width, height
ctx.drawImage(imageObj, 0, 0, 100, 50);
Maintain original image size:
ctx.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
Keep canvas from overflowing off the page:
ctx.canvas.width = document.body.clientWidth;
You can easily scale the image width and height to 70% of original:
ctx.drawImage(imageObj, 0, 0, imageObj.width * 0.7, imageObj.height * 0.7);
To display a MJPEG stream on a canvas (or something else) without define the width and the height of the canvas in HTML, so only using CSS to get a responsive canvas and fit with the page, I use that:
//get size from CSS
var sizeWidth = context.canvas.clientWidth;
var sizeHeight = context.canvas.clientHeight;
//here the solution, it replaces HTML width="" height=""
canvas.width = sizeWidth;
canvas.height = sizeHeight;
...........
context.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height, 0, 0, sizeWidth, sizeHeight);
The picture is entirely contained in the canvas whatever the size of the canvas (the rate between height and width is not kept but it doesn't matter, an height:auto; in css can fix that).
Et voilà !
Related
I am doing drag and drop and want to use a different drag image than the default. But I would also like to scale the size of the drag image depending on the size of the element where the drag starts. I have tried doing the following:
<div id="drag-with-image" draggable="true">drag me</div>
<script>
document.getElementById("drag-with-image").addEventListener("dragstart", function(e) {
var img = document.createElement("img");
img.src = "https://www.w3schools.com/css/paris.jpg";
img.style.width = "60px";
img.style.height = "40px";
e.dataTransfer.setDragImage(img, 0, 0);
}, false);
</script>
But the drag image is always displayed as full size.
Is there any way the drag image size can be scaled dynamically?
Yes, it is possible to scale a custom drag image.
The Problem
If you're using setDragImage with an image element, what will be drawn is the image in its intrinsic size (content size before any modification). This means that setting the image size doesn't help. However, as mentioned in MDN Docs, you can also set a drag image to be something else:
If Element is an img element, then set the drag data store bitmap to the element's image (at its intrinsic size); otherwise, set the drag data store bitmap to an image generated from the given element (the exact mechanism for doing so is not currently specified).
Furthermore, it also mentions that the "other elements" can be any visible element or even a <canvas>:
However, if a custom image is desired, the DataTransfer.setDragImage() method can be used to set the custom image to be used. The image will typically be an element but it can also be a or any other visible element.
Solution
To draw an image that is smaller than its intrinsic size and setting it to drag image, you can:
Load the image to an image element
Create a canvas to be drawn with the image
When drawing to the canvas, adjust the width and height of the drawn image accordingly
Here's a working example.
document.getElementById('drag-with-image').addEventListener('dragstart', function(e) {
var img = document.createElement('img')
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
// Setting img src
img.src = 'https://www.w3schools.com/css/paris.jpg'
// Drawing to canvas with a smaller size
canvas.width = img.width * 0.1
canvas.height = img.height * 0.1
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
// Setting drag image with drawn canvas image
e.dataTransfer.setDragImage(canvas, 0, 0)
}, false)
<div id="drag-with-image" draggable="true">drag me</div>
I am loading an image and then drawing that image to a canvas. I am also scaling the image down to fit the canvas. When I do this, the image draws onto the canvas at the proper width but the height is about 1/4 of what the canvas' actual height is.
//Calculate height from canvas-to-image width ratio
var width = canvas.width;
var height = ( width / img.width ) * img.height;
//Draw scale image (This results in a squished height, despite "height" being correct)
context.drawImage( image, 0, 0, img.width, img.height, 0, 0, width, height );
Even though height is correct (checked in console), the image draws to the canvas at a much smaller height.
Also, when I check the ratio of the canvas.width / canvas.height vs img.width / img.height I get: .707234 vs .707818. That's so close it could not account for the huge height problem.
Why does this happen? How do I fix this?
EDIT: On Chrome, this exact code shows correctly.
var ratio = ( width / img.width ) * img.width; will leave ratio equal to width and nothing learned from img.width since you're undoing the division with multiplication by the same value. This will mess up your height calculation which will mess up the drawn image.
Try it like this:
var ratio = ( width / img.width );
And you'll get a real ratio between the canvas and images height. But I don't think you want that anyway.
What you want is to keep the aspect ratio (width/height) of your image the same and shrink it to fit. That is possible even if the canvas has a different aspect ratio by leaving unused space on the sides or top and bottom.
So what you really need to know is which you should use to scale your image. Width or height.
If the image has a greater aspect ratio than the canvas then scale using width. That means make the widths the same and set the height at whatever preserves the aspect ratio of the image. This will leave blanks top and/or bottom.
If the image has a lower aspect ratio than the canvas then scale using height. Blah blah height same. Scale width. Blah blah blanks on the sides.
var imgRatio = img.width / img.height;
var canRatio = canvas.width / canvas.height;
var scaledWidth = img.width * (canvas.height / img.height);
var scaledHeight = img.height * (canvas.width / img.height);
if (imgRatio > canRatio) {
context.drawImage( image, 0, 0, canvas.width, scaledHeight );
} else {
context.drawImage( image, 0, 0, scaledWidth, canvas.height );
}
Also if you aren't doing any clipping of the image, only scaling, then these parameters are all you need.
http://www.w3schools.com/tags/canvas_drawimage.asp
This is a bug in iOS Safari. It's described here: Mobile Safari renders <img src="data:image/jpeg;base64..."> scaled on Canvas?
Solution is here: https://github.com/stomita/ios-imagefile-megapixel
Problem
If you have an image with very high resolution (greater than 1024x1024) it will be subsampled (reduces the number of pixels by 16x). When doing this, Safari introduces an error that results in a too-small vertical height.
Solution
To solve, this, you take small chunks of the image (like reading from a file into a buffer in chunks), adjust for the vertical height differential, draw just those to a temporary canvas, and then draw that temporary canvas' pixels to the destination canvas.
I'm playing around with html5 canvas, and I have came across some strange behaviour. I'm doing pretty basic animation based on these three steps:
I call update() function inside wich I change x and y of the objects.
I clear the canvas with this line of code this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
I redraw all the elements.
This is how I draw the figures:
// drawing a circle
function drawCircle(x,y) {
var rad = 5;
ctx.beginPath();
ctx.arc(x, y, rad, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
}
// and a rect
function drawRect(x, y,) {
var width = 60,
height = 10;
ctx.fillRect(x, y, width, height);
}
Now I expect my rectangle to be 60px width and 10px height. I've added a div after the <canvas> tag and set its width and height to 60px and 10px respectively in order to illustrate the discrepancy. As you can see on the picture, obviously my rectangle isn't 60х10. The same apply to the circle. What am I missing here?
here is fiddle
Set the size of the canvas using it's width and height attributes (for tag) or properties (in JS):
<canvas id="..." width=400 height=400></canvas>
in JS:
canvasEl.width = 400;
canvasEl.height = 400;
Don't use CSS as that only affects the canvas element but not its bitmap (consider canvas as an image). The default size of a canvas is 300 x 150 pixels. If you don't change that size it will be stretched to the size you set using CSS. This is why we in general don't recommend using CSS (there are special cases though where CSS is necessary such as print situations, non 1:1 pixel aspect ratios and so forth).
Probably it's because you styled your canvas to a costum with/height. A canvas' default width/height is 150*300 and if you do not scale well you obtain such result as you found.
drawImage(image, x, y, width, height)
This adds the width and height parameters, which indicate the size to which to
scale the image when drawing it onto the canvas.
So to be short you have to scale your drawings.
the Canvas element on MDN
Canvas drawing on MDN
I have a canvas object that I want to put an image in for a web application. I can get the image loaded, but I've run into 2 problems: The image won't stretch to the canvas, and the canvas won't stretch to cover the entire div in any browser but Firefox.
http://jsfiddle.net/LFJ59/1/
var canvas = $("#imageView");
var context = canvas.get(0).getContext("2d");
$(document).ready(drawImage());
$(window).resize(refreshCanvas());
refreshCanvas();
function refreshCanvas() {
//canvas/context resize
canvas.attr("width", $(window).get(0).innerWidth / 2);
canvas.attr("height", $(window).get(0).innerHeight / 2);
drawImage();
};
function drawImage() {
//shadow
context.shadowBlur = 20;
context.shadowColor = "rgb(0,0,0)";
//image
var image = new Image();
image.src = "http://www.netstate.com/states/maps/images/ca_outline.gif";
$(image).load(function () {
image.height = canvas.height();
image.width = canvas.width();
context.drawImage(image);
});
};
Is there a solution to making the canvas responsive? Or do I just need to lock the canvas and image down to predefined sizes?
width and height of image are read-only so that won't work.
Try instead:
context.drawImage(image, 0, 0, canvas.width, canvas.height);
This will draw the image the same dimension as the canvas is (you don't need to reload the image every time btw. - just load it once globally and reuse the image variable.)
<canvas id="imageView" width="1000" height="1000" style="width:100%; height:100%"></canvas>
Both CSS and height and width attributes can be used and do not need to agree in size. The CSS style will determine the displayed size, you asked for a canvas that can stretch. The width and height control the number of pixels the canvas uses for drawing.
for example this will be scaled 10 to 1, and with anti-aliasing scrolling an drawing in this canvas would be as smooth as silk.
<canvas id="imageView" width="1000" height="1000" style="width:100px; height:100px"></canvas>
If CSS is not used, their defaults will be the width and height attributes of the canvas element.
When I first started this project that I'm working on, my canvas size with 1400px wide and 480px tall. I realized that I am going to need to make the canvas the same size as the window itself later, so I did that and everything inside of the canvas zoomed in or something. I set a drawImage(); to be 300 px wide and 180 px tall, and it is a LOT bigger than that, the image is actually the same width as the canvas now. Any suggestions? Here's the link to the project:
http://brycemckenney.com/animation-app
Thank you guys!
You have set the dimensions through css, instead of the physical dimensions of the (image) canvas.
The relevant piece (for others to read in the future) of your code is:
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var windowHeight = $(window).height();
var windowWidth = $(window).width();
$(canvas).css({
height: windowHeight - 8,
width: windowWidth - 8
});
Think of it like this: suppose you have a normal jpg-image.
That jpg has it's own 'physical' dimensions (aka width and height).
In both HTML and CSS you can set the dimensions (in px, percent, etc) that you'd like the browser to render (scale) the picture (hey, the picture already has a immutable size right?).
Now for canvas:
In order for canvas to have a physical width/height, you have to set the .width and .height of the canvas-element itself, either in HTML or per javascript (a side-effect is that setting the physical dimensions is that the canvas will clear itself, as per spec).
Then to scale the image (like you did with the above jpg example) you use css (again in px/percent/etc).
I think this is a clever solution by the way to add that new canvas-element to the HTML-Spec!
So, rounding up:
A canvas with a width and a height of 300 px rendered as 100% of a container (like document.body) that measures 900x900px will be scaled-up 3 times!
The reverse (scaling down) will let you draw even more crisp lines by the way!
Hope this helps your understanding!