本文介绍了如何填充图案在画布和沿形状弯曲?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的图片我想填充这样的模式使结果像这样。



我可以使用下面的代码填充模式,但我不知道如何正确地沿着领子形状曲线模式,因为它应该看起来像真的,但我的结果变成这样。 。



这里是我的示例脚本

  $(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
$ b

原始领图片:





填充弯曲纹理纹理的领子





**方法:*




  • 创建一个用方格纹理平铺的图像。

  • 将纹理图像绘制到临时画布上。 / li>
  • 获取临时画布的图像数据。

  • 对于每一列像素, >
  • 一个二次曲线适合你的领子的曲线,所以我在示例中使用它来确定Y偏移。

  • 将图像数据放回

  • (您现在有一个弯曲的方格图案可以应用到您的衣领图像)。

  • 在主画布上绘制衣领图像。

  • 设置context.globalCompositeOperation =source-atop

  • 将纹理从临时画布绘制到主画布上。




这里是代码和一个小提琴:

 <!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>


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

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

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:*

  • Create an image tiled with your checkered texture.
  • Draw that texture image onto a temporary canvas.
  • Get the image data for the temporary canvas.
  • For each column of pixels, offset that entire column by the curve of your collar.
  • A quadratic curve fits the curve of your collar well, so I used that in the example to determin the Y offset.
  • Put the image data back on the temporary canvas.
  • (You now have a curved checkered pattern to apply to your collar image).
  • Draw the collar image on your main canvas.
  • Set context.globalCompositeOperation="source-atop"
  • Draw the texture from the temporary canvas onto the main canvas.
  • (The compositing mode will paint the texture only on the collar—not the background)

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/hdXyk/

<!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>

这篇关于如何填充图案在画布和沿形状弯曲?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-18 21:36