discord.js使用canvas开发悬赏令头像合成命令报错如何解决
问题解决方法
1. 路径报错修复
该找不到文件报错是因为使用了相对路径加载图片,Node.js 运行时的相对路径是基于进程启动的工作目录,而非当前代码文件所在目录,解决步骤如下:
- 首先引入
path模块处理路径:
const path = require('path')
- 调整图片加载的路径为绝对路径,根据你项目结构调整
../的层数,假设imgs文件夹存放在项目根目录,当前命令文件位于src/commands/目录下,写法参考如下:
// __dirname 代表当前代码文件所在目录的绝对路径 const wantedImg = await loadImage(path.resolve(__dirname, '../../imgs/wanted.png'))
你可以先打印
path.resolve(__dirname, 'imgs/wanted.png')的结果,确认和你实际的图片存放路径是否一致,调整到匹配即可解决路径报错。
另外你代码里如果存在"要替换为正常的双引号",这是内容转义导致的错误字符。
2. 完整功能实现步骤
直接返回wantedImg无法正常发送,需要通过canvas合成后转成discord支持的附件发送,完整实现代码如下:
const { createCanvas, loadImage } = require('canvas') const { MessageAttachment } = require('discord.js'); const path = require('path') const Command = require('../../structures/Command') module.exports = class extends Command { constructor(client) { super(client, { name: 'wanted', description: '将指定用户放到悬赏令海报中', options: [ { name: 'user', description: '要放在悬赏令中的用户', type: 'USER', required: true } ] }) } run = async (interaction) => { // 先延迟回复,避免图片加载超时导致交互失效 await interaction.deferReply() const canvas = createCanvas(239, 338) const ctx = canvas.getContext('2d') // 加载悬赏令模板,自行调整路径到你实际的图片位置 const wantedImg = await loadImage(path.resolve(__dirname, '../../imgs/wanted.png')) // 先绘制模板到画布 ctx.drawImage(wantedImg, 0, 0, canvas.width, canvas.height) // 加载用户头像,指定png格式和合适大小 const targetUser = interaction.options.getUser('user') const avatarUrl = targetUser.avatarURL({ extension: 'png', size: 256 }) const avatar = await loadImage(avatarUrl) // 绘制用户头像到悬赏令预留位置,以下坐标/宽高需要你根据自己的模板调整 // 四个参数分别是:头像、x坐标、y坐标、宽度、高度 ctx.drawImage(avatar, 30, 80, 180, 180) // 将画布转成附件 const attachment = new MessageAttachment(canvas.toBuffer(), 'wanted.png') // 发送结果 await interaction.editReply({ files: [attachment] }) } }
参数调整说明
- 你需要根据自己的
wanted.png模板的头像预留位置,调整ctx.drawImage(avatar, 30, 80, 180, 180)里的后四个参数,直到头像刚好匹配模板的空位即可。 - 如果需要将头像裁剪为圆形,可以在绘制头像前添加圆形裁剪路径:
ctx.save() ctx.beginPath() ctx.arc(120, 170, 90, 0, Math.PI * 2, true) // 圆心x、圆心y、半径 ctx.closePath() ctx.clip() // 这里放绘制头像的代码 ctx.drawImage(avatar, 30, 80, 180, 180) ctx.restore()
内容的提问来源于stack exchange,提问作者karasugami
相关产品推荐
相关产品推荐

