如何在我使用路径绘制的梯形html画布上拟合图像 [英] how to to fit an image on a trapezium html canvas which I drew using path

查看:135
本文介绍了如何在我使用路径绘制的梯形html画布上拟合图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[我想在笔记本电脑屏幕上添加另一张图片.var ctx = myCanvas.getContext('2d');

[I want to add another image over the laptop screen`var ctx = myCanvas.getContext('2d');

                ctx.beginPath();
                ctx.moveTo(13,28);
                ctx.lineTo(237,7);
                ctx.lineTo(285,105);
                ctx.lineTo(73,151);
                ctx.closePath();
                   ctx.lineWidth = 0.5;
            ctx.strokeStyle = 'blue';
                ctx.stroke();
                //ctx.clip();
                //ctx.rotate(-20*Math.PI/180);
                var img = new Image;
                img.onload = function()
                {

                    var width = img.width;
                      var  height = img.height;
                    ctx.drawImage(img, 0, 0, img.width,    img.height,
                           0, 0, myCanvas.width, myCanvas.height);

                    }
                };
                img.src = reader.result; 
               `][1]

如何倾斜图像以适应梯形ctx我已经创建了

how do I skew the image to fit in the trapezium ctx that i have created

推荐答案

为什么2D API是2D



canvas 2D API被称为2D API是有充分理由的。它只能进行2D变换。

Why 2D API is 2D

The canvas 2D API is called a 2D API for a very good reason. It can only do 2D transformations.

你的形状......

The shape you have...

上图为您的形状添加注释。线A,C不平行。

The above image annotates your shape. Lines A,C are not parallel.

画布2D变换不适合矩形到那个形状,因为它没有足够的信息来处理会聚线以及如何在像素收敛时缩放像素。

The canvas 2D transformation can not fit a rectangle to that shape as it does not carry enough information to deal with the converging lines and how to scale the pixels as they converge.

你能做的最好就是近似

下一个图像使用两条线将形状平分。这些线将用于创建最适合使用2D变换的形状的变换。

The next image bisects the shape using two lines. These lines will be used to create the transform that will best fit the shape using the 2D transformation.

我们使用二等分线来定义变换的x和y轴,并使用每个的长度来确定比例。图像的中心点是其中一条二等分线的中心。

We use the bisecting lines to define the x and y axis of the transform and use the length of each to determine the scale. The center point of the image is the center of one of the bisecting lines.

const ctx = canvas.getContext("2d");
const path = [13, 28, 237, 7, 285, 105, 73, 151];
const imageURL = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Sarcoramphus_papa_%28K%C3%B6nigsgeier_-_King_Vulture%29_-_Weltvogelpark_Walsrode_2013-01.jpg/675px-Sarcoramphus_papa_%28K%C3%B6nigsgeier_-_King_Vulture%29_-_Weltvogelpark_Walsrode_2013-01.jpg";
function setStyle(style){
    Object.keys(style).forEach(key => ctx[key] = style[key]);
}
function drawPath(path, style) {
    var i = 0;
    setStyle(style);
    ctx.beginPath();
    ctx.moveTo(path[i++], path[i++]);
    while (i < path.length) {
        ctx.lineTo(path[i++], path[i++]);
    }
    ctx.closePath();
    ctx.stroke();
}
function markPath(path, style, marks) {
    var i = 0;
    var len = path.length;
    setStyle(style);
    while (i < len) {
        ctx.fillText(
            marks[i >> 1],
            (path[i] + path[((i++) + 2) % len]) / 2,
            (path[i] + path[((i++) + 2) % len]) / 2
        );
    }
}
function bisectPath(path, modulo, style) {
    var i = 0;
    var len = path.length;
    setStyle(style);
    ctx.beginPath();
    while (i < len) {
        ctx.moveTo(
            (path[i] + path[((i++) + 2) % len]) / 2,
            (path[i] + path[((i++) + 2) % len]) / 2
        );
        i += modulo;
        ctx.lineTo(
            (path[i] + path[((i++) + 2) % len]) / 2,
            (path[i] + path[((i++) + 2) % len]) / 2
        );
        i -= modulo + 2;
    }
    ctx.stroke();

}

// functions to create lines, get vectors, length and normals
function getLine(x1,y1,x2,y2){
   return {
      p1 : { x : x1 , y : y1 },
      p2 : { x : x2 , y : y2 }
   };
}
function getVec(line){
   line.vec = { 
       x : line.p2.x - line.p1.x,
       y : line.p2.y - line.p1.y
   };
   return line;
}    
function getNormal(line){
   line.len = Math.hypot(line.vec.x, line.vec.y);
   line.norm = { 
       x : line.vec.x / line.len,
       y : line.vec.y / line.len,
   };
   return line;
}    
// create the 2 bisecting lines
var line1 = getNormal( getVec( getLine(
     (path[0] + path[2]) / 2,
     (path[1] + path[3]) / 2,
     (path[4] + path[6]) / 2,
     (path[5] + path[7]) / 2
)));
var line2 = getNormal( getVec( getLine(
     (path[6] + path[0]) / 2,
     (path[7] + path[1]) / 2,
     (path[2] + path[4]) / 2,
     (path[3] + path[5]) / 2
)));

// create an image to fit
var image = new Image;
image.src = imageURL;
image.onload = function(){
    var w, h, sx, sy, cx, cy;
    w = this.width;
    h = this.height;
    // calculate the image scales
    sx = line2.len / w;
    sy = line1.len / h;
    // calculate the center
    cx = (line1.p1.x + line1.p2.x) / 2;
    cy = (line1.p1.y + line1.p2.y) / 2;

    // now we have all the information needed to create the transformation
    ctx.setTransform(
       line2.norm.x * sx,  // scale and direction of x axis
       line2.norm.y * sx,
       line1.norm.x * sy,  // scale and direction of y axis
       line1.norm.y * sy,
       cx, cy,             // the origin coordinate (0,0)
    );
    // Draw the image offset from its center by half its width and heigth
    ctx.drawImage(this, -w / 2, -h / 2);
    // reset the transformation
    ctx.setTransform(1,0,0,1,0,0);

    // draw the guides
    drawPath(path, {
        lineWidth : 0.5,
        strokeStyle : "blue"
    });
    bisectPath(path, 2, {
        lineWidth : 1,
        strokeStyle : "white"
    });
    markPath(path, {
        font : "18px arial",
        textAlign : "center",
        textBaseline : "middle",
        fillStyle : "black"
    }, ["A", "B", "C", "D"]);





}

<canvas id=canvas height=160></canvas>

这是你可以做的最好的canvas 2D API。您可以渲染每个像素来计算3D变换以适合您拥有的形状。取决于可能需要一些时间(CPU)的图像大小,结果将是正常的。

That is the best you can do with the canvas 2D API. You could render each pixel calculating the 3D transform to fit the shape you have. Depending on the image size that can take some time (CPU) to do and the result will be OK.

如果你真的需要3D变换,你应该使用webGL。 SO和网上有很多关于如何做到这一点的例子

If you really need the 3D transform you should use webGL. There are plenty of examples on SO and the web on how to do that

这篇关于如何在我使用路径绘制的梯形html画布上拟合图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆