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

Canvas绘图应用按下Enter后下划线残留问题求助

Canvas绘图应用Enter后下划线残留问题

我正在开发一款Canvas绘图应用,按下Enter后日志显示流程符合预期,但下划线仍残留在画布上(仅颜色变淡)。按预期此时isDrawingText已设为false,下划线本应停止绘制,求问题原因及解决办法。


文本类代码

const Text = class {
  constructor(ctx, colorPicker, text, coordinates) {
    this.ctx = ctx,
    this.colorPicker = colorPicker,
    this.text = text || "Text...",
    this.coordinates = coordinates,
    this.measure = this.ctx.measureText(this.text),
    this.underline = {
      x1: undefined,
    }

  }
  draw() {
    this.ctx.font = `normal 20px Lora`
    this.ctx.textBaseline = 'alphabetic'
    this.ctx.fillStyle = "red"
    this.ctx.textAlign = "left"
    this.ctx.textBaseline = "bottom"
    this.ctx.fillText(this.text, this.coordinates.x, this.coordinates.y )
    this.ctx.stroke() // 问题根源之一
  }
  update() {
    this.draw()
  }
  drawUnderline() {
    this.ctx.beginPath()
    this.ctx.moveTo(this.coordinates.x - this.measure.actualBoundingBoxLeft, this.coordinates.y)
    this.ctx.lineTo(this.coordinates.x + this.measure.actualBoundingBoxRight, this.coordinates.y)
    this.ctx.stroke()
  }
}

export default Text

动画函数代码

function animate() {
  requestAnimationFrame(animate)
  ctx.clearRect(0, 0, innerWidth, innerHeight)

  if (texts[0]) {
    console.log("texts 0")
    texts.forEach(text => {
      text.update()
    })
  }

  if (currentText && isDrawingText) {
      console.log("is drawing text")
      drawText(ctx, colorPicker, textToPlace, { x: textCoordinates.x, y: textCoordinates.y })
      currentText.drawUnderline()
  }
}

画布点击逻辑

const start = (event) => {

    isDrawingText = true
    textCoordinates.x = event.offsetX
    textCoordinates.y = event.offsetY

    drawText(ctx, colorPicker, textToPlace, { x: textCoordinates.x, y: textCoordinates.y })
  
}

绘图函数

import Text from '../classes/Text.js'

let texts = []
let currentText = null

const drawText = (ctx, colorPicker, textToPlace, coordinates) => {

  let textCoordinates = {
    x: undefined,
    y: undefined
  }

  if (coordinates.x && coordinates.y) {
    textCoordinates.x = coordinates.x,
    textCoordinates.y = coordinates.y
  }

  currentText = new Text(ctx, colorPicker.value, textToPlace, textCoordinates)
  
  currentText.update(true)
}

export { texts, drawText, currentText }

回车键逻辑

if (e.key === 'Enter') {
  texts.push(currentText)
  isDrawingText = false
} else if (e.key === 'Backspace') {
  textToPlace = textToPlace.substring(0, textToPlace.length - 1)
} else if (e.key !== 'Shift' && e.location === 0) {
  textToPlace = textToPlace + e.key
}

问题原因

  1. Canvas上下文路径残留:clearRect()仅清除画布像素,不会重置绘图上下文的路径状态。绘制下划线时创建的路径会保留在ctx中,后续绘制会复用该路径。
  2. 多余的stroke()调用:Text类的draw()方法末尾的this.ctx.stroke()属于无效调用——fillText不会生成路径,此调用会意外绘制之前残留的下划线路径。
  3. 样式未隔离:drawUnderline()未设置专属strokeStyle,后续绘制时使用默认样式,导致下划线呈现“颜色变淡”的异常视觉效果。

解决办法

  1. 删除draw()中多余的stroke()
    修改Text类的draw方法,移除末尾无意义的stroke()调用:
    draw() {
      this.ctx.font = `normal 20px Lora`
      this.ctx.textBaseline = 'alphabetic'
      this.ctx.fillStyle = "red"
      this.ctx.textAlign = "left"
      this.ctx.textBaseline = "bottom"
      this.ctx.fillText(this.text, this.coordinates.x, this.coordinates.y )
      // 删除此行:this.ctx.stroke()
    }
    
  2. 在draw()开头添加路径重置
    每次绘制文本前重置路径,彻底避免残留路径干扰:
    draw() {
      this.ctx.beginPath() // 新增:重置当前路径
      this.ctx.font = `normal 20px Lora`
      this.ctx.textBaseline = 'alphabetic'
      this.ctx.fillStyle = "red"
      this.ctx.textAlign = "left"
      this.ctx.textBaseline = "bottom"
      this.ctx.fillText(this.text, this.coordinates.x, this.coordinates.y )
    }
    
  3. 给下划线设置专属样式
    在drawUnderline()中明确指定下划线颜色,避免样式污染:
    drawUnderline() {
      this.ctx.beginPath()
      this.ctx.strokeStyle = "red" // 设置下划线颜色,与文本颜色一致
      this.ctx.moveTo(this.coordinates.x - this.measure.actualBoundingBoxLeft, this.coordinates.y)
      this.ctx.lineTo(this.coordinates.x + this.measure.actualBoundingBoxRight, this.coordinates.y)
      this.ctx.stroke()
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 23:27:44