diff --git a/index.html b/index.html
index eb920d90..cacd003d 100644
--- a/index.html
+++ b/index.html
@@ -36,6 +36,16 @@
BlueArchive
Transparent
Background
+
+
+
+
diff --git a/src/assets/image/cross.svg b/src/assets/image/cross.svg
new file mode 100644
index 00000000..e8de1dd4
--- /dev/null
+++ b/src/assets/image/cross.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/image/halo.svg b/src/assets/image/halo.svg
new file mode 100755
index 00000000..499969b0
--- /dev/null
+++ b/src/assets/image/halo.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/canvas.ts b/src/canvas.ts
index 38659e4b..e7100dbe 100644
--- a/src/canvas.ts
+++ b/src/canvas.ts
@@ -25,7 +25,10 @@ export default class LogoCanvas {
private textWidthL = 0;
private textWidthR = 0;
private graphOffset = graphOffset;
+ private accentColor = '#128AFA';
private transparentBg = false;
+ private swapColors = false;
+ private darkMode = false;
constructor() {
this.canvas = document.querySelector('#canvas')!;
this.ctx = this.canvas.getContext('2d')!;
@@ -33,6 +36,18 @@ export default class LogoCanvas {
this.canvas.width = canvasWidth;
this.bindEvent();
}
+ get backgroundColor() {
+ return this.darkMode ? '#2B2B2B' : '#fff';
+ }
+ get textColor() {
+ return this.darkMode ? '#fff' : '#2B2B2B';
+ }
+ get primaryColor() {
+ return this.swapColors ? this.textColor : this.accentColor;
+ }
+ get secondaryColor() {
+ return this.swapColors ? this.accentColor : this.textColor;
+ }
async draw() {
const loading = document.querySelector('#loading')!;
loading.classList.remove('hidden');
@@ -48,7 +63,7 @@ export default class LogoCanvas {
c.clearRect(0, 0, this.canvas.width, this.canvas.height);
//Background
if (!this.transparentBg) {
- c.fillStyle = '#fff';
+ c.fillStyle = this.backgroundColor;
c.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
//guide line
@@ -69,24 +84,26 @@ export default class LogoCanvas {
}
//blue text -> halo -> black text -> cross
c.font = font;
- c.fillStyle = '#128AFA';
+ c.fillStyle = this.primaryColor;
c.textAlign = 'end';
c.setTransform(1, 0, horizontalTilt, 1, 0, 0);
c.fillText(this.textL, this.canvasWidthL, this.canvas.height * textBaseLine);
c.resetTransform(); //restore don't work
- c.drawImage(
+ this.drawSVG(
+ c,
window.halo,
this.canvasWidthL - this.canvas.height / 2 + this.graphOffset.X,
this.graphOffset.Y,
canvasHeight,
- canvasHeight
+ canvasHeight,
+ this.textColor,
);
- c.fillStyle = '#2B2B2B';
+ c.fillStyle = this.secondaryColor;
c.textAlign = 'start';
if (this.transparentBg) {
c.globalCompositeOperation = 'destination-out';
}
- c.strokeStyle = 'white';
+ c.strokeStyle = this.backgroundColor;
c.lineWidth = 12;
c.setTransform(1, 0, horizontalTilt, 1, 0, 0);
c.strokeText(this.textR, this.canvasWidthL, this.canvas.height * textBaseLine);
@@ -112,17 +129,30 @@ export default class LogoCanvas {
if (this.transparentBg) {
c.globalCompositeOperation = 'destination-out';
}
- c.fillStyle = 'white';
+ c.fillStyle = this.backgroundColor;
c.fill();
c.globalCompositeOperation = 'source-over';
- c.drawImage(
+ this.drawSVG(
+ c,
window.cross,
this.canvasWidthL - this.canvas.height / 2 + graphOffset.X,
this.graphOffset.Y,
canvasHeight,
- canvasHeight
+ canvasHeight,
+ this.accentColor,
);
}
+ private drawSVG(c: CanvasRenderingContext2D, paths: string[], x: number, y: number, w: number, h: number, color: string) {
+ const path = new Path2D();
+ paths.forEach(pathString => {
+ const matrix = document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGMatrix();
+ const transformedMatrix = matrix.scale(w / 500, h / 500);
+ path.addPath(new Path2D(pathString), transformedMatrix);
+ });
+ c.fillStyle = color;
+ c.translate(x, y);
+ c.fill(path);
+ }
bindEvent() {
const process = (id: 'textL' | 'textR', el: HTMLInputElement) => {
this[id] = el.value;
@@ -153,6 +183,21 @@ export default class LogoCanvas {
this.transparentBg = tSwitch.checked;
this.draw();
});
+ const scSwitch = document.querySelector('#swap-colors')! as HTMLInputElement;
+ scSwitch.addEventListener('change', () => {
+ this.swapColors = scSwitch.checked;
+ this.draw();
+ });
+ const dSwitch = document.querySelector('#dark-mode')! as HTMLInputElement;
+ dSwitch.addEventListener('change', () => {
+ this.darkMode = dSwitch.checked;
+ this.draw();
+ });
+ const accentColorInput = document.querySelector('#accent-color')! as HTMLInputElement;
+ accentColorInput.addEventListener('input', () => {
+ this.accentColor = accentColorInput.value;
+ this.draw();
+ });
const gx = document.querySelector('#graphX')! as HTMLInputElement;
const gy = document.querySelector('#graphY')! as HTMLInputElement;
gx.addEventListener('input', () => {
diff --git a/src/locales/en.json b/src/locales/en.json
index 29e2d2cc..15afeb8b 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -4,11 +4,14 @@
"copy": "COPY",
"copy-success": "Image copied",
"transparent-background": "Transparent Background",
+ "swap-colors": "Swap Colors",
+ "dark-mode": "Dark Mode",
"advance": "Advance settings",
"halo-cross": "Halo & Cross position",
+ "accent-color": "Accent color",
"font-title": "Used Fonts",
"main-font": "Main font: ",
"fallback-font": "Fallback font: ",
"glow": "WĂȘlai Glow Sans",
"github-repo": "GitHub repo"
-}
\ No newline at end of file
+}
diff --git a/src/main.ts b/src/main.ts
index 8ed45d47..f596797b 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,10 +1,10 @@
import './style.css';
import LogoCanvas from './canvas';
-import loadImages from './utils/loadImages';
+import loadSVGs from './utils/loadSVGs';
import './i18n';
(async function () {
- await loadImages();
+ await loadSVGs();
const logo = new LogoCanvas();
logo.draw();
})();
diff --git a/src/utils/loadImages.ts b/src/utils/loadImages.ts
deleted file mode 100644
index 3ab6e98e..00000000
--- a/src/utils/loadImages.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import halo from '../assets/image/halo.png';
-import cross from '../assets/image/cross.png';
-
-const loadImg = (src: string): Promise => {
- return new Promise((resolve, reject) => {
- const img = new Image();
- img.src = src;
- img.onload = () => resolve(img);
- img.onerror = reject;
- });
-};
-export default async () => {
- await Promise.all([
- loadImg(halo).then((img) => (window.halo = img)),
- loadImg(cross).then((img) => (window.cross = img)),
- ]);
-};
diff --git a/src/utils/loadSVGs.ts b/src/utils/loadSVGs.ts
new file mode 100644
index 00000000..ef623b14
--- /dev/null
+++ b/src/utils/loadSVGs.ts
@@ -0,0 +1,18 @@
+import halo from '../assets/image/halo.svg';
+import cross from '../assets/image/cross.svg';
+
+const loadImg = async (src: string): Promise => {
+ const svg = await fetch(src);
+ const svgText = await svg.text();
+
+ const dp = new DOMParser();
+ const doc = dp.parseFromString(svgText, 'image/svg+xml');
+ const pathItems = doc.getElementsByTagName('path');
+ return Array.from(pathItems).map((item) => item.getAttribute('d')!);
+};
+export default async () => {
+ await Promise.all([
+ loadImg(halo).then((img) => (window.halo = img)),
+ loadImg(cross).then((img) => (window.cross = img)),
+ ]);
+};
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
index 382dbadd..ad99347f 100644
--- a/src/vite-env.d.ts
+++ b/src/vite-env.d.ts
@@ -1,6 +1,6 @@
///
interface Window {
- halo: HTMLImageElement;
- cross: HTMLImageElement;
+ halo: string[];
+ cross: string[];
}