Skip to content

Commit

Permalink
Merge pull request #4 from Sygnator/dev
Browse files Browse the repository at this point in the history
Enhanced profile type, Canvas Documentation
  • Loading branch information
Sygnator authored Apr 5, 2024
2 parents 5211b1a + 6786a1e commit b26538a
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 144 deletions.
2 changes: 1 addition & 1 deletion src/app.pcss
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

/* scrollbar */
::-webkit-scrollbar {
width: 8px;
width: 8px;
height: 8px;
}

Expand Down
1 change: 1 addition & 0 deletions src/lib/assets/CircleNone.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/lib/assets/SquareNone.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
184 changes: 129 additions & 55 deletions src/lib/components/Canvas.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,60 @@
let context: CanvasRenderingContext2D;
function loadImage(src: string): Promise<HTMLImageElement> {
/**
* Load an image from the specified source.
*
* @param source The URL or path to the image.
* @returns *HTMLImageElement* when the image is loaded successfully.
*/
function loadImage(source: string): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
const image = new Image();
image.onload = () => resolve(image);
image.onerror = reject;
image.src = source;
});
}
/**
* Draw an image.
*
* @param image The *HTML image element* to be drawn.
* @param x The X coordinate of the top left corner of the image.
* @param y The Y coordinate of the top left corner of the image.
* @param w The width of the image.
* @param h The height of the image.
* @param context The canvas rendering context.
*/
async function drawImage(
image: HTMLImageElement,
dx: number,
dy: number,
dw: number,
dh: number,
x: number,
y: number,
w: number,
h: number,
context: CanvasRenderingContext2D
): Promise<void> {
await image.decode();
context.drawImage(image, dx, dy, dw, dh);
context.drawImage(image, x, y, w, h);
}
/**
* Draw a **rounded** image.
*
* @param image The *HTML image element* to be drawn.
* @param x The X coordinate of the top left corner of the image.
* @param y The Y coordinate of the top left corner of the image.
* @param w The width of the image.
* @param h The height of the image.
* @param radius The radius of the rounded corners. **Specified in pixels.**
* @param context The canvas rendering context.
*/
async function drawRoundedImage(
image: HTMLImageElement,
dx: number,
dy: number,
dw: number,
dh: number,
x: number,
y: number,
w: number,
h: number,
radius: number,
context: CanvasRenderingContext2D
): Promise<void> {
Expand All @@ -59,15 +86,25 @@
context.clearRect(0, 0, 0, 0);
context.beginPath();
context.arc(dx + radius, dy + radius, radius, 0, Math.PI * 2);
context.arc(x + radius, y + radius, radius, 0, Math.PI * 2);
context.closePath();
context.clip();
context.drawImage(image, dx, dy, dw, dh);
context.drawImage(image, x, y, w, h);
context.restore();
}
/**
* Fills a rectangle.
*
* @param x The X coordinate of the top left corner of the rectangle.
* @param y The Y coordinate of the top left corner of the rectangle.
* @param w The width of the rectangle.
* @param h The height of the rectangle.
* @param color The fill color in hexadecimal format (#RRGGBB).
* @param context The canvas rendering context.
*/
async function fillRect(
x: number,
y: number,
Expand All @@ -81,7 +118,7 @@
}
/**
* Fills a rounded rectangle.
* Fills a **rounded** rectangle.
*
* @param x The X coordinate of the top left corner of the rectangle.
* @param y The Y coordinate of the top left corner of the rectangle.
Expand Down Expand Up @@ -115,6 +152,19 @@
context.fill();
}
/**
* Draw text onto the canvas.
*
* @param text The text to be drawn.
* @param x The X coordinate of the starting point for the text.
* @param y The Y coordinate of the starting point for the text.
* @param context The canvas rendering context.
* @param color The color of the text in hexadecimal format (#RRGGBB).
* @param size The size of the text (in pixels).
* @param font The font family for the text.
* @param fontStyle The style of the font (**bold**, *italic*, or nothing).
* @param weight The font weight (100, 300, 400, 700, or 900).
*/
async function drawText(
text: string,
x: number,
Expand Down Expand Up @@ -142,71 +192,78 @@
levelBorder: LevelBorderType,
context: CanvasRenderingContext2D
): Promise<void> {
let abImg: HTMLImageElement;
let avatarBorderImage: HTMLImageElement;
if (avatarBorder === AvatarBorder.Base && levelBorder) {
abImg = await loadImage(`/profile_assets/avatar_border/level/${levelBorder}.png`);
avatarBorderImage = await loadImage(`/profile_assets/avatar_border/level/${levelBorder}.png`);
} else {
abImg = await loadImage(`/profile_assets/avatar_border/${avatarBorder}.png`);
avatarBorderImage = await loadImage(`/profile_assets/avatar_border/${avatarBorder}.png`);
}
let pos = { x: 24, y: 39 };
let position = { x: 24, y: 39 };
// get positon
// get position of specific avatar border
switch (avatarBorder) {
case AvatarBorder.Bow:
pos = { x: 26, y: 48 };
position = { x: 26, y: 48 };
break;
case AvatarBorder.Dzedai:
pos = { x: 23, y: 38 };
position = { x: 23, y: 38 };
break;
case AvatarBorder.Water:
pos = { x: 35, y: 58 };
position = { x: 35, y: 58 };
break;
case AvatarBorder.Base:
pos = { x: 43, y: 59 };
position = { x: 43, y: 59 };
break;
case AvatarBorder.Crows:
pos = { x: 25, y: 42 };
position = { x: 25, y: 42 };
break;
case AvatarBorder.Metal:
pos = { x: 49, y: 65 };
position = { x: 49, y: 65 };
break;
case AvatarBorder.RedThinLeaves:
pos = { x: 30, y: 44 };
position = { x: 30, y: 44 };
break;
case AvatarBorder.Skull:
pos = { x: 28, y: 47 };
position = { x: 28, y: 47 };
break;
case AvatarBorder.Fire:
pos = { x: 45, y: 60 };
position = { x: 45, y: 60 };
break;
case AvatarBorder.Promium:
pos = { x: 38, y: 53 };
position = { x: 38, y: 53 };
break;
case AvatarBorder.Ice:
pos = { x: 44, y: 61 };
position = { x: 44, y: 61 };
break;
case AvatarBorder.Gold:
pos = { x: 18, y: 33 };
position = { x: 18, y: 33 };
break;
case AvatarBorder.Red:
pos = { x: 40, y: 58 };
position = { x: 40, y: 58 };
break;
case AvatarBorder.Rainbow:
pos = { x: 44, y: 60 };
position = { x: 44, y: 60 };
break;
case AvatarBorder.Pink:
pos = { x: 38, y: 53 };
position = { x: 38, y: 53 };
break;
case AvatarBorder.Simple:
pos = { x: 36, y: 53 };
position = { x: 36, y: 53 };
break;
default:
pos = { x: 24, y: 39 };
position = { x: 24, y: 39 };
break;
}
drawImage(abImg, pos.x, pos.y, abImg.width, abImg.height, context);
drawImage(
avatarBorderImage,
position.x,
position.y,
avatarBorderImage.width,
avatarBorderImage.height,
context
);
}
async function drawAvatar(
Expand Down Expand Up @@ -594,30 +651,41 @@
context: CanvasRenderingContext2D,
flip: boolean = false
): Promise<void> {
let isOnImg =
profileType === ProfileTypeEnum.StatsOnImg ||
profileType === ProfileTypeEnum.MiniGalleryOnImg;
switch (profileType) {
case ProfileTypeEnum.Cards:
case ProfileTypeEnum.CardsOnImg:
await drawCards(context, $profileConfig.cardsAmount);
break;
case ProfileTypeEnum.MiniGallery:
case ProfileTypeEnum.ShowCards:
case ProfileTypeEnum.MiniGalleryOnImg:
if ($profileConfig.miniGallery)
await drawMiniGallery(context, $profileConfig.isSmall, true, shadowsOpacity, flip);
await drawMiniGallery(context, $profileConfig.isSmall, isOnImg, shadowsOpacity, flip);
if ($profileConfig.cardsStats)
await drawWaifuProfile(context, true, shadowsOpacity, flip, $profileConfig.karma);
await drawWaifuProfile(context, isOnImg, shadowsOpacity, flip, $profileConfig.karma);
break;
case ProfileTypeEnum.Stats:
case ProfileTypeEnum.StatsOnImg:
case ProfileTypeEnum.StatsWithImg:
await drawStats(
context,
true,
isOnImg,
shadowsOpacity,
$profileConfig.animeStats,
$profileConfig.mangaStats,
$profileConfig.flip
);
if ($profileConfig.cardsStats)
await drawWaifuProfile(context, true, shadowsOpacity, flip, $profileConfig.karma);
await drawWaifuProfile(context, isOnImg, shadowsOpacity, flip, $profileConfig.karma);
if ($profileConfig.image && profileType === ProfileTypeEnum.StatsWithImg) {
const profileImage = await loadImage($profileConfig.image);
await drawImage(profileImage, 0, 160, 750, 340, context);
}
break;
case ProfileTypeEnum.Img:
default:
Expand All @@ -640,7 +708,13 @@
await drawImage(imgBase, 0, 0, imgBase.width, imgBase.height, context);
// Image profile
if ($profileConfig.image) {
if (
$profileConfig.image &&
$profileConfig.profileType != ProfileTypeEnum.Stats &&
$profileConfig.profileType != ProfileTypeEnum.StatsWithImg &&
$profileConfig.profileType != ProfileTypeEnum.Cards &&
$profileConfig.profileType != ProfileTypeEnum.MiniGallery
) {
const profileImage = await loadImage($profileConfig.image);
await drawImage(profileImage, 0, 160, 750, 340, context);
}
Expand All @@ -652,14 +726,6 @@
await drawImage(imgWaifu, 622, 34, 85, 120, context);
}
// profile bar
await drawProfileBar(
$profileConfig.barTop,
$profileConfig.barOpacity,
context,
$profileConfig.shadowsOpacity
);
// profil type
await drawProfile(
$profileConfig.profileType,
Expand All @@ -668,6 +734,14 @@
$profileConfig.flip
);
// profile bar
await drawProfileBar(
$profileConfig.barTop,
$profileConfig.barOpacity,
context,
$profileConfig.shadowsOpacity
);
// nickname and rank
const avatarX = 52;
const avatarY = 68;
Expand Down
30 changes: 23 additions & 7 deletions src/lib/components/ChooseCustomBorder.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import { AvatarBorder, type LevelBorderType } from '$lib';
import { profileConfig } from '$lib/profileConfig';
import { Modal, Card, Range, Tooltip, Label, Toggle, Input } from 'flowbite-svelte';
import CircleNone from '$lib/assets/CircleNone.svg?raw';
import SquareNone from '$lib/assets/SquareNone.svg?raw';
export let openModal: boolean;
let level = 0;
let levelB: LevelBorderType = false;
Expand Down Expand Up @@ -32,14 +35,17 @@
outsideclose
size="lg"
placement="top-center"
on:close={() => profileConfig.setLevelBorder(levelB)}
on:close={() => {
profileConfig.setLevelBorder(levelB);
profileConfig.setAvatarBorderColor(color);
}}
>
<div class="flex flex-row items-center justify-between">
<Toggle
checked={$profileConfig.hasRoundAvatar}
on:change={profileConfig.switchRoundAvatar}
disabled={$profileConfig.avatarBorder != AvatarBorder.None}
class={`dark:text-gray-${$profileConfig.avatarBorder != AvatarBorder.None ? "500" : "300"}`}
class={`dark:text-gray-${$profileConfig.avatarBorder != AvatarBorder.None ? '500' : '300'}`}
>
Okrągły Awatar
</Toggle>
Expand Down Expand Up @@ -85,11 +91,21 @@
}
}}
>
<img
class="object-fit: contain max-w-30 place-self-center p-2"
src={`/profile_assets/avatar_border/${avatarBorder == AvatarBorder.Base && levelB != false ? 'level/' + levelB : avatarBorder}.png`}
alt={avatarBorder}
/>
{#if avatarBorder != AvatarBorder.None}
<img
class="object-fit: contain max-w-30 place-self-center p-2"
src={`/profile_assets/avatar_border/${avatarBorder == AvatarBorder.Base && levelB != false ? 'level/' + levelB : avatarBorder}.png`}
alt={avatarBorder}
/>
{:else}
<div class="h-10/12 w-10/12" style={`stroke: ${color};`}>
{#if $profileConfig.hasRoundAvatar}
{@html CircleNone}
{:else}
{@html SquareNone}
{/if}
</div>
{/if}
<p class="mt-2 pb-1">{avatarBorder}</p>
</Card>
{/each}
Expand Down
Loading

0 comments on commit b26538a

Please sign in to comment.