最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How would I fillRect with an image? - Stack Overflow

programmeradmin4浏览0评论

Normally you can fill a rectangle in a canvas withctx.fillStyle = "whatever color here" and then ctx.fillRect(cords and length and width here). Is there a syntax where I can say ctx.fillRect(someImagePathHere, xOfTopLeft, yofTopLeft)

If not, how else can I achieve this?

Normally you can fill a rectangle in a canvas withctx.fillStyle = "whatever color here" and then ctx.fillRect(cords and length and width here). Is there a syntax where I can say ctx.fillRect(someImagePathHere, xOfTopLeft, yofTopLeft)

If not, how else can I achieve this?

Share Improve this question edited Nov 12, 2018 at 6:16 user128511 asked Aug 9, 2015 at 18:07 OneStigOneStig 9482 gold badges11 silver badges24 bronze badges 3
  • 2 drawImage with appropriate arguments...? – Niet the Dark Absol Commented Aug 9, 2015 at 18:10
  • 1 drawImage : developer.mozilla.org/en-US/docs/Web/API/… – oiledCode Commented Aug 9, 2015 at 18:21
  • Not exactly a duplicate, but possibly helpful: stackoverflow.com/questions/9953844/… – Paul Roub Commented Aug 9, 2015 at 18:24
Add a comment  | 

3 Answers 3

Reset to default 17

The question is ambiguous as there are many ways to "fillRect with an image".

First off images in the browser are downloaded asynchronously so you need to wait for an image to load before you can use it. For canvas situations the most common way to get an image is to create a new Image and set an onload listener

const img = new Image();
img.onload = someFunctionToCallWhenTheImageHasLoaded
img.src = 'http://url/to/image';

Then the question is what do mean by "fillRect"

Using this 256x256 image

For example to draw the image at the size it was downloaded you can use drawImage with 3 arguments

ctx.drawImage(img, x, y);

const img = new Image();
img.onload = draw;
img.src = 'https://i.sstatic.net/CbEMh.png';

function draw() {
  const ctx = document.querySelector('canvas').getContext('2d');
  ctx.drawImage(img, 0, 0);
}
canvas { border: 1px solid black; }
<canvas></canvas>

To draw the image at a different size you can use

ctx.drawImage(img, x, y, width, height);

const img = new Image();
img.onload = draw;
img.src = 'https://i.sstatic.net/CbEMh.png';

function draw() {
  const ctx = document.querySelector('canvas').getContext('2d');
  const destX = 10;
  const destY = 20;
  const destWidth = 30;
  const destHeight = 40;
  ctx.drawImage(img, destX, destY, destWidth, destHeight);
}
canvas { border: 1px solid black; }
<canvas></canvas>

To draw part of the image you can use

// part of image to draw
const srcX = 10;
const srcY = 20;
const srcWidth = 130;
const srcHeight = 140;

// where to draw it
const dstX = 60;
const dstY = 70;
const dstWidth = 160;
const dstHeight = 40;

ctx.drawImage(img, srcX, srcY, srcWidth, srcHeight,
              dstX, dstY, dstWidth, dstHeight);

const img = new Image();
img.onload = draw;
img.src = 'https://i.sstatic.net/CbEMh.png';

function draw() {
  const ctx = document.querySelector('canvas').getContext('2d');
  
  // part of image to draw
  const srcX = 10;
  const srcY = 20;
  const srcWidth = 130;
  const srcHeight = 140;

  // where to draw it
  const dstX = 60;
  const dstY = 70;
  const dstWidth = 160;
  const dstHeight = 40;

  ctx.drawImage(img, srcX, srcY, srcWidth, srcHeight,
                dstX, dstY, dstWidth, dstHeight);
}
canvas { border: 1px solid black; }
<canvas></canvas>

That said, "fillRect" being ambiguous maybe you wanted to use the image as a pattern in which case you need to make a pattern out of it using createPattern

const pattern = ctx.createPatttern(img, 'repeat');

For these let's use this 16x16 pixel image

You can then use the pattern as your fillStyle as in

ctx.fillStyle = pattern;
ctx.fillRect(10, 20, 30, 40);

const img = new Image();
img.onload = draw;
img.src = 'https://i.sstatic.net/HlmSe.png';

function draw() {
  const ctx = document.querySelector('canvas').getContext('2d');
  
  const pattern = ctx.createPattern(img, 'repeat');
  
  ctx.fillStyle = pattern;
  ctx.fillRect(10, 20, 30, 40);
}
canvas { border: 1px solid black; }
<canvas></canvas>

Patterns are relative to the origin of the canvas which means if you just use ctx.fillRect (or any other fill) the pattern will match across fills.

ctx.fillRect(10, 20, 30, 40);
ctx.beginPath();
ctx.arc(50, 60, 25, 0, Math.PI * 2);
ctx.fill();

const img = new Image();
img.onload = draw;
img.src = 'https://i.sstatic.net/HlmSe.png';

function draw() {
  const ctx = document.querySelector('canvas').getContext('2d');
  
  const pattern = ctx.createPattern(img, 'repeat');
  
  ctx.fillStyle = pattern;
  ctx.fillRect(10, 20, 30, 40);
  ctx.beginPath();
  ctx.arc(50, 60, 25, 0, Math.PI * 2);
  ctx.fill();
}
canvas { border: 1px solid black; }
<canvas></canvas>

Because patterns are anchored at the origin if you are animating without changing the origin you'll notice the pattern doesn't move

const img = new Image();
img.onload = start;
img.src = 'https://i.sstatic.net/HlmSe.png';

function start() {
  const ctx = document.querySelector('canvas').getContext('2d');
  
  const pattern = ctx.createPattern(img, 'repeat');

  function render(time) {
    time *= 0.001;  // seconds;
    
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    
    const x = Math.sin(time * 1.1) * 150 + 150;
    const y = Math.sin(time * 1.2) * 50 + 50;
    
    ctx.fillStyle = pattern;
    ctx.fillRect(x, y, 30, 40);
    ctx.beginPath();
    ctx.arc(x, y, 25, 0, Math.PI * 2);
    ctx.fill();
    
    requestAnimationFrame(render);
  }
  requestAnimationFrame(render);
}
canvas { border: 1px solid black; }
<canvas></canvas>

In order to move the pattern you need to move the origin of the canvas using ctx.translate (as well as ctx.rotate, ctx.scale, ctx.setTransform)

const img = new Image();
img.onload = start;
img.src = 'https://i.sstatic.net/HlmSe.png';

function start() {
  const ctx = document.querySelector('canvas').getContext('2d');
  
  const pattern = ctx.createPattern(img, 'repeat');

  function render(time) {
    time *= 0.001;  // seconds;
    
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    
    const x = Math.sin(time * 1.1) * 150 + 150;
    const y = Math.sin(time * 1.2) * 50 + 50;
    
    ctx.translate(x, y);
    
    ctx.fillStyle = pattern;
    ctx.fillRect(0, 0, 30, 40);
    ctx.beginPath();
    ctx.arc(0, 0, 25, 0, Math.PI * 2);
    ctx.fill();
    
    ctx.setTransform(1, 0, 0, 1, 0, 0);  // set it back to the default
    
    requestAnimationFrame(render);
  }
  requestAnimationFrame(render);
}
canvas { border: 1px solid black; }
<canvas></canvas>

Here's an illustration of some of the possibilities:

var im = new Image();
im.src = "https://upload.wikimedia.org/wikipedia/commons/7/79/Face-smile.svg";
im.onload = function () { /* first, wait until the image is loaded */
    /* create five canvases, and draw something in each */
    for (var i=1; i<=5; i++) {
    var canvas = document.createElement("canvas");
    document.body.appendChild(canvas);
    canvas.width = canvas.height = 200;
    var ctx=canvas.getContext("2d");
    var x=50, y=50; /* where to plot */
    var w=20, h=60; /* width and height of rectangle, if applicable */
    switch (i) {
    case 1:
        /* first canvas: draw a rectangle */
        ctx.fillRect(x, y, w, h);
        break;
    case 2:
        /* second canvas: draw an image, actual size, no clipping */
        /* coordinates are where the top left of the image is plotted */
        ctx.drawImage(im, x, y);
        break;
    case 3:
        /* third canvas: draw an image, scaled to rectangle */
        ctx.drawImage(im, x, y, w, h);
        break;
    case 4:
        /* fourth canvas: draw an image, actual size, clipped to rectangle */
        ctx.save();
        ctx.rect(x, y, w, h);
        ctx.clip();
        ctx.drawImage(im, x, y);
        ctx.restore();
        break;
    case 5:
        /* fifth canvas: draw shapes filled with a background image */
        ctx.fillStyle = ctx.createPattern(im, 'repeat'); /* or 'no-repeat', or 'repeat-x', or 'repeat-y' */
        /* note that the image is tiled from the top left of the canvas */
        ctx.fillRect(x, y, w, h);

        /* also draw a circle, why not */
        ctx.beginPath();
        ctx.arc(150, 150, 40, 0, Math.PI*2);
        ctx.fill();
        break;
    }
    }
}
im.onerror = function() { alert("failed to load image"); };

Jsfiddle: http://jsfiddle.net/efeqjjno/

Here is a quick example of how you can use drawImage to draw an image to a canvas. The element on the left is the image, the element on the right is the canvas with the image drawn on it.

JSFiddle: https://jsfiddle.net/gw8ncg7g/

window.onload = function() {
    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    var img = document.getElementById("image");
    ctx.drawImage(img, 0, 0);
}
canvas {
    border:1px solid #d3d3d3;
}
<img id="image" width="300" height="300" src="http://i.imgur.com/LDR6AWn.png?1">
<canvas id="myCanvas" width="300" height="300" >

发布评论

评论列表(0)

  1. 暂无评论