如何在 JavaScript 画布中向透明 PNG 图像添加笔触/轮廓 [英] How to add stroke/outline to transparent PNG image in JavaScript canvas
本文介绍了如何在 JavaScript 画布中向透明 PNG 图像添加笔触/轮廓的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
使用 JavaScript 画布为透明 PNG 图像添加轮廓/描边效果的最简单方法是什么?
最受欢迎的
解决方案
这是一种在图像上添加贴纸效果"的方法...
演示:http://jsfiddle.net/m1erickson/Q2j3L/
首先将原始图像绘制到主画布上.
将图像分解为离散元素".
离散元素由相互连接但不与其他元素连接的像素组组成.例如,精灵表上的每个单独精灵都是一个离散元素.
您可以使用行进方块"等边缘检测算法找到离散像素组.
将每个离散元素放在自己的画布上以供进一步处理.同时从主画布中删除该离散元素(因此不会再次处理).
检测每个离散元素的轮廓路径.
您可以再次使用marching squares"算法进行边缘检测.行进方块的结果是形成元素外部轮廓的 x/y 坐标数组
创建贴纸效果"
您可以通过在每个元素周围放置一个白色的描边轮廓来创建贴纸效果.通过抚摸您在上面计算的轮廓路径来做到这一点.您可以选择为笔画添加阴影.
注意:画布笔触总是画在一半的内侧 &一半在路径之外.这意味着贴纸笔画将侵入元素内部.要解决此问题:在绘制贴纸笔划后,您应该将元素重新绘制回顶部.这会覆盖贴纸笔划的侵入部分.
重新构图包括贴纸效果
通过将每个元素的画布分层到主画布上来重构最终图像
这里是带注释的示例代码:
<头><link rel="stylesheet" type="text/css" media="all" href="css/reset.css"/><!-- 重置 css --><script src="http://code.jquery.com/jquery.min.js"></script><script src="marching squares.js"></script><风格>身体{背景颜色:银色;}画布{边框:1px纯红色;}</风格><脚本>$(函数(){//画布相关变量var canvas=document.getElementById("canvas");var ctx=canvas.getContext("2d");//像素操作中使用的变量var canvases=[];var imageData,data,imageData1,data1;//贴纸轮廓的大小varstrokeWeight=8;//边缘检测方法使用的真/假函数vardefineNonTransparent=function(x,y){返回(数据1[(y*cw+x)*4+3]>0);}//接收贴纸效果的图片var img=new Image();img.crossOrigin="匿名";img.onload=开始;img.src="https://dl.dropboxusercontent.com/u/139992952/multple/makeIndividual.png";//img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/angryBirds.png";函数开始(){//将主画布调整为图像大小canvas.width=cw=img.width;canvas.height=ch=img.height;//在主画布上绘制图像ctx.drawImage(img,0,0);//将每个离散元素从主画布移动到单独的画布//贴纸效果单独应用于每个离散元素和//在单独的画布上为每个离散元素完成while(moveDiscreteElementToNewCanvas()){}//将贴纸效果添加到所有离散元素(每个画布)for(var i=0;i0){hit=true;break;}}如果(!命中){返回;}//获取勾勒出离散元素的点路径var points=geom.contour(defineNonTransparent);//创建一个新画布并将其附加到页面var newCanvas=document.createElement('canvas');newCanvas.width=canvas.width;newCanvas.height=canvas.height;document.body.appendChild(newCanvas);canvases.push(newCanvas);var newCtx=newCanvas.getContext('2d');//将轮廓点附加到新画布(稍后需要)newCanvas.outlinePoints=点;//只将该元素绘制到新画布上定义GeomPath(newCtx,points);newCtx.save();newCtx.clip();newCtx.drawImage(canvas,0,0);newCtx.restore();//从主画布中删除元素定义几何路径(ctx,点);ctx.save();ctx.clip();ctx.globalCompositeOperation="destination-out";ctx.clearRect(0,0,canvas.width,canvas.height);ctx.restore();返回(真);}//实用功能//在画布上定义一条路径,但不抚摸或填充该路径函数defineGeomPath(上下文,点){context.beginPath();context.moveTo(points[0][0],points[0][1]);for(var i=1;i头部><身体><canvas id="canvas" width=300 height=300></canvas><br>