You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

p5.js中文本首字符重叠问题技术求助

文本字符重叠与空格消失问题的成因分析

问题描述

我正在实现一段文本默认隐藏、鼠标悬停时动态展开/收缩的效果,功能大体正常,但出现两个异常:

  • 索引0和1的字符(如"L"和"o")x坐标重叠
  • "e"与"laborum"之间的空格消失

相关代码

JavaScript 代码

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

function draw() {
  background(220);
  letters()
}

function letters() {
  let toParse = 'Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tempore pariatur explicabo itaque laborum. Reiciendis rem consectetur labore, molestiae pariatur laudantium eos dicta impedit tenetur vel id animi provident modi doloremque, recusandae excepturi veniam odio eaque quos delectus odit amet? Nihil vero facere maiores ducimus itaque distinctio eligendi magni, ab aliquid expedita eveniet porro, exercitationem blanditiis aliquam veritatis provident commodi a officiis illo magnam perferendis quam. Nihil alias optio mollitia aperiam consequatur, a labore ab exercitationem perferendis sunt velit ut et quisquam. Nemo ab voluptatum architecto esse iusto delectus, rem rerum velit quam ullam omnis autem sed accusamus quia! Voluptas vero qui quas natus adipisci, harum dolores fuga aperiam, officia pariatur consequatur quibusdam illo a saepe voluptatum quis temporibus cumque rerum, aliquid necessitatibus quae repudiandae excepturi? Sunt eius obcaecati eveniet laboriosam voluptate, quos impedit nam odit amet, commodi vero, accusamus aliquid accusantium fugit ducimus molestiae ex similique veniam. Fuga nam quis cupiditate ex facilis, ipsum, repellendus iure sed, consequuntur nisi illum repudiandae. Nobis ex nam, deserunt maiores facilis veritatis praesentium fugit delectus ab magni magnam laudantium, aut eum ullam aliquid cumque.'

  let parsedText = toParse.split('')

  noStroke()
  fill(223, 112, 69)
  ellipse(mouseX, mouseY, width / 20)

  let numLines = 4;

  for (let j = 0; j < numLines; j++) {
    let numLetters = 100
    let x = width / 10
    let y = height / 2 + height / 50 * j
    for (let i = numLetters * j; i < numLetters + numLetters * j; i++) {
      let char = parsedText[i]
      let charWidth = textWidth(char)
      let charSize = map(dist(mouseX, mouseY, x, y), 0, width / 5, 24, 20)
      textSize(charSize)
      fill(map(dist(mouseX, mouseY, x, y), 0, width / 4, 15, 255))
      text(char, x, y)
      x += charWidth
    }
  }
}

HTML 代码

<html>

<head>
  <script src="https://cdn.jsdelivr.net/npm/p5@1.6.0/lib/p5.js"></script>
</head>

<body>
  <main>
  </main>
</body>

</html>

成因分析

  1. 字符宽度计算时机错误:代码中先调用textWidth(char)计算宽度,再设置textSize(charSize)。textWidth的结果依赖当前生效的文本尺寸,第一次循环时使用的是p5.js默认的12号字体宽度,而实际渲染用的是24或20号字体,导致计算出的宽度远小于实际需要的偏移量,后续字符的x坐标叠加不足,出现重叠。
  2. 空格字符偏移量不足:同样因为上述时机问题,空格的宽度是基于12号字体计算的,当实际渲染用更大的字号时,空格的实际显示宽度大于计算出的偏移量,导致后续字符覆盖了空格,视觉上看起来空格消失。

修正方案

将textSize(charSize)移到textWidth(char)之前,确保计算字符宽度时使用的是当前要渲染的字号:

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

function draw() {
  background(220);
  letters()
}

function letters() {
  let toParse = 'Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tempore pariatur explicabo itaque laborum. Reiciendis rem consectetur labore, molestiae pariatur laudantium eos dicta impedit tenetur vel id animi provident modi doloremque, recusandae excepturi veniam odio eaque quos delectus odit amet? Nihil vero facere maiores ducimus itaque distinctio eligendi magni, ab aliquid expedita eveniet porro, exercitationem blanditiis aliquam veritatis provident commodi a officiis illo magnam perferendis quam. Nihil alias optio mollitia aperiam consequatur, a labore ab exercitationem perferendis sunt velit ut et quisquam. Nemo ab voluptatum architecto esse iusto delectus, rem rerum velit quam ullam omnis autem sed accusamus quia! Voluptas vero qui quas natus adipisci, harum dolores fuga aperiam, officia pariatur consequatur quibusdam illo a saepe voluptatum quis temporibus cumque rerum, aliquid necessitatibus quae repudiandae excepturi? Sunt eius obcaecati eveniet laboriosam voluptate, quos impedit nam odit amet, commodi vero, accusamus aliquid accusantium fugit ducimus molestiae ex similique veniam. Fuga nam quis cupiditate ex facilis, ipsum, repellendus iure sed, consequuntur nisi illum repudiandae. Nobis ex nam, deserunt maiores facilis veritatis praesentium fugit delectus ab magni magnam laudantium, aut eum ullam aliquid cumque.'

  let parsedText = toParse.split('')

  noStroke()
  fill(223, 112, 69)
  ellipse(mouseX, mouseY, width / 20)

  let numLines = 4;

  for (let j = 0; j < numLines; j++) {
    let numLetters = 100
    let x = width / 10
    let y = height / 2 + height / 50 * j
    for (let i = numLetters * j; i < numLetters + numLetters * j; i++) {
      let char = parsedText[i]
      // 先设置当前字符的字号,再计算对应宽度
      let charSize = map(dist(mouseX, mouseY, x, y), 0, width / 5, 24, 20)
      textSize(charSize)
      let charWidth = textWidth(char)
      fill(map(dist(mouseX, mouseY, x, y), 0, width / 4, 15, 255))
      text(char, x, y)
      x += charWidth
    }
  }
}

内容的提问来源于stack exchange,提问作者Anton E

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:25:03