拉伸图像以适合多边形html5画布

拉伸图像以适合多边形html5画布

本文介绍了拉伸图像以适合多边形html5画布的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的方形图像:

I have a square image like this:

我正在尝试将此图像拉伸成这样的多边形:

I am trying to stretch this image into a polygon like this:

到目前为止,我已经能够使用以下javascript在画布上创建一个多边形,如上图所示:

So far I have been able to create a polygon on the canvas as the above image using the following javascript:

function drawCanvas() {
        var c2 = document.getElementById('myCanvas6').getContext('2d');
        var img = document.getElementById("scream");
        c2.fillStyle = '#000';
        c2.beginPath();
        c2.moveTo(20, 20);
        c2.lineTo(320, 50);
        c2.lineTo(320, 170);
        c2.lineTo(20, 200);
        //c2.drawImage(img, 150, 10, img.width, img.height);
        c2.closePath();
        c2.fill();

    }

我尝试使用 drawImage()方法,但是它不会将点A,B,C,D拉伸到新位置.无论如何,这可以实现吗?

I tried using drawImage() method, but it does not stretch the points A, B, C, D to the new positions. Is there anyway this can be achieved?

推荐答案

2D画布被称为2D是有充分理由的.您不能对正方形进行转换,以使其任何一侧都收敛(不平行),因此为2D

The 2D canvas is called 2D for a very good reason. You can not transform a square such that any of its side converge (are not parallel) hence 2D

但是有需要的地方总有办法.

But where there is a need there is always a way..

您可以通过将图像切成片,然后将每个片画得比上一个小一点来完成.

You can do it by cutting the image into slices and then draw each slice slightly smaller than the last.

我们人类不喜欢看到图像会聚时变形,因此您需要添加我们期望的透视图失真.物体离物体越远,眼睛之间的距离就越小.

We humans don't like to see an image distort when it converges, so you need to add the distortion we expect, perspective. The further away the object the smaller the distance between points appears to the eye.

因此,下面的函数绘制的图像的顶部和底部边缘会聚.

So the function below draws an image with the top and bottom edges converging..

这不是真正的3D,但是它确实使图像看起来像扭曲顶部和底部而不会减小y阶跃一样.动画引入了一些视觉上的错觉.第二个渲染会缩短图像,使图像看起来更不假.

It is not true 3D but it does make the image appear as distorted as jus converging the top and bottom without decreasing the y step. The animation introduced a bit of an optical illusion. the second render shortens the image to make it appear a little less fake.

请参阅有关如何使用该功能的代码.

See the code on how to use the function.

/** CreateImage.js begin **/
// creates a blank image with 2d context
var createImage=function(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}

/** CreateImage.js end **/

var can = createImage(512,512);
document.body.appendChild(can);
var ctx = can.ctx;
const textToDisplay = "Perspective"
const textSize = 80;
ctx.font = textSize+"px arial";
var w = ctx.measureText(textToDisplay).width + 8;
var text = createImage(w + 64,textSize + 32);
text.ctx.fillStyle = "#08F";
text.ctx.strokeStyle = "black";
text.ctx.lineWidth = 16;
text.ctx.fillRect(0,0,text.width,text.height);
text.ctx.strokeRect(0,0,text.width,text.height);
text.ctx.font = textSize+"px arial";
text.ctx.fillStyle = "#F80";
text.ctx.strokeStyle = "Black";
text.ctx.lineWidth = 4;
text.ctx.strokeText(textToDisplay,38,textSize + 8);
text.ctx.fillText(textToDisplay,38,textSize + 8);






// Not quite 3D
// ctx is the context to draw to
// image is the image to draw
// x1,x2 left and right edges of the image
// zz1,zz2 top offset for left and right
// image top edge has a slops from zz1 to zz2
// yy if the position to draw top. This is where the top would be if z = 0
function drawPerspective(ctx, image, x1, zz1, x2, zz2, yy){
    var x, w, h, h2,slop, topLeft, botLeft, zDistR, zDistL, lines, ty;
    w    = image.width;                   // image size
    h    = image.height;
    h2   = h /2;                          // half height
    slop = (zz2 - zz1) / (x2 - x1);       // Slope of top edge
    z1   = h2 - zz1;                      // Distance (z) to first line
    z2   = (z1 / (h2 - zz2)) * z1 - z1;   // distance (z) between first and last line
    if(z2 === 0){ // if no differance in z then is square to camera
        topLeft = - x1 * slop + zz1;      // get scan line top left edge
        ctx.drawImage(image,0, 0, w, h,x1, topLeft + yy ,x2-x1, h - topLeft * 2)  // render to desination
        return;
    }
    // render each display line getting all pixels that will be on that line
    for (x = x1; x < x2; x++) {                 // for each line horizontal line
        topLeft = (x - x1) * slop + zz1;        // get scan line top left edge
        botLeft = ((x + 1) - x1) * slop + zz1;  // get scan line bottom left edge
        zDistL  = (z1 / (h2 - topLeft)) * z1;   // get Z distance to Left of this line
        zDistR  = (z1 / (h2 - botLeft)) * z1;   // get Z distance to right of this line
        ty      = ((zDistL - z1) / z2) * w;     // get y bitmap coord
        lines   = ((zDistR - z1) / z2) * w - ty;// get number of lines to copy
        ctx.drawImage(image,
            ty % w, 0, lines, h,                // get the source location of pixel
            x, topLeft + yy,1 , h - topLeft * 2 // render to desination
        );
    }
}


var animTick = 0;
var animRate = 0.01;
var pos = 0;
var short = 0;
function update1(){
    animTick += animRate;
    pos =  Math.sin(animTick) * 20 + 20;
    short =  Math.cos((pos / 40) * Math.PI) * text.width * 0.12 -  text.width * 0.12;
    ctx.clearRect(0,0,can.width,can.height)

    drawPerspective(ctx,text,0,0,text.width,pos,20)

    drawPerspective(ctx,text,0,0,text.width+short,pos,textSize + 32 + 30)


    requestAnimationFrame(update1);
}
update1();

这篇关于拉伸图像以适合多边形html5画布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 16:16