根据行的位置(画布)添加文本标签

Good Day Stackoverflowers,

我正在使用画布创建平面图。我有点想在行旁边添加标签。它应该在水平和垂直方向上居中,并放置在线条的外部。

这就是我要实现的目标。

根据行的位置(画布)添加文本标签

该平面图由4条线组成。我希望根据行数为每行创建一个标签。

this.floorplan.getWalls().forEach((wall) => {
    this.drawWall(wall);
});

private drawWall(wall: Wall) {
    var startX = wall.startX();
    var startY = wall.startY();
    var endX = wall.endX();
    var endY = wall.endY();

    this.context.beginPath();
    this.context.moveTo(startX,startY);
    this.context.lineTo(endX,endY);
    this.context.lineWidth = width;
    this.context.strokeStyle = color;
    this.context.stroke();

    // add labels here
    var label = wall.getLabel();
}

希望有人可以照亮。

谢谢。

yubin1006 回答:根据行的位置(画布)添加文本标签

为确保您知道线的哪一侧是外侧还是内侧,必须统一线方向,以便它们始终沿顺时针方向移动。

然后可以很容易地找到线的哪一侧在外面。如果站在行的开头并沿行看,则外部位置在您的左侧。

该示例显示了如何在已转换的(沿线)未转换的文本和沿线的文本(确保其始终向上)上如何在行的左侧呈现文本

将未转换的文本移离行,以使文本中心位于行中心左90度处,并进行移动,以使拐角尽可能靠近。我在线条中心到文本之间添加了一条细线,以显示文本中心与线条对齐的位置。

requestAnimationFrame(mainLoop);
const w = canvas.width;
const h= canvas.height;
const ctx = canvas.getContext("2d");

function drawLabledLine(label,x,y,x1,y1,fontSize = 12) {
    ctx.font = fontSize + "px arial";
    ctx.lineWidth = 1;
    ctx.fillStyle = ctx.strokeStyle = "black";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle"; // Rather than mess around with this
                                 // I use the same alignment and just change the
                                 // position to put the text where it is needed
  
    // normalize line
    var nx = x1 - x;
    var ny = y1 - y;
    const dist = (nx * nx + ny * ny) ** 0.5;
    nx /= dist;
    ny /= dist;
    
    // set the transform
    ctx.setTransform(nx,ny,-ny,nx,y);
    
    // The transformed is now aligned to the line. Along the line is X and 
    // 90 deg clockwise is right of the line
    
    ctx.beginPath();
    ctx.lineTo(0,0);
    ctx.lineTo(dist,0);
    ctx.lineTo(dist - 4,-4);
    ctx.stroke();


    var offset = -fontSize * 0.6;
    var distAlong = dist / 2; /// where to put the line
    
    // Use the normal's of the line to workout how
    // to render the text so it is always readable
    if (nx < 0) {
       ctx.setTransform(-nx,-nx,y);
       offset = -offset;
       distAlong = - distAlong;
    }
    ctx.fillText(label,distAlong,offset);

}


function drawLabledLineTextHor(label,fontSize = 12) {

    ctx.font = fontSize + "px arial";
    ctx.lineWidth = 1;
    ctx.fillStyle = ctx.strokeStyle = "black";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle"; // Rather than mess around with this
                                 // I use the same alignment and just change the
                                 // position to put the text where it is needed
  
    // normalize line
    var nx = x1 - x;
    var ny = y1 - y;
    const dist = (nx * nx + ny * ny) ** 0.5;
    nx /= dist;
    ny /= dist;
    
    // set the transform
    ctx.setTransform(nx,-4);
    ctx.stroke();


    // need the text width so that the text can be moved away from the line
    const textW = ctx.measureText(label).width;
    
    // Offset a little more than half the font size to stop text from
    // touching (top and (bottom if hanging char eg `jgq`))
    var offset = -fontSize * 0.575 - (textW / 2 * -ny) * (-ny < 0 ? -1 : 1);
    var distAlong = dist / 2; // where along the line to move out from (left)
                              // to place the text
    
    // Show center line 
    ctx.lineWidth = 0.25;
    ctx.beginPath();
    ctx.lineTo(dist / 2,5);
    ctx.lineTo(dist / 2,offset + fontSize / 2 );
    ctx.stroke();
    
    
    // set transform origin to center of line
    ctx.setTransform(
        1,// x Axis
        0,1,// y Axis
        x + nx * distAlong,// origin
        y + ny * distAlong,);
    
    // The vector -ny,nx is CW (right of the line) so the offset is negative
    // to that direction as we want to move left of the line
    ctx.fillText(label,-ny * offset,nx * offset);

}

const points = [
    {x: -40,y: -40,tx: 0,ty: 0},// tx,ty is tranformed pos
    {x:  40,{x:  40,y:  40,{x: -40,];
const lines = [
    {txt: "A",p1: points[0],p2: points[1],method: drawLabledLine},{txt: "B",p1: points[1],p2: points[2],method: drawLabledLineTextHor},{txt: "Line C",p1: points[2],p2: points[3],{txt: "Line D",p1: points[3],p2: points[0],]

function mainLoop(time) {
    ctx.setTransform(1,0); // default transform
    ctx.clearRect(0,w,h);
    var ang = time / 1000;

    // rotate and move to center of canvas all points
    const xAx = Math.cos(ang);
    const xAy = Math.sin(ang);
    for (const p of points) {
        p.tx = p.x * xAx - p.y * xAy + w / 2;
        p.ty = p.x * xAy + p.y * xAx + h / 2;
    }
 
    // render the lines
    for(const l of lines) {
        l.method(l.txt,l.p1.tx,l.p1.ty,l.p2.tx,l.p2.ty);
    }
    requestAnimationFrame(mainLoop);
}
<canvas id="canvas" width="200" height="200"></canvas>

本文链接:https://www.f2er.com/3168422.html

大家都在问