欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

html5 canvas+js 实现 ps 笔抠字(快速抠字 www.sukoutu.com)

最编程 2024-05-05 12:07:49
...
1 <script type="text/javascript"> 2 $(function () { 3 var a = new tailorImg(); 4 a.iniData(); 5 }); 6 // 7 var tailorImg=function() 8 { 9 this.iniData = function () { 10 //画布 11 this.can.id = "canvas"; 12 this.can.w = 400; 13 this.can.h = 400; 14 this.can.roundr = 7; 15 this.can.roundrr = 3; 16 this.can.curPointIndex = 0; 17 this.can.imgBack.src = "gzf.png"; 18 this.can.canvas = document.getElementById(this.can.id).getContext("2d"); 19 //图片 20 this.img.w = 400; 21 this.img.h = 400; 22 this.img.image.src = "flower.jpg"; 23 //加载事件: 24 //初始化事件: 25 var a = this; 26 var p = a.can.pointList; 27 $("#" + a.can.id).mousemove(function (e) { 28 if (a.can.paint) {//是不是按下了鼠标 29 if (p.length > 0) { 30 a.equalStartPoint(p[p.length - 1].pointx, p[p.length - 1].pointy); 31 } 32 a.roundIn(e.offsetX, e.offsetY); 33 } 34 //判断是否在直线上 35 //光标移动到线的附近如果是闭合的需要重新划线,并画上新添加的点 36 a.AddNewNode(e.offsetX, e.offsetY); 37 }); 38 $("#" + a.can.id).mousedown(function (e) { 39 a.can.paint = true; 40 //点击判断是否需要在线上插入新的节点: 41 if (a.can.tempPointList.length > 0) { 42 a.can.pointList.splice(a.can.tempPointList[1].pointx, 0, new a.point(a.can.tempPointList[0].pointx, a.can.tempPointList[0].pointy)); 43 //清空临时数组 44 a.can.tempPointList.length = 0; 45 } 46 }); 47 $("#" + a.can.id).mouseup(function (e) { 48 //拖动结束 49 a.can.paint = false; 50 //拖动结束; 51 if (a.can.juPull) { 52 a.can.juPull = false; 53 a.can.curPointIndex = 0; 54 //验证抠图是否闭合:闭合,让结束点=开始点;添加标记 55 a.equalStartPoint(p[p.length - 1].pointx, p[p.length - 1].pointy); 56 //判断是否闭合: 57 if (a.can.IsClose) { 58 59 } 60 } 61 else { 62 //如果闭合:禁止添加新的点; 63 if (!a.can.IsClose) {//没有闭合 64 p.push(new a.point(e.offsetX, e.offsetY)); 65 //验证抠图是否闭合:闭合,让结束点=开始点;添加标记 66 a.equalStartPoint(p[p.length - 1].pointx, p[p.length - 1].pointy); 67 //判断是否闭合: 68 //重新画; 69 if (p.length > 1) { 70 a.drawLine(p[p.length - 2].pointx, p[p.length - 2].pointy, p[p.length - 1].pointx, p[p.length - 1].pointy); 71 a.drawArc(p[p.length - 1].pointx, p[p.length - 1].pointy); 72 } else { 73 a.drawArc(p[p.length - 1].pointx, p[p.length - 1].pointy); 74 } 75 } 76 else { 77 //闭合 78 } 79 } 80 //验证是否填充背景: 81 if (a.can.IsClose) { 82 a.fillBackColor(); 83 a.drawAllLine(); 84 } 85 }); 86 $("#" + a.can.id).mouseleave(function (e) { 87 a.can.paint = false; 88 }); 89 //鼠标点击事件: 90 $("#" + a.can.id).click(function (e) { 91 // 92 }); 93 } 94 this.point = function (x, y) { 95 this.pointx = x; 96 this.pointy = y; 97 }; 98 //图片 99 this.img = { 100 image:new Image(), 101 id: "", 102 w:0, 103 h:0 104 }; 105 //画布; 106 this.can = { 107 canvas:new Object(), 108 id: "", 109 w: 0, 110 h: 0, 111 //坐标点集合 112 pointList: new Array(), 113 //临时存储坐标点 114 tempPointList: new Array(), 115 //圆点的触发半径: 116 roundr: 7, 117 //圆点的显示半径: 118 roundrr: 7, 119 //当前拖动点的索引值; 120 curPointIndex : 0, 121 //判断是否点击拖动 122 paint : false, 123 //判断是否点圆点拖动,并瞬间离开,是否拖动点; 124 juPull : false, 125 //判断是否闭合 126 IsClose: false, 127 imgBack: new Image() 128 129 }; 130 //函数: 131 //更新画线 132 this.drawAllLine=function () { 133 for (var i = 0; i < this.can.pointList.length - 1; i++) { 134 //画线 135 var p = this.can.pointList; 136 this.drawLine(p[i].pointx, p[i].pointy, p[i + 1].pointx, p[i + 1].pointy); 137 //画圈 138 this.drawArc(p[i].pointx, p[i].pointy); 139 if (i == this.can.pointList.length - 2) { 140 this.drawArc(p[i+1].pointx, p[i+1].pointy); 141 } 142 } 143 } 144 //画线 145 this.drawLine = function (startX, startY, endX, endY) { 146 //var grd = this.can.canvas.createLinearGradient(0, 0,2,0); //坐标,长宽 147 //grd.addColorStop(0, "black"); //起点颜色 148 //grd.addColorStop(1, "white"); 149 //this.can.canvas.strokeStyle = grd; 150 this.can.canvas.strokeStyle = "blue" 151 this.can.canvas.lineWidth =1; 152 this.can.canvas.moveTo(startX, startY); 153 this.can.canvas.lineTo(endX, endY); 154 this.can.canvas.stroke(); 155 } 156 //画圈: 157 this.drawArc=function(x, y) { 158 this.can.canvas.fillStyle = "blue"; 159 this.can.canvas.beginPath(); 160 this.can.canvas.arc(x, y,this.can.roundrr, 360, Math.PI * 2, true); 161 this.can.canvas.closePath(); 162 this.can.canvas.fill(); 163 } 164 //光标移到线上画大圈: 165 this.drawArcBig = function (x, y) { 166 this.can.canvas.fillStyle = "blue"; 167 this.can.canvas.beginPath(); 168 this.can.canvas.arc(x, y, this.can.roundr+2, 360, Math.PI * 2, true); 169 this.can.canvas.closePath(); 170 this.can.canvas.fill(); 171 } 172 //渲染图片往画布上 173 this.showImg=function() { 174 this.img.image.onload = function () { 175 this.can.canvas.drawImage(this.img.image, 0, 0, this.img.w,this.img.h); 176 }; 177 } 178 //填充背景色 179 this.fillBackColor = function () { 180 for (var i = 0; i <this.img.w; i += 96) { 181 for (var j = 0; j <= this.img.h; j += 96) { 182 this.can.canvas.drawImage(this.can.imgBack, i, j, 96, 96); 183 } 184 } 185 this.can.canvas.globalCompositeOperation = "destination-out"; 186 this.can.canvas.beginPath(); 187 for (var i = 0; i <this.can.pointList.length; i++) { 188 this.can.canvas.lineTo(this.can.pointList[i].pointx,this.can.pointList[i].pointy); 189 } 190 this.can.canvas.closePath(); 191 this.can.canvas.fill(); 192 this.can.canvas.globalCompositeOperation = "destination-over"; 193 this.drawAllLine(); 194 } 195 //去掉pointlist最后一个坐标点: 196 this.clearLastPoint=function () { 197 this.can.pointList.pop(); 198 //重画: 199 this.clearCan(); 200 this.drawAllLine(); 201 } 202 //判断结束点是否与起始点重合; 203 this.equalStartPoint = function (x,y) { 204 var p = this.can.pointList; 205 if (p.length > 1 && Math.abs((x - p[0].pointx) * (x - p[0].pointx)) + Math.abs((y - p[0].pointy) * (y - p[0].pointy)) <= this.can.roundr * this.can.roundr) { 206 //如果闭合 207 this.can.IsClose = true; 208 p[p.length - 1].pointx = p[0].pointx; 209 p[p.length - 1].pointy = p[0].pointy; 210 } 211 else { 212 this.can.IsClose = false; 213 } 214 } 215 //清空画布 216 this.clearCan=function (){ 217 this.can.canvas.clearRect(0, 0, this.can.w, this.can.h); 218 } 219 //剪切区域 220 this.CreateClipArea=function () { 221 this.showImg(); 222 this.can.canvas.beginPath(); 223 for (var i = 0; i <this.can.pointList.length; i++) { 224 this.can.canvas.lineTo(this.can.pointList[i].pointx,this.can.pointList[i].pointy); 225 } 226 this.can.canvas.closePath(); 227 this.can.canvas.clip(); 228 } 229 // 230 this.CreateClipImg=function() 231 { 232 233 } 234 //判断鼠标点是不是在圆的内部: 235 this.roundIn = function (x, y) { 236 //刚开始拖动 237 var p = this.can.pointList; 238 if (!this.can.juPull) { 239 for (var i = 0; i < p.length; i++) { 240 241 if (Math.abs((x - p[i].pointx) * (x - p[i].pointx)) + Math.abs((y - p[i].pointy) * (y - p[i].pointy)) <= this.can.roundr * this.can.roundr) { 242 //说明点击圆点拖动了; 243 this.can.juPull = true;//拖动 244 // 245 this.can.curPointIndex = i; 246 p[i].pointx = x; 247 p[i].pointy = y; 248 //重画: 249 this.clearCan(); 250 //showImg(); 251 if (this.can.IsClose) { 252 this.fillBackColor(); 253 } 254 this.drawAllLine(); 255 return; 256 } 257 } 258 } 259 else {//拖动中 260 p[this.can.curPointIndex].pointx = x; 261 p[this.can.curPointIndex].pointy = y; 262 //重画: 263 this.clearCan(); 264 if (this.can.IsClose) { 265 this.fillBackColor(); 266 } 267 this.drawAllLine(); 268 } 269 }; 270 271 //光标移到线上,临时数组添加新的节点: 272 this.AddNewNode=function(newx, newy) { 273 //如果闭合 274 var ii=0; 275 if (this.can.IsClose) { 276 //判断光标点是否在线上: 277 var p = this.can.pointList; 278 for (var i = 0; i < p.length - 1; i++) { 279 //计算a点和b点的斜率 280 var k = (p[i + 1].pointy - p[i].pointy) / (p[i + 1].pointx - p[i].pointx); 281 var b = p[i].pointy - k * p[i].pointx; 282 //if (parseInt((p[i + 1].pointy - p[i].pointy) / (p[i + 1].pointx - p[i].pointx)) ==parseInt((p[i + 1].pointy - newy) / (p[i + 1].pointx - newx)) && newx*2-p[i+1].pointx-p[i].pointx<0 && newy*2-p[i+1].pointy-p[i].pointy<0) { 283 // //如果在直线上 284 // alert("在直线上"); 285 //} 286 $("#txtone").val(parseInt(k * newx + b)); 287 $("#txttwo").val(parseInt(newy)); 288 if (parseInt(k * newx + b) == parseInt(newy) && (newx - p[i + 1].pointx) * (newx - p[i].pointx) <= 2 && (newy - p[i + 1].pointy) * (newy - p[i].pointy) <= 2) { 289 // 290 //parseInt(k * newx + b) == parseInt(newy) 291 //添加临时点: 292 this.can.tempPointList[0] = new this.point(newx, newy);//新的坐标点 293 this.can.tempPointList[1] = new this.point(i+1, i+1);//需要往pointlist中插入新点的索引; 294 i++; 295 //alert(); 296 //光标移动到线的附近如果是闭合的需要重新划线,并画上新添加的点; 297 if (this.can.tempPointList.length > 0) { 298 //重画: 299 this.clearCan(); 300 //showImg(); 301 if (this.can.IsClose) { 302 this.fillBackColor(); 303 } 304 this.drawAllLine(); 305 this.drawArcBig(this.can.tempPointList[0].pointx, this.can.tempPointList[0].pointy); 306 return; 307 } 308 return; 309 } 310 else { 311 // $("#Text1").val(""); 312 } 313 } 314 if (ii == 0) { 315 if (this.can.tempPointList.length > 0) { 316 //清空临时数组; 317 this.can.tempPointList.length = 0; 318 //重画: 319 this.clearCan(); 320 //showImg(); 321 if (this.can.IsClose) { 322 this.fillBackColor(); 323 } 324 this.drawAllLine(); 325 //this.drawArc(this.can.tempPointList[0].pointx, this.can.tempPointList[0].pointy); 326 } 327 } 328 } 329 else { 330 //防止计算误差引起的添加点,当闭合后,瞬间移动起始点,可能会插入一个点到临时数组,当再次执行时, 331 //就会在非闭合情况下插入该点,所以,时刻监视: 332 if (this.can.tempPointList.length > 0) { 333 this.can.tempPointList.length = 0; 334 } 335 } 336 } 337 338 }; 339 340 </script>