【问题标题】:HTML5 Canvas - Fill circle with imageHTML5 Canvas - 用图像填充圆圈
【发布时间】:2011-05-15 15:10:53
【问题描述】:

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

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

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

【问题讨论】:

    标签: html canvas


    【解决方案1】:

    前几天我这样做是为了做一件大事;

    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();
    };
    

    非常适合我。

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

    【讨论】:

    • 虽然这最终是我在画布中提出的解决方案,但在使用我正在开发的应用程序需要完成的各种内容对其进行高度扩充和修改之后,结果证明在发布之前的 2 天出现了一些问题,并且有 2 天的时间来做一个替代解决方案,结果证明它对于桌面和移动设备来说更快、更跨浏览器。解决方案是@MatTheCat 建议的答案“将 与 CSS 用于边框半径”。刚刚使用 border-radius: 100% 使其成为圆形。迄今为止最好的解决方案。只是说...
    • 只是想补充一点,最好在设置onload 回调之后设置src 。 IE。 thumbImg.src = 'path_to_image'; 成为最后一行
    • True 最好在onload之后设置src。但是,无论如何,当我发布此答案时,我发现它并没有太大的区别,除非您像我一样使用它,并尽快通过它运行数百张图像,以便它们显示而不会显示损坏的图像在画布中绘制一次。再说一次,那时最好也使用延迟,我最终确实这样做了。
    • 能否请你为这个 tmpCtx 添加 jsfiddle 这对我来说是未定义的
    • @PravinWaychal 这是我在发布此答案时所做的一个小提琴。这是我当时需要做的事情的一个版本,这是非常复杂的事情。但你应该明白这一点。 jsfiddle.net/jaredwilli/ex5n5
    【解决方案2】:

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

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

    您也可以使用图案来做到这一点,但图像放置的灵活性会降低

    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"
    

    【讨论】:

      【解决方案3】:

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

      • border-radius 使用带有CSS 的&lt;img&gt;http://jsfiddle.net/ChrisMorgan/BQGxA/

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

      不了解您的要求和情况我不知道这些是否能满足您的要求,但我认为它们值得考虑。 &lt;canvas&gt; 并不能解决您的所有问题 - 对于其中许多情况,普通 HMTL 和/或 SVG 中的 CSS 可能更适合。

      【讨论】:

      • SVG 可能是要走的路。我正在做的是,我有一个视频,当我暂停它时,会弹出一个放大镜。然后使用画布在画布上绘制视频图像并进行缩放。问题是放大镜是圆形的,所以我需要夹住它或用它填充弧线。
      • 在这种情况下,您可能有兴趣查看 6 月的 Tutorialzine 文章 [tutorialzine.com/2010/06/apple-like-retina-effect-jquery-css/… Retina Effect With jQuery)。它涵盖了获得这样的工作效果,尽管使用的是静态图像而不是 &lt;video&gt; 框架。
      • 我实际上最终需要使用 CSS border-radius 作为我在上面发布的答案的替代品脸书应用程序。事实证明,它是我们需要做的最好的解决方案,以使最新版本的 Chrome 18 不会完全破坏应用程序的性能,因为他们在该版本中默认启用了 2D Canvas 硬件加速,但存在错误出于某种原因,这使得绘制大量复杂路径和图像变得极其缓慢。
      【解决方案4】:

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

      一种解决方案是使用 globalCompositeOperation,如 Daniel 的回答所示:

      //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, ...);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-23
        • 2019-01-02
        • 2019-01-24
        • 1970-01-01
        相关资源
        最近更新 更多