javascript 我将如何用图像填充矩形?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31907295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 14:33:24  来源:igfitidea点击:

How would I fillRect with an image?

javascriptimagecanvas

提问by OneStig

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)

通常,您可以使用ctx.fillStyle = "whatever color here"和 然后在画布中填充矩形ctx.fillRect(cords and length and width here)。有没有我可以说的语法ctx.fillRect(someImagePathHere, xOfTopLeft, yofTopLeft)

If not, how else can I achieve this?

如果没有,我还能如何实现这一目标?

采纳答案by Maximillian Laumeister

Here is a quick example of how you can use drawImageto 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.

下面是一个快速示例,说明如何drawImage将图像绘制到画布上。左边的元素是图像,右边的元素是画布上绘制的图像。

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

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" >

回答by gman

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 Imageand set an onloadlistener

首先浏览器中的图像是异步下载的,因此您需要等待图像加载才能使用它。对于画布情况,获取图像的最常见方法是创建一个新的Image并设置一个onload侦听器

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

Then the question is what do mean by "fillRect"

那么问题是“fillRect”是什么意思

Using this 256x256 image

使用这个 256x256 的图像

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

例如,要以下载的大小绘制图像,您可以使用drawImage3 个参数

ctx.drawImage(img, x, y);

enter image description here

在此处输入图片说明

const img = new Image();
img.onload = draw;
img.src = 'https://i.imgur.com/ZKMnXce.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);

enter image description here

在此处输入图片说明

const img = new Image();
img.onload = draw;
img.src = 'https://i.imgur.com/ZKMnXce.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);

enter image description here

在此处输入图片说明

const img = new Image();
img.onload = draw;
img.src = 'https://i.imgur.com/ZKMnXce.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

也就是说,“fillRect”是模棱两可的,也许您想将图像用作模式,在这种情况下,您需要使用 createPattern

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

For these let's use this 16x16 pixel image

对于这些让我们使用这个 16x16 像素的图像

You can then use the pattern as your fillStyle as in

然后,您可以使用该模式作为您的 fillStyle

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

enter image description here

在此处输入图片说明

const img = new Image();
img.onload = draw;
img.src = 'https://i.imgur.com/fqgm8uh.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(或任何其他填充)图案将在填充之间匹配。

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

enter image description here

在此处输入图片说明

const img = new Image();
img.onload = draw;
img.src = 'https://i.imgur.com/fqgm8uh.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.imgur.com/fqgm8uh.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)

为了移动图案,您需要使用ctx.translate(以及ctx.rotate, ctx.scale, ctx.setTransform)移动画布的原点

const img = new Image();
img.onload = start;
img.src = 'https://i.imgur.com/fqgm8uh.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>

回答by hexwab

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/

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