@cognima/banners 0.0.1-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/fonts/Manrope/Manrope-Bold.ttf +0 -0
- package/assets/fonts/Manrope/Manrope-Regular.ttf +0 -0
- package/assets/fonts/Others/AbyssinicaSIL-Regular.ttf +0 -0
- package/assets/fonts/Others/ChirpRegular.ttf +0 -0
- package/assets/fonts/Poppins/Poppins-Bold.ttf +0 -0
- package/assets/fonts/Poppins/Poppins-Medium.ttf +0 -0
- package/assets/fonts/Poppins/Poppins-Regular.ttf +0 -0
- package/assets/placeholders/album_art.png +0 -0
- package/assets/placeholders/avatar.png +0 -0
- package/assets/placeholders/badge.jpg +0 -0
- package/assets/placeholders/badge.png +0 -0
- package/assets/placeholders/badge_2.jpg +0 -0
- package/assets/placeholders/badge_3.jpg +0 -0
- package/assets/placeholders/badge_4.jpg +0 -0
- package/assets/placeholders/badge_5.jpg +0 -0
- package/assets/placeholders/banner.jpeg +0 -0
- package/assets/placeholders/images.jpeg +0 -0
- package/index.js +153 -0
- package/package.json +34 -0
- package/src/animation-effects.js +631 -0
- package/src/cache-manager.js +258 -0
- package/src/community-banner.js +1536 -0
- package/src/constants.js +208 -0
- package/src/discord-profile.js +584 -0
- package/src/e-commerce-banner.js +1214 -0
- package/src/effects.js +355 -0
- package/src/error-handler.js +305 -0
- package/src/event-banner.js +1319 -0
- package/src/facebook-post.js +679 -0
- package/src/gradient-welcome.js +430 -0
- package/src/image-filters.js +1034 -0
- package/src/image-processor.js +1014 -0
- package/src/instagram-post.js +504 -0
- package/src/interactive-elements.js +1208 -0
- package/src/linkedin-post.js +658 -0
- package/src/marketing-banner.js +1089 -0
- package/src/minimalist-banner.js +892 -0
- package/src/modern-profile.js +755 -0
- package/src/performance-optimizer.js +216 -0
- package/src/telegram-header.js +544 -0
- package/src/test-runner.js +645 -0
- package/src/tiktok-post.js +713 -0
- package/src/twitter-header.js +604 -0
- package/src/validator.js +442 -0
- package/src/welcome-leave.js +445 -0
- package/src/whatsapp-status.js +386 -0
- package/src/youtube-thumbnail.js +681 -0
- package/utils.js +710 -0
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Módulo de Banner de Boas-vindas com Gradiente
|
|
5
|
+
*
|
|
6
|
+
* Este módulo gera banners de boas-vindas modernos com gradientes personalizáveis,
|
|
7
|
+
* efeitos de sombra e design minimalista.
|
|
8
|
+
*
|
|
9
|
+
* @author Cognima Team (melhorado)
|
|
10
|
+
* @version 2.0.0
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
|
|
15
|
+
const pureimage = require("pureimage");
|
|
16
|
+
const path = require("path");
|
|
17
|
+
const {
|
|
18
|
+
loadImageWithAxios,
|
|
19
|
+
encodeToBuffer,
|
|
20
|
+
roundRect,
|
|
21
|
+
wrapText,
|
|
22
|
+
registerFontIfNeeded,
|
|
23
|
+
isValidHexColor,
|
|
24
|
+
DEFAULT_FONT_FAMILY,
|
|
25
|
+
applyTextShadow,
|
|
26
|
+
clearShadow,
|
|
27
|
+
createLinearGradient,
|
|
28
|
+
hexToRgba
|
|
29
|
+
} = require("../utils");
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @class GradientWelcome
|
|
33
|
+
* @classdesc Gera um banner de boas-vindas moderno com gradientes e design minimalista.
|
|
34
|
+
* @example const welcomeCard = new GradientWelcome()
|
|
35
|
+
* .setAvatar("avatar.png")
|
|
36
|
+
* .setUsername("NovoUsuário")
|
|
37
|
+
* .setMessage("Bem-vindo à nossa comunidade!")
|
|
38
|
+
* .setGradient("#3498db", "#8e44ad", "diagonal")
|
|
39
|
+
* .build();
|
|
40
|
+
*/
|
|
41
|
+
module.exports = class GradientWelcome {
|
|
42
|
+
constructor(options) {
|
|
43
|
+
// Dados Principais
|
|
44
|
+
this.avatar = null;
|
|
45
|
+
this.username = "Usuário";
|
|
46
|
+
this.message = "Bem-vindo à comunidade!";
|
|
47
|
+
this.memberCount = null;
|
|
48
|
+
|
|
49
|
+
// Personalização Visual
|
|
50
|
+
this.font = { name: options?.font?.name ?? DEFAULT_FONT_FAMILY, path: options?.font?.path };
|
|
51
|
+
this.gradientStart = "#3498db";
|
|
52
|
+
this.gradientEnd = "#8e44ad";
|
|
53
|
+
this.gradientDirection = "diagonal";
|
|
54
|
+
this.textColor = "#FFFFFF";
|
|
55
|
+
this.secondaryTextColor = "#E0E0E0";
|
|
56
|
+
this.avatarBorderColor = "#FFFFFF";
|
|
57
|
+
this.avatarBorderWidth = 4;
|
|
58
|
+
this.cornerRadius = 30;
|
|
59
|
+
this.useTextShadow = true;
|
|
60
|
+
this.useBlur = true;
|
|
61
|
+
this.blurAmount = 10;
|
|
62
|
+
|
|
63
|
+
// Configurações de Layout
|
|
64
|
+
this.cardWidth = 800;
|
|
65
|
+
this.cardHeight = 300;
|
|
66
|
+
this.avatarSize = 150;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// --- Setters para Dados Principais ---
|
|
70
|
+
/**
|
|
71
|
+
* Define a imagem do avatar
|
|
72
|
+
* @param {string|Buffer|Object} image - URL, Buffer ou caminho da imagem do avatar
|
|
73
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
74
|
+
*/
|
|
75
|
+
setAvatar(image) {
|
|
76
|
+
if (!image) throw new Error("A fonte da imagem do avatar não pode estar vazia.");
|
|
77
|
+
this.avatar = image;
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Define o nome de usuário
|
|
83
|
+
* @param {string} name - Nome do usuário
|
|
84
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
85
|
+
*/
|
|
86
|
+
setUsername(name) {
|
|
87
|
+
if (!name || typeof name !== "string") throw new Error("O nome de usuário deve ser uma string não vazia.");
|
|
88
|
+
this.username = name;
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Define o texto da mensagem
|
|
94
|
+
* @param {string} text - Texto da mensagem
|
|
95
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
96
|
+
*/
|
|
97
|
+
setMessage(text) {
|
|
98
|
+
if (!text || typeof text !== "string") throw new Error("O texto da mensagem deve ser uma string não vazia.");
|
|
99
|
+
this.message = text;
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Define o contador de membros
|
|
105
|
+
* @param {number|string} count - Número de membros
|
|
106
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
107
|
+
*/
|
|
108
|
+
setMemberCount(count) {
|
|
109
|
+
if (count === null || count === undefined) {
|
|
110
|
+
this.memberCount = null;
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (typeof count !== "number" && typeof count !== "string") {
|
|
115
|
+
throw new Error("O contador de membros deve ser um número ou uma string.");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
this.memberCount = count.toString();
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// --- Setters para Personalização Visual ---
|
|
123
|
+
/**
|
|
124
|
+
* Define o gradiente de fundo
|
|
125
|
+
* @param {string} startColor - Cor inicial do gradiente (hexadecimal)
|
|
126
|
+
* @param {string} endColor - Cor final do gradiente (hexadecimal)
|
|
127
|
+
* @param {string} direction - Direção do gradiente ('vertical', 'horizontal', 'diagonal')
|
|
128
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
129
|
+
*/
|
|
130
|
+
setGradient(startColor, endColor, direction = "diagonal") {
|
|
131
|
+
if (!startColor || !isValidHexColor(startColor)) throw new Error("Cor inicial do gradiente inválida. Use o formato hexadecimal.");
|
|
132
|
+
if (!endColor || !isValidHexColor(endColor)) throw new Error("Cor final do gradiente inválida. Use o formato hexadecimal.");
|
|
133
|
+
|
|
134
|
+
const validDirections = ["vertical", "horizontal", "diagonal"];
|
|
135
|
+
if (!validDirections.includes(direction.toLowerCase())) {
|
|
136
|
+
throw new Error(`Direção do gradiente inválida. Use uma das seguintes: ${validDirections.join(", ")}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.gradientStart = startColor;
|
|
140
|
+
this.gradientEnd = endColor;
|
|
141
|
+
this.gradientDirection = direction.toLowerCase();
|
|
142
|
+
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Define a cor do texto principal
|
|
148
|
+
* @param {string} color - Cor hexadecimal
|
|
149
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
150
|
+
*/
|
|
151
|
+
setTextColor(color) {
|
|
152
|
+
if (!color || !isValidHexColor(color)) throw new Error("Cor de texto inválida. Use o formato hexadecimal.");
|
|
153
|
+
this.textColor = color;
|
|
154
|
+
return this;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Define a cor do texto secundário
|
|
159
|
+
* @param {string} color - Cor hexadecimal
|
|
160
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
161
|
+
*/
|
|
162
|
+
setSecondaryTextColor(color) {
|
|
163
|
+
if (!color || !isValidHexColor(color)) throw new Error("Cor de texto secundário inválida. Use o formato hexadecimal.");
|
|
164
|
+
this.secondaryTextColor = color;
|
|
165
|
+
return this;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Define a cor da borda do avatar
|
|
170
|
+
* @param {string} color - Cor hexadecimal
|
|
171
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
172
|
+
*/
|
|
173
|
+
setAvatarBorderColor(color) {
|
|
174
|
+
if (!color || !isValidHexColor(color)) throw new Error("Cor de borda do avatar inválida. Use o formato hexadecimal.");
|
|
175
|
+
this.avatarBorderColor = color;
|
|
176
|
+
return this;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Define a largura da borda do avatar
|
|
181
|
+
* @param {number} width - Largura da borda em pixels
|
|
182
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
183
|
+
*/
|
|
184
|
+
setAvatarBorderWidth(width) {
|
|
185
|
+
if (typeof width !== "number" || width < 0) throw new Error("A largura da borda do avatar deve ser um número não negativo.");
|
|
186
|
+
this.avatarBorderWidth = width;
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Define o raio dos cantos arredondados
|
|
192
|
+
* @param {number} radius - Raio dos cantos em pixels
|
|
193
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
194
|
+
*/
|
|
195
|
+
setCornerRadius(radius) {
|
|
196
|
+
if (typeof radius !== "number" || radius < 0) throw new Error("O raio dos cantos deve ser um número não negativo.");
|
|
197
|
+
this.cornerRadius = radius;
|
|
198
|
+
return this;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Ativa ou desativa a sombra de texto
|
|
203
|
+
* @param {boolean} enabled - Se a sombra de texto deve ser ativada
|
|
204
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
205
|
+
*/
|
|
206
|
+
enableTextShadow(enabled = true) {
|
|
207
|
+
this.useTextShadow = enabled;
|
|
208
|
+
return this;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Ativa ou desativa o efeito de desfoque
|
|
213
|
+
* @param {boolean} enabled - Se o desfoque deve ser ativado
|
|
214
|
+
* @param {number} amount - Quantidade de desfoque (1-20)
|
|
215
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
216
|
+
*/
|
|
217
|
+
enableBlur(enabled = true, amount = 10) {
|
|
218
|
+
this.useBlur = enabled;
|
|
219
|
+
|
|
220
|
+
if (typeof amount === "number" && amount >= 1 && amount <= 20) {
|
|
221
|
+
this.blurAmount = amount;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Define as dimensões do card
|
|
229
|
+
* @param {number} width - Largura do card em pixels
|
|
230
|
+
* @param {number} height - Altura do card em pixels
|
|
231
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
232
|
+
*/
|
|
233
|
+
setCardDimensions(width, height) {
|
|
234
|
+
if (typeof width !== "number" || width < 400 || width > 1200) {
|
|
235
|
+
throw new Error("A largura do card deve estar entre 400 e 1200 pixels.");
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (typeof height !== "number" || height < 200 || height > 600) {
|
|
239
|
+
throw new Error("A altura do card deve estar entre 200 e 600 pixels.");
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
this.cardWidth = width;
|
|
243
|
+
this.cardHeight = height;
|
|
244
|
+
|
|
245
|
+
return this;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Define o tamanho do avatar
|
|
250
|
+
* @param {number} size - Tamanho do avatar em pixels
|
|
251
|
+
* @returns {GradientWelcome} - Instância atual para encadeamento
|
|
252
|
+
*/
|
|
253
|
+
setAvatarSize(size) {
|
|
254
|
+
if (typeof size !== "number" || size < 80 || size > 250) {
|
|
255
|
+
throw new Error("O tamanho do avatar deve estar entre 80 e 250 pixels.");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
this.avatarSize = size;
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// --- Método de Construção ---
|
|
263
|
+
/**
|
|
264
|
+
* Constrói o banner e retorna um buffer de imagem
|
|
265
|
+
* @returns {Promise<Buffer>} - Buffer contendo a imagem do banner
|
|
266
|
+
*/
|
|
267
|
+
async build() {
|
|
268
|
+
if (!this.avatar) throw new Error("A imagem do avatar deve ser definida usando setAvatar().");
|
|
269
|
+
|
|
270
|
+
// --- Registro de Fonte ---
|
|
271
|
+
const registeredFontName = await registerFontIfNeeded(this.font);
|
|
272
|
+
|
|
273
|
+
// --- Configuração do Canvas ---
|
|
274
|
+
const cardWidth = this.cardWidth;
|
|
275
|
+
const cardHeight = this.cardHeight;
|
|
276
|
+
const avatarSize = this.avatarSize;
|
|
277
|
+
const borderRadius = this.cornerRadius;
|
|
278
|
+
const padding = 40;
|
|
279
|
+
|
|
280
|
+
const canvas = pureimage.make(cardWidth, cardHeight);
|
|
281
|
+
const ctx = canvas.getContext("2d");
|
|
282
|
+
|
|
283
|
+
// --- Desenha Plano de Fundo com Gradiente ---
|
|
284
|
+
ctx.save();
|
|
285
|
+
roundRect(ctx, 0, 0, cardWidth, cardHeight, borderRadius, false, false);
|
|
286
|
+
ctx.clip();
|
|
287
|
+
|
|
288
|
+
// Cria e aplica o gradiente
|
|
289
|
+
const gradient = createLinearGradient(
|
|
290
|
+
ctx,
|
|
291
|
+
0,
|
|
292
|
+
0,
|
|
293
|
+
cardWidth,
|
|
294
|
+
cardHeight,
|
|
295
|
+
this.gradientStart,
|
|
296
|
+
this.gradientEnd,
|
|
297
|
+
this.gradientDirection
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
ctx.fillStyle = gradient;
|
|
301
|
+
ctx.fillRect(0, 0, cardWidth, cardHeight);
|
|
302
|
+
|
|
303
|
+
// Adiciona um efeito de "brilho" no canto superior
|
|
304
|
+
ctx.globalAlpha = 0.15;
|
|
305
|
+
ctx.fillStyle = "#FFFFFF";
|
|
306
|
+
ctx.beginPath();
|
|
307
|
+
ctx.arc(cardWidth * 0.2, cardHeight * 0.2, Math.min(cardWidth, cardHeight) * 0.5, 0, Math.PI * 2);
|
|
308
|
+
ctx.fill();
|
|
309
|
+
|
|
310
|
+
ctx.restore();
|
|
311
|
+
ctx.globalAlpha = 1;
|
|
312
|
+
|
|
313
|
+
// --- Desenha Avatar ---
|
|
314
|
+
const avatarX = padding;
|
|
315
|
+
const avatarY = (cardHeight - avatarSize) / 2;
|
|
316
|
+
|
|
317
|
+
// Desenha sombra do avatar
|
|
318
|
+
ctx.shadowColor = "rgba(0, 0, 0, 0.3)";
|
|
319
|
+
ctx.shadowBlur = 15;
|
|
320
|
+
ctx.shadowOffsetX = 0;
|
|
321
|
+
ctx.shadowOffsetY = 5;
|
|
322
|
+
|
|
323
|
+
ctx.save();
|
|
324
|
+
ctx.beginPath();
|
|
325
|
+
ctx.arc(avatarX + avatarSize / 2, avatarY + avatarSize / 2, avatarSize / 2, 0, Math.PI * 2);
|
|
326
|
+
ctx.closePath();
|
|
327
|
+
ctx.clip();
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
const avatarImg = await loadImageWithAxios(this.avatar);
|
|
331
|
+
ctx.drawImage(avatarImg, avatarX, avatarY, avatarSize, avatarSize);
|
|
332
|
+
} catch (e) {
|
|
333
|
+
console.error("Falha ao desenhar imagem do avatar:", e.message);
|
|
334
|
+
ctx.fillStyle = "#555";
|
|
335
|
+
ctx.fillRect(avatarX, avatarY, avatarSize, avatarSize);
|
|
336
|
+
ctx.fillStyle = "#FFF";
|
|
337
|
+
ctx.font = `bold 30px ${registeredFontName}-Bold`;
|
|
338
|
+
ctx.textAlign = "center";
|
|
339
|
+
ctx.textBaseline = "middle";
|
|
340
|
+
ctx.fillText("?", avatarX + avatarSize / 2, avatarY + avatarSize / 2);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
ctx.restore();
|
|
344
|
+
|
|
345
|
+
// Remove a sombra para os próximos elementos
|
|
346
|
+
clearShadow(ctx);
|
|
347
|
+
|
|
348
|
+
// --- Desenha Borda do Avatar ---
|
|
349
|
+
if (this.avatarBorderColor) {
|
|
350
|
+
ctx.strokeStyle = this.avatarBorderColor;
|
|
351
|
+
ctx.lineWidth = this.avatarBorderWidth;
|
|
352
|
+
ctx.beginPath();
|
|
353
|
+
ctx.arc(avatarX + avatarSize / 2, avatarY + avatarSize / 2, avatarSize / 2 + ctx.lineWidth / 2, 0, Math.PI * 2);
|
|
354
|
+
ctx.stroke();
|
|
355
|
+
ctx.closePath();
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// --- Desenha Texto --- (À direita do avatar)
|
|
359
|
+
const textX = avatarX + avatarSize + padding;
|
|
360
|
+
const textY = cardHeight / 2 - 40;
|
|
361
|
+
const textMaxWidth = cardWidth - textX - padding;
|
|
362
|
+
|
|
363
|
+
// Mensagem de Boas-vindas
|
|
364
|
+
ctx.fillStyle = this.textColor;
|
|
365
|
+
ctx.font = `bold 36px ${registeredFontName}-Bold`;
|
|
366
|
+
ctx.textAlign = "start";
|
|
367
|
+
ctx.textBaseline = "middle";
|
|
368
|
+
|
|
369
|
+
// Aplica sombra de texto se ativada
|
|
370
|
+
if (this.useTextShadow) {
|
|
371
|
+
applyTextShadow(ctx, "rgba(0, 0, 0, 0.5)", 3, 2, 2);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
ctx.fillText(this.message, textX, textY);
|
|
375
|
+
wrapText(ctx, this.message, textX, textY, textMaxWidth, 28, registeredFontName);
|
|
376
|
+
|
|
377
|
+
// Remove sombra para o próximo texto
|
|
378
|
+
if (this.useTextShadow) {
|
|
379
|
+
clearShadow(ctx);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Nome de Usuário
|
|
383
|
+
ctx.fillStyle = this.secondaryTextColor;
|
|
384
|
+
ctx.font = `medium 28px ${registeredFontName}-Medium`;
|
|
385
|
+
|
|
386
|
+
// Aplica sombra de texto se ativada
|
|
387
|
+
if (this.useTextShadow) {
|
|
388
|
+
applyTextShadow(ctx, "rgba(0, 0, 0, 0.4)", 2, 1, 1);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const usernameText = this.username.length > 25 ? this.username.slice(0, 22) + "..." : this.username;
|
|
392
|
+
ctx.fillText(usernameText, textX, textY + 50);
|
|
393
|
+
wrapText(ctx, usernameText, textX, textY + 50, textMaxWidth, 28, registeredFontName);
|
|
394
|
+
|
|
395
|
+
// Remove sombra para o próximo texto
|
|
396
|
+
if (this.useTextShadow) {
|
|
397
|
+
clearShadow(ctx);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Contador de Membros (se fornecido)
|
|
401
|
+
if (this.memberCount !== null) {
|
|
402
|
+
ctx.fillStyle = this.secondaryTextColor;
|
|
403
|
+
ctx.font = `regular 20px ${registeredFontName}-Regular`;
|
|
404
|
+
ctx.textAlign = "start";
|
|
405
|
+
|
|
406
|
+
// Aplica sombra de texto se ativada
|
|
407
|
+
if (this.useTextShadow) {
|
|
408
|
+
applyTextShadow(ctx, "rgba(0, 0, 0, 0.3)", 2, 1, 1);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const memberText = `Membro #${this.memberCount}`;
|
|
412
|
+
ctx.fillText(memberText, textX, textY + 90);
|
|
413
|
+
wrapText(ctx, memberText, textX, textY + 90, textMaxWidth, 28, registeredFontName);
|
|
414
|
+
|
|
415
|
+
// Remove sombra
|
|
416
|
+
if (this.useTextShadow) {
|
|
417
|
+
clearShadow(ctx);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// --- Codifica e Retorna Buffer ---
|
|
422
|
+
try {
|
|
423
|
+
return await encodeToBuffer(canvas);
|
|
424
|
+
} catch (err) {
|
|
425
|
+
console.error("Falha ao codificar o card de Boas-vindas com Gradiente:", err);
|
|
426
|
+
throw new Error("Não foi possível gerar o buffer de imagem do card de Boas-vindas com Gradiente.");
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
|