javascript - 拉伸(stretch)图像以适应多边形 html5 Canvas

标签 javascript css html canvas

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

enter image description here

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

enter image description here

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

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 拉伸(stretch)到新位置。无论如何,这可以实现吗?

最佳答案

二维 Canvas 被称为二维是有充分理由的。你不能变换一个正方形,使得它的任何边收敛(不平行)因此是 2D

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

您可以将图像切割成切片,然后将每个切片绘制得比上一个略小。

我们人类不喜欢看到图像在收敛时扭曲,因此您需要添加我们期望的扭曲,透视。物体离得越远,在眼睛看来点之间的距离就越小。

所以下面的函数绘制了一个顶部和底部边缘会聚的图像..

这不是真正的 3D,但它确实使图像看起来像在不减少 y 步长的情况下会聚顶部和底部一样扭曲。动画引入了一点视觉错觉。第二个渲染缩短了图像,使其看起来不那么虚假。

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

/** 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();

关于javascript - 拉伸(stretch)图像以适应多边形 html5 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39871739/

相关文章:

javascript - Angular JS 错误状态未显示

javascript - 如何从视频中删除 YouTube Logo ?

javascript - 如何通过在 Javascript 中单击按钮来更新里程表值?

Javascript - 如何使用 bootstrap-datetimepicker 自动计算两个时间输入之间的差异?

javascript - 如何在html5中根据时间在 Canvas 中绘制条形图

jQuery - 选择不在 ID 内的元素

html - 如何将具有 table-cell 显示属性的 html 元素向右推送?

javascript - 在 JavaScript 中使用 CryptoJS 和 AES 加密的 AES 加密的不同输出

android - 仅限手机(iPhone 和 Android)的 css

CSS 选择类后的元素