一个可重用的函数,使用 html5 canvas 将图像剪辑成多边形

2023-12-04

猜测帖子的标题可能需要编辑,但目前我不知道问题出在哪里。我在这里和其他地方阅读了类似问题的页面和答案。 Stack Overflow 的一个答案特别接近,但我不明白。

我想要一个函数,在画布上所需的坐标处绘制多边形,并用从文件加载的一些背景图像填充它们(足够大,不需要平铺)。三角形适合测试。显然我应该使用drawImage和clip,并且为了给多边形一个边框,我可以为clip和描边重新使用相同的路径。显然我也应该保持顺序

- define path
- save
- clip
- drawImage
- restore
- stroke.

另请参阅某处,加载图像一次就足够了。 (如果你想让我引用所有这些假设的来源,我会寻找我在哪里看到它们。大多数都在 Stack Overflow 上)

HTML 是空的

<body onload = "main ();"></body>

第一种方法,假装浏览器将等待图片加载:

var ctx, img;
var image_path = 'bg.jpg';

function main () {

    var CANVAS_SIZE = 600;
    var view_field_cnv = document.createElement ('canvas');
    view_field_cnv.width  = CANVAS_SIZE;
    view_field_cnv.height = CANVAS_SIZE;
    view_field_cnv.style.border = "1px solid";
    document.body.appendChild (view_field_cnv);
    ctx = view_field_cnv.getContext ('2d');

    img = document.createElement ('img');
    img.src = image_path;

    place_triangle (0, 0);
    place_triangle (300, 300);
    place_triangle (500, 500);
    place_triangle (0, 0);

}

function place_triangle (x, y) {

    console.log (x, y);

    ctx.beginPath ();
    ctx.moveTo (x + 10, y);
    ctx.lineTo (x + 110, y);
    ctx.lineTo (x + 60, y + 40);
    ctx.closePath ();

    img = document.createElement ('img');
    img.src = image_path;

    ctx.save ();
    ctx.clip ();
    ctx.drawImage (img, x, y);
    ctx.restore ();
    ctx.stroke ();


}

这会绘制所有三个三角形,但不会剪切图像。

第二次尝试,在 image.onload 中使用drawImage:

var ctx;
var image_path = 'bg.jpg';

function main () {

    var CANVAS_SIZE = 600;
    var view_field_cnv = document.createElement ('canvas');
    view_field_cnv.width  = CANVAS_SIZE;
    view_field_cnv.height = CANVAS_SIZE;
    view_field_cnv.style.border = "1px solid";
    document.body.appendChild (view_field_cnv);
    ctx = view_field_cnv.getContext ('2d');

    place_triangle (0, 0);
    place_triangle (300, 300);
    place_triangle (500, 500);
    place_triangle (0, 0);

}

function place_triangle (x, y) {

    console.log (x, y);

    var img;

    ctx.beginPath ();
    ctx.moveTo (x + 10, y);
    ctx.lineTo (x + 110, y);
    ctx.lineTo (x + 60, y + 40);
    ctx.closePath ();

    img = document.createElement ('img');
    img.src = image_path;
    img.onload = function () {

        ctx.save ();
        ctx.clip ();
        ctx.drawImage (img, x, y);
        ctx.restore ();
        ctx.stroke ();
    }

}

这个确实绘制了剪切图像,但只有一个三角形,即最后一个。仅注释掉保存和恢复没有帮助。

所以,我不明白加载图像、保存、恢复以及可能一百万个其他事情。哪里有 bug?


我发现您已经了解了剪辑的基础知识:

  • 保存上下文,定义路径,剪辑,绘制图像,恢复上下文。

  • 如果您希望笔划稍微与剪切的图像重叠,则可以在恢复后进行笔划。

  • 如果您不希望描边与剪切的图像重叠,可以在剪切之前进行描边。

enter image description here

这是示例代码和演示:http://jsfiddle.net/m1erickson/p0fup425/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

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

    // image loader
    // put the paths to your images in imageURLs[]
    var imageURLs=[];  
    // push all your image urls!
    imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/norwayFlag.jpg");
    imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/swedishFlag.jpg");

    // the loaded images will be placed in images[]
    var imgs=[];

    var imagesOK=0;
    loadAllImages(start);

    function loadAllImages(callback){
        for (var i=0; i<imageURLs.length; i++) {
            var img = new Image();
            imgs.push(img);
            img.onload = function(){ 
                imagesOK++; 
                if (imagesOK>=imageURLs.length ) {
                    callback();
                }
            };
            img.onerror=function(){alert("image load failed");} 
            img.crossOrigin="anonymous";
            img.src = imageURLs[i];
        }      
    }

    function start(){

        // the imgs[] array now holds fully loaded images
        // the imgs[] are in the same order as imageURLs[]

        // clip image#1
        clippingPath([10,70,50,10,90,70],imgs[0],10,10);

        // clip image#2
        clippingPath([10,170,50,110,90,170],imgs[1],10,110);

        // append the original images for demo purposes
        document.body.appendChild(imgs[0]);
        document.body.appendChild(imgs[1]);

    }

    function clippingPath(pathPoints,img,x,y){

        // save the unclipped context
        ctx.save();

        // define the path that will be clipped to
        ctx.beginPath();
        ctx.moveTo(pathPoints[0],pathPoints[1]);
        // this demo has a known number of polygon points
        // but include a loop of "lineTo's" if you have a variable number of points
        ctx.lineTo(pathPoints[2],pathPoints[3]);
        ctx.lineTo(pathPoints[4],pathPoints[5]);
        ctx.closePath();    

        // stroke the path
        // half of the stroke is outside the path
        // the outside part of the stroke will survive the clipping that follows
        ctx.lineWidth=2;
        ctx.stroke();

        // make the current path a clipping path
        ctx.clip();

        // draw the image which will be clipped except in the clipping path
        ctx.drawImage(img,x,y);

        // restore the unclipped context (==undo the clipping path)
        ctx.restore();
    }


}); // end $(function(){});
</script>
</head>
<body>
    <p>Images clipped inside triangular canvas paths</p>
    <canvas id="canvas" width=150 height=200></canvas>
    <p>Original Images</p>
</body>
</html>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一个可重用的函数,使用 html5 canvas 将图像剪辑成多边形 的相关文章

随机推荐

  • 如何使用查询生成器在 Symfony 4 中连接外部 ID 上的多个实体?

    我正在努力学习 Symfony 今天我正在关注关联教程 我决定制作一个小应用程序 包括房屋 厨房 卧室和橱柜 我 尝试 使用draw io制作一个小的类图 以便为您提供更好的想法 所以基本上一栋房子可以有多个卧室和多个厨房 每个厨房可以有多
  • Javascript - 为什么从函数返回 array.push(x) 不会将元素 x 推入数组?

    我想知道为什么以下功能有效 function foo list var array array push list return array gt foo 1 2 3 1 2 3 而这个则没有 function foo list var a
  • Python 和 .Net 集成选项

    我想将 Python 与 C 集成 我发现两种方法使用进程间通信和 IronPython 进程间通信需要在所有客户端计算机上安装 Python exe 因此这不是一个可行的解决方案 我们开始使用 IronPython 但它目前仅支持 2 7
  • PHP 类 - 如何仅连接一次数据库

    我尝试做一个简单的 SQL 类 只有一个问题 function classDBREAD table where value back link mysql connect 127 0 0 1 XXXX XXXXXX mysql select
  • 如何忽略 LNK2005 和 LNK1169?

    因此 我有一个使用外部库的 Visual Studio 2010 项目 为了在没有 LNK2005 的情况下编译它 我必须在链接器设置中调整库的顺序 我让它在发布模式下编译得很好 但出于某种原因 我无法在调试中没有 LNK 错误的情况下编译
  • 如何在单击按钮时从数据库将新行添加到 jTable 中而不清除现有行

    如何在单击按钮时从数据库将新行添加到 jTable 中而不清除 jTable 中的现有行 我尝试了很多方法 但没有成功 帮助 String SQL SELECT name price FROM items WHERE ID jTextFie
  • Paypal使用phpcurl通过支付密钥获取交易详细信息

    android paypal 付款成功后我得到回复 回应如下 response state approved id PAY 6PU626847B294842SKPEWXHY create time 2014 07 18T18 46 55Z
  • 如何在我的 Activity 中重新启动 Fragment - Android

    我有一个活动 里面有 3 个片段 我需要通过单击按钮重新启动活动中的第一个片段 ViewPagerAdapter adapter new ViewPagerAdapter getSupportFragmentManager adapter
  • 自 iOS 8 起,SignificantLocationChanges 不再起作用

    我有一个问题SignificantLocationChanges自iOS 8发布以来 该方法 locationManager startMonitoringSignificantLocationChanges 在检查可用性后被正确调用 代表
  • 读取由 NewCookie() 创建的 cookie

    I created a cookie using Newcookie and I can access it thorough the browser as below Now I need to read the cookie funct
  • 带有圆角的 UIButton 的活动可点击区域?

    So I have created a button with a border in my storyboard 然后我把它的角弄圆并添加了边框颜色 button layer cornerRadius button bounds size
  • Unified_thread 还没有对外开放?

    据 Facebook 称 他们很久以前就发布了新的消息系统 http developers facebook com blog post 591 来自博客 应用程序应迁移到新的消息传递图形 API 端点和消息传递 FQL 表 unified
  • 为什么 eval('{a:23}') 给我的是 23 而不是 {a:23}?

    我在浏览器中有这段 JavaScript 代码 console log eval a 23 它打印 23 我原本期待看到 Object 有人可以解释一下吗 thanks 在这种背景下 开始一个block 不是对象字面量 a 那么是一个lab
  • .* 匹配 2 次

    我尝试过了match 用C 正则表达式 结果发现它匹配任何字符串两次 first the 完整的字符串 比第二次空字符串 我期望 在一场比赛中匹配所有内容 我完全困惑为什么会这样以及如何防止这种情况 长话短说 我需要替换部分文件名 并且可以
  • 如何在 C++ 中创建文件映射?

    我正在编写一个游戏预加载器 一个简单的程序 在启动程序之前将某些文件 映射 加载到缓存中 我被告知要使用CreateFileMapping 但我仍然不确定它将它加载到物理内存还是虚拟内存中 不管怎样 我应该把需要加载的文件放在哪里 这是我的
  • Jersey 和 HK2 - 注入当前用户

    我正在使用 jersey 2 17 和 HK2 创建一个简单的休息应用程序 我有一个ContainerRequestFilter拒绝任何没有 currentuser cookie 的请求 我有这样的事情 Path users public
  • 远程运行 python 脚本的更好方法

    我在远程计算机上有一个 python 脚本 我想从本地计算机执行该脚本 它接受一些参数 如果我要在那台机器上运行它 这就是我运行它的方式 python python parallel py num 10 ssh home user1 pat
  • Javascript生成具有特定字母数量的随机密码[关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我想在客户端的网页中用 JavaScript 生成密码 密码应使用字母和数字 也许还有一些符号 如何在 Javascript 中安全地生成密码 由于密码需要是不可预测的 因此它需要由
  • 使用 CSS 而不是 jquery 将图像置于 div 中居中

    我试图将任何大小的图像放入 始终 方形 div 中 并在父 div 的大小发生变化时保留外观 这就是我正在做的 CSS photo container width 250px height 250px overflow hidden bor
  • 一个可重用的函数,使用 html5 canvas 将图像剪辑成多边形

    猜测帖子的标题可能需要编辑 但目前我不知道问题出在哪里 我在这里和其他地方阅读了类似问题的页面和答案 Stack Overflow 的一个答案特别接近 但我不明白 我想要一个函数 在画布上所需的坐标处绘制多边形 并用从文件加载的一些背景图像