discord-canvas
Version:
A package to simplifie the usage of canvas for Discord !
302 lines (274 loc) • 9.24 kB
JavaScript
const Canvas = require("canvas");
const { formatVariable, applyText } = require("../../utils/functions");
const badges = [1,9]; // min, max
module.exports = class RankCard {
constructor() {
this.backgroundImage = `${__dirname}/../../assets/img/1px.png`;
this.avatar = `${__dirname}/../../assets/img/default-avatar.png`;
this.level = "1";
this.rank = "10";
this.rankName = "rank Name";
this.reputation = "0";
this.username = "username";
this.xpCurrent = 8000;
this.xpNeeded = 12000;
this.addonReputation = true;
this.addonRank = true;
this.addonRankName = true;
this.addonBadges = true;
this.colorBackground = "#000000";
this.colorLevelBox = "#ff7b4b";
this.colorReputationBox = "#ff7b4b";
this.colorLevel = "#ffffff";
this.colorRank = "#ffffff";
this.colorRankName = "#ffffff";
this.colorUsername = "#ffffff";
this.colorReputation = "#ffffff";
this.colorBackgroundBar = "#000000";
this.colorNeededXp = "#ffffff";
this.colorBar = "#ffffff";
this.colorNoBadges = "#000000";
this.colorBadgesBox = "#000000";
this.radiusCorner = "20";
this.opacityAvatar = "0.4";
this.opacityBadges = "0.4";
this.opacityLevel = "1";
this.opacityBackgroundBar = "0.4";
this.opacityReputation = "1";
this.opacityNoBadges = "0.4";
this.textLevel = "lvl {level}";
this.textNeededXp = "{current}/{needed} for next rank";
this.textReputation = "+{reputation} rep";
for(let i = badges[0]; i <= badges[1]; i++) this[`badge${i}`] = null;
}
setAvatar(value) {
this.avatar = value;
return this;
}
setUsername(value) {
this.username = value;
return this;
}
setRank(value) {
this.rank = value;
return this;
}
setLevel(value) {
this.level = value;
return this;
}
setReputation(value) {
this.reputation = value;
return this;
}
setRankName(value) {
this.rankName = value;
return this;
}
setBackground(value) {
this.backgroundImage = value;
return this;
}
setXP(variable, value) {
const formattedVariable = formatVariable("xp", variable);
if (this[formattedVariable]) this[formattedVariable] = value;
return this;
}
setColor(variable, value) {
const formattedVariable = formatVariable("color", variable);
if (this[formattedVariable]) this[formattedVariable] = value;
return this;
}
setText(variable, value) {
const formattedVariable = formatVariable("text", variable);
if (this[formattedVariable]) this[formattedVariable] = value;
return this;
}
setOpacity(variable, value) {
const formattedVariable = formatVariable("opacity", variable);
if (this[formattedVariable]) this[formattedVariable] = value;
return this;
}
setAddon(variable, value) {
const formattedVariable = formatVariable("addon", variable);
if (this[formattedVariable]) this[formattedVariable] = value;
return this;
}
setBadge(variable, value) {
const number = Number(variable);
for(let i = badges[0]; i <= badges[1]; i++)
if(number === i){
this[`badge${number}`] = value;
break;
}
return this;
}
setRadius(value) {
this.radiusCorner = value;
return this;
}
async toAttachment() {
let canvas = Canvas.createCanvas(1080, 400),
ctx = canvas.getContext("2d");
const lvlText = this.textLevel.replace(/{level}/g, this.level);
const repText = this.textReputation.replace(
/{reputation}/g,
this.reputation
);
// Background
ctx.beginPath();
ctx.moveTo(0 + Number(this.radiusCorner), 0);
ctx.lineTo(0 + 1080 - Number(this.radiusCorner), 0);
ctx.quadraticCurveTo(0 + 1080, 0, 0 + 1080, 0 + Number(this.radiusCorner));
ctx.lineTo(0 + 1080, 0 + 400 - Number(this.radiusCorner));
ctx.quadraticCurveTo(
0 + 1080,
0 + 400,
0 + 1080 - Number(this.radiusCorner),
0 + 400
);
ctx.lineTo(0 + Number(this.radiusCorner), 0 + 400);
ctx.quadraticCurveTo(0, 0 + 400, 0, 0 + 400 - Number(this.radiusCorner));
ctx.lineTo(0, 0 + Number(this.radiusCorner));
ctx.quadraticCurveTo(0, 0, 0 + Number(this.radiusCorner), 0);
ctx.closePath();
ctx.clip();
ctx.fillStyle = this.colorBackground;
ctx.fillRect(0, 0, 1080, 400);
let background = await Canvas.loadImage(this.backgroundImage);
ctx.drawImage(background, 0, 0, 1080, 400);
ctx.restore();
// Draw layer
ctx.fillStyle = "#000000";
ctx.globalAlpha = this.opacityAvatar;
ctx.fillRect(50, 0, 240, canvas.height);
ctx.globalAlpha = 1;
// Avatar
let avatar = await Canvas.loadImage(this.avatar);
ctx.drawImage(avatar, 50 + 30, 30, 180, 180);
// Level
ctx.fillStyle = this.colorLevelBox;
ctx.globalAlpha = this.opacityLevel;
ctx.fillRect(50 + 30, 30 + 180 + 30, 180, 50);
ctx.globalAlpha = 1;
ctx.fillStyle = this.colorLevel;
ctx.font = applyText(canvas, lvlText, 32, 170, "Bold");
ctx.textAlign = "center";
ctx.fillText(lvlText, 50 + 30 + 180 / 2, 30 + 180 + 30 + 38);
// Rep
if (this.addonReputation) {
ctx.fillStyle = this.colorReputationBox;
ctx.globalAlpha = this.opacityReputation;
ctx.fillRect(50 + 30, 30 + 180 + 30 + 50 + 30, 180, 50);
ctx.globalAlpha = 1;
ctx.fillStyle = this.colorReputation;
ctx.font = applyText(canvas, repText, 32, 170, "Bold");
ctx.textAlign = "center";
ctx.fillText(repText, 50 + 30 + 180 / 2, 30 + 180 + 30 + 30 + 50 + 38);
}
// Username
ctx.textAlign = "left";
ctx.fillStyle = this.colorUsername;
ctx.font = applyText(canvas, this.username, 45, 460, "Bold");
ctx.fillText(this.username, 50 + 240 + 45 + 5, 80);
// Rank
if (this.addonRank) {
ctx.textAlign = "right";
ctx.fillStyle = this.colorRank;
ctx.font = applyText(canvas, "#" + this.rank, 45, 194, "Bold");
ctx.fillText("#" + this.rank, canvas.width - 50 - 5, 80);
}
if (this.addonRankName) {
ctx.textAlign = "left";
ctx.fillStyle = this.colorRankName;
ctx.font = applyText(canvas, this.rankName, 35, 690, "Bold");
ctx.fillText(this.rankName, 50 + 240 + 45 + 5, 80 + 45 + 15);
}
// Badges
if (this.addonBadges) {
ctx.fillStyle = this.colorBadgesBox;
ctx.globalAlpha = this.opacityBadges;
ctx.fillRect(240 + 50 + 50, 295, 700, 70);
ctx.fillStyle = this.colorNoBadges;
const badgeNames = [
'bubble', 'speaker', 'stream',
'picture', 'like', 'star',
'boost', 'money', 'bot'
];
for(let index = 0; index < badgeNames.length; index++){
let badge = `badge${index+1}`
if (!this[badge]){
ctx.globalAlpha = this.opacityNoBadges;
ctx.textAlign = "center";
ctx.font = applyText(canvas, ".", 120, 50, "Bold");
ctx.fillText(".", 75 * index + 390, 340);
}else{
ctx.globalAlpha = 1;
let badgeImg = await Canvas.loadImage(
['bronze','silver','gold','diamond'].includes(this[badge].toLowerCase()) ?
`${__dirname}/../../assets/img/rank/${badgeNames[index]}_${this[badge].toLowerCase()}.png` :
this[badge]
);
ctx.drawImage(badgeImg, 75 * index + 365, 305, 50, 50);
}
}
}
// XP
ctx.globalAlpha = 1;
const latestXP = Number(this.xpNeeded) - Number(this.xpCurrent);
const textXPEdited = this.textNeededXp
.replace(/{needed}/g, this.xpNeeded)
.replace(/{current}/g, this.xpCurrent)
.replace(/{latest}/g, latestXP);
ctx.textAlign = "center";
ctx.fillStyle = this.colorNeededXp;
ctx.font = applyText(canvas, textXPEdited, 25, 690, "Bold");
ctx.fillText(
textXPEdited,
50 + 240 + 45 + 5 + 690 / 2,
80 + 45 + 15 + 30 + 90
);
ctx.beginPath();
ctx.moveTo(240 + 50 + 50 + 25, 80 + 45 + 10 + 40);
ctx.lineTo(240 + 50 + 50 + 700 - 25, 80 + 45 + 10 + 40);
ctx.quadraticCurveTo(
240 + 50 + 50 + 700,
80 + 45 + 10 + 40,
240 + 50 + 50 + 700,
80 + 45 + 10 + 40 + 25
);
ctx.lineTo(240 + 50 + 50 + 700, 80 + 45 + 10 + 40 + 50 - 25);
ctx.quadraticCurveTo(
240 + 50 + 50 + 700,
80 + 45 + 10 + 40 + 50,
240 + 50 + 50 + 700 - 25,
80 + 45 + 10 + 40 + 50
);
ctx.lineTo(240 + 50 + 50 + 25, 80 + 45 + 10 + 40 + 50);
ctx.quadraticCurveTo(
240 + 50 + 50,
80 + 45 + 10 + 40 + 50,
240 + 50 + 50,
80 + 45 + 10 + 40 + 50 - 25
);
ctx.lineTo(240 + 50 + 50, 80 + 45 + 10 + 40 + 25);
ctx.quadraticCurveTo(
240 + 50 + 50,
80 + 45 + 10 + 40,
240 + 50 + 50 + 25,
80 + 45 + 10 + 40
);
ctx.closePath();
ctx.clip();
ctx.fillStyle = this.colorBackgroundBar;
ctx.globalAlpha = this.opacityBackgroundBar;
ctx.fillRect(240 + 50 + 50, 80 + 45 + 10 + 40, 700, 50);
ctx.fillStyle = this.colorBar;
ctx.globalAlpha = 1;
const percent = (100 * this.xpCurrent) / this.xpNeeded;
const progress = (percent * 700) / 100;
ctx.fillRect(240 + 50 + 50, 80 + 45 + 10 + 40, progress, 50);
ctx.restore();
return canvas;
}
};