Html HTML5 Canvas - 用图像填充圆圈

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4276048/
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-08-29 05:27:20  来源:igfitidea点击:

HTML5 Canvas - Fill circle with image

htmlcanvas

提问by tbleckert

How can I draw an image inside a circle? If I do:

如何在圆圈内绘制图像?如果我做:

context.beginPath();
context.arc((e.pageX),(e.pageY),161,0,Math.PI*2,true);
context.closePath();

How can I then use fill() to fill it with my drawn image?

然后我如何使用 fill() 用我绘制的图像填充它?

回答by jaredwilli

I did this the other day for a big thing I'm making;

前几天我为我正在做的一件大事做了这个;

var thumbImg = document.createElement('img');

thumbImg.src = 'path_to_image';
thumbImg.onload = function() {
    tmpCtx.save();
    tmpCtx.beginPath();
    tmpCtx.arc(25, 25, 25, 0, Math.PI * 2, true);
    tmpCtx.closePath();
    tmpCtx.clip();

    tmpCtx.drawImage(thumbImg, 0, 0, 50, 50);

    tmpCtx.beginPath();
    tmpCtx.arc(0, 0, 25, 0, Math.PI * 2, true);
    tmpCtx.clip();
    tmpCtx.closePath();
    tmpCtx.restore();
};

Worked perfect for me.

非常适合我。

Here's a more complex version of it that I made which does image caching too, https://jsfiddle.net/jaredwilli/ex5n5/

这是我制作的一个更复杂的版本,它也进行图像缓存,https://jsfiddle.net/jaredwilli/ex5n5/

回答by moby

Not sure if you are still looking for the answer, but here's how:

不确定您是否仍在寻找答案,但方法如下:

var ctx = document.getElementById('your_canvas').getContext("2d");
//ctx.lineWidth = 13; 
//ctx.strokeStyle = 'rgba(0,0,0,1)'; 
//ctx.fillStyle="rgba(0,0,0,0)" // if using this, make sure alpha < 1

ctx.arc(100,100, 50, 0, Math.PI*2,true); // you can use any shape
ctx.clip();

var img = new Image();
img.addEventListener('load', function(e) {
    ctx.drawImage(this, 0, 0, 200, 300);
    //ctx.fill();
//ctx.stroke();
}, true);
img.src="/path/to/image.jpg";

You can also do this with pattern, but you get less image placement flexibility

您也可以使用图案来执行此操作,但图像放置的灵活性会降低

ctx.arc(100,100, 70, 0, Math.PI*2,true);
ctx.clip();

img = new Image()
img.addEventListener('load', function(e) {
    ctx.fillStyle = ctx.createPattern(this, 'no-repeat') 
    ctx.fill();
}, true);
img.src="/path/to/image.jpg"

回答by Chris Morgan

Consider using some of these alternatives:

考虑使用其中一些替代方案:

  • Using an <img>with CSS for border-radius: http://jsfiddle.net/ChrisMorgan/BQGxA/

  • Use SVG rather than <canvas>and set the ellipse as the clipping path for an image. (More complex clipping paths are then easy, too)

  • 使用<img>CSS 用于border-radiushttp: //jsfiddle.net/ChrisMorgan/BQGxA/

  • 使用 SVG 而不是<canvas>并将椭圆设置为图像的剪切路径。(更复杂的剪切路径也很容易)

Not knowing more about your requirements and situation I don't know if these will satisfy your requirements, but I think they're worth while considering. <canvas>isn't the solution to all your problems - for many of these cases, CSS in normal HMTL and/or SVG may be a better match.

不知道更多关于您的要求和情况我不知道这些是否会满足您的要求,但我认为它们值得考虑。<canvas>不是所有问题的解决方案 - 对于许多这些情况,普通 HMTL 和/或 SVG 中的 CSS 可能更匹配。

回答by Jesús Carrera

The problem with the clip() method is that Chrome will render the borders non antialiased, as shown in this question.

clip() 方法的问题在于 Chrome 会将边框呈现为非抗锯齿,如本问题所示。

One solution is to use globalCompositeOperation as shown in Daniel's answer:

一种解决方案是使用 globalCompositeOperation 如丹尼尔的回答所示:

//set-up - probably only needs to be done once
var scratchCanvas = document.createElement('canvas');
scratchCanvas.width = 100;
scratchCanvas.height = 100;
var scratchCtx = scratchCanvas.getContext('2d');


//drawing code
scratchCtx.clearRect(0, 0, scratchCanvas.width, scratchCanvas.height);

scratchCtx.globalCompositeOperation = 'source-over'; //default

//Do whatever drawing you want. In your case, draw your image.
scratchCtx.drawImage(imageToCrop, ...);


//As long as we can represent our clipping region as a single path, 
//we can perform our clipping by using a non-default composite operation.
//You can think of destination-in as "write alpha". It will not touch
//the color channel of the canvas, but will replace the alpha channel.
//(Actually, it will multiply the already drawn alpha with the alpha
//currently being drawn - meaning that things look good where two anti-
//aliased pixels overlap.)
//
//If you can't represent the clipping region as a single path, you can
//always draw your clip shape into yet another scratch canvas.

scratchCtx.fillStyle = '#fff'; //color doesn't matter, but we want full opacity
scratchCtx.globalCompositeOperation = 'destination-in';
scratchCtx.beginPath();
scratchCtx.arc(50, 50, 50, 0, 2 * Math.PI, true);
scratchCtx.closePath();
scratchCtx.fill();


//Now that we have a nice, cropped image, we can draw it in our
//actual canvas. We can even draw it over top existing pixels, and
//everything will look great!

ctx.drawImage(scratchCanves, ...);