首页 > 解决方案 > 使用 innerwidth 排版由 p5.js 函数组成的字体

问题描述

我用一组函数制作了一个实验字体。我试图通过在达到浏览器窗口的内部宽度时让字体移动到下一行来排版字体。但由于某种原因,这里的逻辑不起作用,我无法将函数移动到下一行。我认为我使用模运算符所做的条件语句有问题,但我不知道是什么。谢谢!

const letterA = {
    lines: [
        { x1: 35, y1: 170, x2: 50, y2: 136 },
        { x1: 50, y1: 136, x2: 89, y2: 45 },
        { x1: 89, y1: 45, x2: 125, y2: 136 },
        { x1: 125, y1: 136, x2: 140, y2: 170 },
        { x1: 125, y1: 136, x2: 50, y2: 135 }
    ]
}

const letterB = {
    lines: [
        { x1: 35, y1: 170, x2: 35, y2: 102 },
        { x1: 35, y1: 102, x2: 35, y2: 41 },
        { x1: 35, y1: 41, x2: 125, y2: 52 },
        { x1: 109, y1: 103, x2: 35, y2: 103 },
        { x1: 125, y1: 52, x2: 109, y2: 103 },
        { x1: 109, y1: 103, x2: 125, y2: 159 },
        { x1: 125, y1: 159, x2: 35, y2: 170 }
    ]
}

const letterC = {
    lines: [
        { x1: 131, y1: 147, x2: 85, y2: 177 },
        { x1: 85, y1: 177, x2: 30, y2: 111 },
        { x1: 30, y1: 111, x2: 85, y2: 38 },
        { x1: 85, y1: 38, x2: 131, y2: 65 },
    ]
}

const letterD = {
    lines: [
        { x1: 36, y1: 170, x2: 36, y2: 45 },
        { x1: 36, y1: 45, x2: 123, y2: 54 },
        { x1: 123, y1: 54, x2: 138, y2: 111 },
        { x1: 138, y1: 111, x2: 113, y2: 162 },
        { x1: 113, y1: 162, x2: 36, y2: 170 }
    ]
}

const allLetters = {
    A: letterA,
    B: letterB,
    C: letterC,
    D: letterD
}



function setup() {
    createCanvas(windowWidth, 1080);
}

function draw() {

    background(255)
    strokeWeight(20);
    frameRate(3)

    const text = 'goodbye';
    const letterWidth = 170;
    const windowWidth = window.innerWidth;
    let currentLine = 0;

    for (let i = 0; i < text.length; i++) {

        const char = text.charAt(i);
        const uppercaseChar = char.toUpperCase();
        const letterData = allLetters[uppercaseChar];

        if ((letterWidth * (i % windowWidth)) >= windowWidth) {
            currentLine = currentLine + 200
        }
        drawLetter(letterData, { x: letterWidth * i, y: currentLine });
    }


    function drawLetter(letter, translation) {
        let range = 4
        push();
        translate(translation.x, translation.y)
        for (let i = 0; i < letter.lines.length; i++) {
            const { x1, y1, x2, y2 } = letter.lines[i];
            line(random(x1, x1 + range), random(y1, y1 + range), random(x2, x2 + range), random(y2, y2 + range));
        }
        pop();

    }
}

标签: javascriptp5.js

解决方案


我喜欢你在做什么。那些曲折的字母很有趣:)

这不是一个功能代码示例。下次您在这里发布问题时,建议添加一个工作示例:) 我确实让它与 const text = 'abcdabcd'..

一些小点:没有必要有“const windowWidth = window.innerWidth”,因为 p5.js 已经提供了该变量。您甚至可以使用宽度,因为您使用 windowWidth 的宽度创建画布。

..

您的代码实际上工作正常。

if ((letterWidth * (i % windowWidth)) >= windowWidth) {
    currentLine = currentLine + 200
}

console.log(currentLine)

您将看到输出为 0、200、400。但是当您调用 drawLetters 时,翻译对象的 x 值仍然是 i * letterWidth。这意味着它在新行上绘制它,但在画布之外,您看不到它。

drawLetter(letterData, { x: letterWidth * i, y: currentLine });

我试过这个,但它也不起作用,因为它会下降一行,但 x 仍然移动超过 1 个字母宽度。

drawLetter(letterData, { x: (letterWidth * i) % windowWidth, y: currentLine });

..

该代码也没有考虑字母的宽度,因此在您跳线之前,可能会将字母画在画布之外的一半。在我的示例中,我从宽度中减去了 letterWidth 以防止这种情况。

如果没有额外的变量,它实际上是不可行的。由于那里有 currentLine,只需添加一个 currentX。

const letterA = {
    lines: [
        { x1: 35, y1: 170, x2: 50, y2: 136 },
        { x1: 50, y1: 136, x2: 89, y2: 45 },
        { x1: 89, y1: 45, x2: 125, y2: 136 },
        { x1: 125, y1: 136, x2: 140, y2: 170 },
        { x1: 125, y1: 136, x2: 50, y2: 135 }
    ]
}

const letterB = {
    lines: [
        { x1: 35, y1: 170, x2: 35, y2: 102 },
        { x1: 35, y1: 102, x2: 35, y2: 41 },
        { x1: 35, y1: 41, x2: 125, y2: 52 },
        { x1: 109, y1: 103, x2: 35, y2: 103 },
        { x1: 125, y1: 52, x2: 109, y2: 103 },
        { x1: 109, y1: 103, x2: 125, y2: 159 },
        { x1: 125, y1: 159, x2: 35, y2: 170 }
    ]
}

const letterC = {
    lines: [
        { x1: 131, y1: 147, x2: 85, y2: 177 },
        { x1: 85, y1: 177, x2: 30, y2: 111 },
        { x1: 30, y1: 111, x2: 85, y2: 38 },
        { x1: 85, y1: 38, x2: 131, y2: 65 },
    ]
}

const letterD = {
    lines: [
        { x1: 36, y1: 170, x2: 36, y2: 45 },
        { x1: 36, y1: 45, x2: 123, y2: 54 },
        { x1: 123, y1: 54, x2: 138, y2: 111 },
        { x1: 138, y1: 111, x2: 113, y2: 162 },
        { x1: 113, y1: 162, x2: 36, y2: 170 }
    ]
}

const allLetters = {
    A: letterA,
    B: letterB,
    C: letterC,
    D: letterD
}



function setup() {
    createCanvas(windowWidth, 1080);
}

function draw() {

    background(255)
    strokeWeight(20);
    frameRate(3)

    const text = 'abcdabcd';
    const letterWidth = 170;

    let currentX = 0;
    let currentLine = 0;

    for (let i = 0; i < text.length; i++) {

        const char = text.charAt(i);
        const uppercaseChar = char.toUpperCase();
        const letterData = allLetters[uppercaseChar];

        //subtract the letterwidth, so it doesn't clip off of the canvas
        if ( currentX % width >= width - letterWidth ) {
            currentLine = currentLine + 200
            currentX = 0;
        }

        drawLetter(letterData, { x: currentX, y: currentLine });

        // here you add the letterWidth to the currentX positions.
        currentX += letterWidth;
    }

}

// This function should be outside the draw function. It cán be inside there, but you wouldn't be able to
// access it outside of the draw function, if you'd want
 function drawLetter(letter, translation) {
  let range = 4
  push();
  translate(translation.x, translation.y)
  for (let i = 0; i < letter.lines.length; i++) {
      const { x1, y1, x2, y2 } = letter.lines[i];
      line(random(x1, x1 + range), random(y1, y1 + range), random(x2, x2 + range), random(y2, y2 + range));
  }
  pop();

}

推荐阅读