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

Canvas中翻转Sprite位置异常问题求助(JavaScript)

问题修复:Canvas图片翻转在centerEnabled关闭时坐标异常

问题现象

开启centerEnabled时,图片翻转(flipped=true)显示正常;关闭centerEnabled后,翻转的图片坐标混乱,超出画布无法看见。

问题代码

draw函数

draw()
{
    this.global.ctx.save();
    
    this.global.ctx.translate(this.getX() + this.getWidth()/2, this.getY() + this.getHeight()/2);
    
    if(this.#flipped)
    {
        this.global.ctx.scale(-1, 1);
    }
    else
    {
        this.global.ctx.scale(1, 1);
    }
    
    this.global.ctx.rotate((this.angle * Math.PI) / 180);
    //this.ctx.fillRect(-this.getWidth()/2, -this.getHeight()/2, this.getWidth(), this.getHeight()); //! DRAW HITBOX
    if(this.#centerEnabled)
    {
        this.global.ctx.drawImage(this.#image, -this.getWidth()/2 , -this.getHeight()/2, this.getWidth(), this.getHeight());
    }
    else
    {
        this.global.ctx.drawImage(this.#image, this.getX(), this.getY(), this.getWidth(), this.getHeight());
    }

    this.global.ctx.restore();
}

辅助获取函数

getX()

getX()
{
    if(this.#centerEnabled)
    {
        return this.global.getSize(this.x,"vw") - (this.getWidth()/2);
    }
    else{
        return this.global.getSize(this.x,"vw");
    }
}

getY()

getY()
{
    if(this.#centerEnabled)
    {
        return this.global.getSize(this.y,"vh") - (this.getHeight()/2);
    }
    else{
        return this.global.getSize(this.y,"vh");
    }
}

getWidth()

getWidth()
{
    return (((this.global.getSize(this.size,this.#resizeRule) * this.#ratio) / 100.0) * this.#scaleX).toFixed(3);
}

getHeight()

getHeight()
{
    return ((this.global.getSize(this.size,this.#resizeRule) / 100.0) * this.#scaleY).toFixed(3);
}

问题根源

  1. 坐标系叠加错误:无论centerEnabled状态如何,代码都将画布原点平移到了图片中心,但关闭centerEnabled时,drawImage使用的this.getX()/this.getY()是原始画布坐标系的左上角坐标,在平移后的坐标系中使用该值会导致图片被偏移到画布外。
  2. 翻转逻辑不统一:翻转操作基于平移后的中心原点,但关闭centerEnabled时未调整绘制偏移,导致翻转后的图片位置完全偏离预期。

修复代码

draw()
{
    this.global.ctx.save();
    
    // 根据centerEnabled确定平移目标:始终平移到图片中心
    const centerX = this.#centerEnabled ? this.getX() : this.getX() + this.getWidth()/2;
    const centerY = this.#centerEnabled ? this.getY() : this.getY() + this.getHeight()/2;
    this.global.ctx.translate(centerX, centerY);
    
    // 执行翻转(无需else分支,默认缩放比例为1)
    if(this.#flipped)
    {
        this.global.ctx.scale(-1, 1);
    }
    
    this.global.ctx.rotate((this.angle * Math.PI) / 180);
    
    // 根据centerEnabled调整绘制偏移,统一基于平移后的原点绘制
    const drawOffsetX = -this.getWidth()/2;
    const drawOffsetY = -this.getHeight()/2;
    this.global.ctx.drawImage(this.#image, drawOffsetX, drawOffsetY, this.getWidth(), this.getHeight());

    this.global.ctx.restore();
}

修复说明

  • 统一平移逻辑:不管centerEnabled是否开启,都将画布原点平移到图片中心,确保翻转、旋转操作始终围绕图片中心进行。
  • 修正绘制偏移:关闭centerEnabled时,绘制偏移依然使用-getWidth()/2和-getHeight()/2,平移后的原点(图片中心)加上该偏移,正好对应图片的左上角位置,与getX()/getY()的原始坐标匹配。
  • 冗余代码移除:删除了不必要的else { scale(1,1) }分支,因为Canvas默认缩放比例就是1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 07:55:17