150

I'm experimenting a bit with the new canvas element in HTML.

I simply want to add an image to the canvas but it doesn't work for some reason.

I have the following code:

HTML

<canvas id="viewport"></canvas>

CSS

canvas#viewport { border: 1px solid white; width: 900px; }

JS

var canvas = document.getElementById('viewport'),
context = canvas.getContext('2d');

make_base();

function make_base()
{
  base_image = new Image();
  base_image.src = 'img/base.png';
  context.drawImage(base_image, 100, 100);
}

The image exists and I get no JavaScript errors. The image just doesn't display.

It must be something really simple I've missed...

PeeHaa
  • 71,436
  • 58
  • 190
  • 262
  • If you want to load multiple images, I suggest using promises as shown in [Loading images before rendering JS canvas](https://stackoverflow.com/questions/61336830/loading-images-before-rendering-js-canvas/61337279#61337279) – ggorlen Mar 21 '22 at 16:30

5 Answers5

287

You need to wait until the image is loaded before you draw it. Try this instead:

var canvas = document.getElementById('viewport'),
context = canvas.getContext('2d');

make_base();

function make_base()
{
  base_image = new Image();
  base_image.src = 'img/base.png';
  base_image.onload = function(){
    context.drawImage(base_image, 0, 0);
  }
}

i.e. draw the image in the onload callback of the image.

ashleedawg
  • 20,365
  • 9
  • 72
  • 105
Thomas
  • 10,358
  • 4
  • 27
  • 35
  • 8
    @swogger rather thank ask anything, try out. That worked perfectly. Make sure you check first the img size of the source, otherwise will be cropped unless you use full function `context.drawImage(base_image, 0, 0, 200, 200);`. That would draw base_img from 0px position, with draw area of 200x200px. – m3nda Feb 16 '15 at 04:52
  • 1
    This was exactly my case. I was loading some blob data into canvas using `new Image` and wondering why it was always showing me a previous image. Turns out even if I'm loading an image from a variable I still have to wait for the `onload` to happen. Thank you! – ᴍᴇʜᴏᴠ Mar 16 '16 at 22:27
  • How to add image style ? – Sagar Rawal Sep 20 '16 at 12:55
  • If [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) gives you a ***`This operation is insecure`*** error, you could try adding `base_image.crossOrigin = "anonymous";` just after the `new Image()` statement. – ashleedawg Oct 15 '21 at 16:40
10

here is the sample code to draw image on canvas-

$("#selectedImage").change(function(e) {

var URL = window.URL;
var url = URL.createObjectURL(e.target.files[0]);
img.src = url;

img.onload = function() {
    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");        

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(img, 0, 0, 500, 500);
}});

In the above code selectedImage is an input control which can be used to browse image on system. For more details of sample code to draw image on canvas while maintaining the aspect ratio:

http://newapputil.blogspot.in/2016/09/show-image-on-canvas-html5.html

nvivekgoyal
  • 484
  • 9
  • 15
5

You have to use .onload

let canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d"); 

const drawImage = (url) => {
    const image = new Image();
    image.src = url;
    image.onload = () => {
       ctx.drawImage(image, 0, 0)
    }
}

Here's Why

If you are loading the image first after the canvas has already been created then the canvas won't be able to pass all the image data to draw the image. So you need to first load all the data that came with the image and then you can use drawImage()

Anthony Gedeon
  • 354
  • 4
  • 12
2

In my case, I was mistaken the function parameters, which are:

context.drawImage(image, left, top);
context.drawImage(image, left, top, width, height);

If you expect them to be

context.drawImage(image, width, height);

you will place the image just outside the canvas with the same effects as described in the question.

Marc
  • 12,706
  • 7
  • 61
  • 97
2

context.drawImage provide three ways for your choise.

drawImage(image: CanvasImageSource, dx: number, dy: number): void;
drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void; 
  • d: destination
  • s: source

Or you can reference explains from w3school-canvas drawImage.

Carson
  • 6,105
  • 2
  • 37
  • 45