问题描述
我有一个像这样的图片我想填充这样的模式使结果像这样。
我可以使用下面的代码填充模式,但我不知道如何正确地沿着领子形状曲线模式,因为它应该看起来像真的,但我的结果变成这样。 。
这里是我的示例脚本
$(function(){
drawCanvas(body,collar,images / collar.png ,180);
function drawCanvas(overlayType,canvasID,imageSource,degreeRotate){
var canvas = document.getElementById(canvasID);
var ctx = canvas.getContext 2d);
var imgBody = new Image();
var imgPattern = new Image();
imgPattern.onload = function(){
imgBody.onload = function(){
start();
}
imgBody.src = imageSource;
}
imgPattern.src = images / pattern.png;
function start(){
ctx.drawImage(imgBody,0,0);
if(overlayType ==body){
ctx.globalCompositeOperation =source-atop;
ctx.globalAlpha = .85;
var pattern = ctx.createPattern(imgPattern,'repeat');
ctx.fillStyle = pattern;
ctx.rect(0,0,canvas.width,canvas.height);
ctx.rotate(degreeRotate * Math.PI / 180);
ctx.fill();
ctx.translate(150,0);
ctx.globalAlpha = .1;
ctx.drawImage(imgBody,150,0);
}
}
}});
有人可以指导我如何管理模式沿着衣领曲线弯曲看起来像真的吗?
您可以通过简单地切割和垂直偏移图案, b 原始领图片: 填充弯曲纹理纹理的领子 **方法:* 这里是代码和一个小提琴: I have one image like this and I want to fill with pattern like this to make result like this . I can fill the pattern using following code but I don't know how to curve pattern properly along the collar shape because it should look like real but my result become like this. . Here is my sample script Can someone guide me to how to manage pattern to curve along side collar shape to look like real? You can get this close by simply slicing and offsetting your pattern vertically Original "collar" image: Collar filled with curved checkered texture **The Method:* Here is code and a Fiddle: http://jsfiddle.net/m1erickson/hdXyk/ 这篇关于如何填充图案在画布和沿形状弯曲?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
$ b
<!doctype html>
< html>
< head>
< link rel =stylesheettype =text / cssmedia =allhref =css / reset.css/> <! - reset css - >
< script type =text / javascriptsrc =http://code.jquery.com/jquery.min.js>< / script>
< style>
body {background-color:ivory; padding:20px; }
canvas {border:1px solid red;}
< / style>
< script>
$(function(){
//获取画布参考(canvas = collar,canvas1 = texture)
var canvas = document.getElementById(canvas);
var ctx = canvas.getContext(2d);
var canvas1 = document.getElementById(canvas1);
var ctx1 = canvas1.getContext(2d);
//在开始之前预加载纹理和衣领图像
var textureImg,collarImg;
var imageURLs = [];
var imagesOK = 0;
var imgs = [];
imageURLs.push(https://dl.dropboxusercontent.com/u/139992952/stackoverflow/checkered.png);
imageURLs.push(https:// dl.dropboxusercontent.com/u/139992952/stackoverflow/collar.png);
loadAllImages();
function loadAllImages(callback){
for(var i = 0 ; i< imageURLs.length; i ++){
var img = new Image();
img.crossOrigin =anonymous;
imgs.push(img);
img.onload = function(){
imagesOK ++;
if(imagesOK == imageURLs.length){
textureImg = imgs [0];
collarImg = imgs [1];
start();
}
};
img.src = imageURLs [i];
}
}
function start(){
//设置两个画布尺寸
canvas.width = collarImg 。宽度;
canvas.height = collarImg.height + 5;
canvas1.width = textureImg.width;
canvas1.height = textureImg.height;
//在canvas1上绘制textureImg
ctx1.drawImage(textureImg,0,0,canvas1.width,canvas1.height);
//将纹理变成一个衣领弯曲的
curveTexture(collarImg.width,collarImg.height);
//在画布上绘制collarImg
ctx.drawImage(collarImg,0,0);
//设置合成到source-atop
//任何新图形将只填充现有的非透明像素
ctx.globalCompositeOperation =source-atop;
//从canvas1中将曲线纹理绘制到画布的衣领上
//(现有的像素是衣领,所以只有衣领被填充)
ctx.drawImage canvas1,0,0);
}
function curveTexture(w,h){
//定义一个二次曲线,如果衣领图像改变(+ 5,-32),这些值会改变
var x0 = 0;
var y0 = h + 5;
var cx = w / 2;
var cy = h-32;
var x1 = w;
var y1 = h + 5;
//获取a,b,c二次方程
//方程用于抵消纹理像素列
//与领口形状相同
var Q = getQuadraticEquation(x0,y0,cx,cy,x1,y1);
//获取纹理画布像素数据
// 2个副本以避免自引用
var imageData0 = ctx1.getImageData(0,0,w,h);
var data0 = imageData0.data;
var imageData1 = ctx1.getImageData(0,0,w,h);
var data1 = imageData1.data;
//通过像素的每个垂直列循环
//将像素列偏移为四元曲线的形状
for(var y = 0; y for(var x = 0; x
//要写入的像素
var n =((w * y)+ x )* 4;
//垂直偏移量
var yy = parseInt(y + h-(Q.a * x * x + Q.b * x + Q.c));
//要读取的偏移像素
var nn =((w * yy)+ x)* 4;
//通过quadCurve Y值(yy)偏移该像素
data0 [n + 0] = data1 [nn + 0]
data0 [n + 1] = data1 [nn + 1];
data0 [n + 2] = data1 [nn + 2];
data0 [n + 3] = data1 [nn + 3];
}
}
ctx1.putImageData(imageData0,0,0);
}
//二次曲线:给定x坐标,找到y坐标
function getQuadraticY(x,Q){
return(Qa * x * x + Qb * x + Qc);
}
//二次曲线:
//给定:开始,控制,结束点
//查找:二次方程中的a,b,c = a * x * x + b * x + c)
function getQuadraticEquation(x0,y0,cx,cy,x2,y2){
//需要在q-它的中点XY
//注意:由于T = 0.5因此TT =(1-T)= 0.5也[可以简化]
var T = 0.50;
var TT = 1-T;
var x1 = TT * TT * x0 + 2 * TT * T * cx + T * T * x2;
var y1 = TT * TT * y0 + 2 * TT * T * cy + T * T * y2;
var A =((y1-y0)*(x0-x2)
+(y2-y0)*(x1-x0))/(x0-x2)*(x1 * x1-x0 * x0)
+(x1-x0)*(x2 * x2-x0 * x0));
var B =((y1-y0)-A *(x1 * x1-x0 * x0))/(x1-x0)
var C = y0-A * x0 * x0-B * x0;
return({a:A,b:B,c:C});
}
}); // end $(function(){});
< / script>
< / head>
< body>
< p>根据Q-curve偏移Y像素,曲线化纹理< / p>
< canvas id =canvaswidth = 300 height = 300>< / canvas>
< p>临时纹理画布< / p>
< canvas id =canvas1width = 300 height = 300>< / canvas>
< / body>
< / html>
$(function(){
drawCanvas("body","collar","images/collar.png", 180);
function drawCanvas(overlayType, canvasID, imageSource, degreeRotate){
var canvas=document.getElementById(canvasID);
var ctx=canvas.getContext("2d");
var imgBody=new Image();
var imgPattern=new Image();
imgPattern.onload=function(){
imgBody.onload=function(){
start();
}
imgBody.src=imageSource;
}
imgPattern.src="images/pattern.png";
function start(){
ctx.drawImage(imgBody,0,0);
if(overlayType=="body"){
ctx.globalCompositeOperation="source-atop";
ctx.globalAlpha=.85;
var pattern = ctx.createPattern(imgPattern, 'repeat');
ctx.fillStyle = pattern;
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.rotate(degreeRotate * Math.PI/180);
ctx.fill();
ctx.translate(150,0);
ctx.globalAlpha=.1;
ctx.drawImage(imgBody,150,0);
}
}
}});
<!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; padding:20px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
// get canvas references (canvas=collar, canvas1=texture)
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");
// preload the texture and collar images before starting
var textureImg,collarImg;
var imageURLs=[];
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/checkered.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/collar.png");
loadAllImages();
function loadAllImages(callback){
for (var i = 0; i < imageURLs.length; i++) {
var img = new Image();
img.crossOrigin="anonymous";
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK==imageURLs.length ) {
textureImg=imgs[0];
collarImg=imgs[1];
start();
}
};
img.src = imageURLs[i];
}
}
function start(){
// set both canvas dimensions
canvas.width=collarImg.width;
canvas.height=collarImg.height+5;
canvas1.width=textureImg.width;
canvas1.height=textureImg.height;
// draw the textureImg on canvas1
ctx1.drawImage(textureImg,0,0,canvas1.width,canvas1.height);
// curve the texture into a collar shaped curved
curveTexture(collarImg.width,collarImg.height);
// draw the collarImg on canvas
ctx.drawImage(collarImg,0,0);
// set compositing to source-atop
// any new drawing will ONLY fill existing non-transparent pixels
ctx.globalCompositeOperation="source-atop";
// draw the curved texture from canvas1 onto the collar of canvas
// (the existing pixels are the collar, so only the collar is filled)
ctx.drawImage(canvas1,0,0);
}
function curveTexture(w,h){
// define a quadratic curve that fits the collar bottom
// These values change if the collar image changes (+5,-32)
var x0=0;
var y0=h+5;
var cx=w/2;
var cy=h-32;
var x1=w;
var y1=h+5;
// get a,b,c for quadratic equation
// equation is used to offset columns of texture pixels
// in the same shape as the collar
var Q=getQuadraticEquation(x0,y0,cx,cy,x1,y1);
// get the texture canvas pixel data
// 2 copies to avoid self-referencing
var imageData0 = ctx1.getImageData(0,0,w,h);
var data0 = imageData0.data;
var imageData1 = ctx1.getImageData(0,0,w,h);
var data1 = imageData1.data;
// loop thru each vertical column of pixels
// Offset the pixel column into the shape of the quad-curve
for(var y=0; y<h; y++) {
for(var x=0; x<w; x++) {
// the pixel to write
var n=((w*y)+x)*4;
// the vertical offset amount
var yy=parseInt(y+h-(Q.a * x*x + Q.b*x + Q.c));
// the offset pixel to read
var nn=((w*yy)+x)*4;
// offset this pixel by the quadCurve Y value (yy)
data0[n+0]=data1[nn+0];
data0[n+1]=data1[nn+1];
data0[n+2]=data1[nn+2];
data0[n+3]=data1[nn+3];
}
}
ctx1.putImageData(imageData0,0,0);
}
// Quadratic Curve: given x coordinate, find y coordinate
function getQuadraticY(x,Q){
return(Q.a * x*x + Q.b*x + Q.c);
}
// Quadratic Curve:
// Given: start,control,end points
// Find: a,b,c in quadratic equation ( y=a*x*x+b*x+c )
function getQuadraticEquation(x0,y0,cx,cy,x2,y2){
// need 1 more point on q-curve, so calc its midpoint XY
// Note: since T=0.5 therefore TT=(1-T)=0.5 also [so could simplify]
var T=0.50;
var TT=1-T;
var x1=TT*TT*x0+2*TT*T*cx+T*T*x2;
var y1=TT*TT*y0+2*TT*T*cy+T*T*y2;
var A = ((y1-y0)*(x0-x2)
+ (y2-y0)*(x1-x0))/((x0-x2)*(x1*x1-x0*x0)
+ (x1-x0)*(x2*x2-x0*x0));
var B = ((y1-y0)-A*(x1*x1-x0*x0))/(x1-x0);
var C = y0-A*x0*x0-B*x0;
return({a:A,b:B,c:C});
}
}); // end $(function(){});
</script>
</head>
<body>
<p>"Curve" a texture by offsetting Y pixels based on Q-curve</p>
<canvas id="canvas" width=300 height=300></canvas>
<p>The temporary texture canvas</p>
<canvas id="canvas1" width=300 height=300></canvas>
</body>
</html>