feat: improve background with low-poly triangular pattern

- Replaced square grid with triangular mesh for more organic look
- Increased default cell size from 75px to 150px for subtlety
- Added variance to point positions for natural randomness
- Each cell now renders two triangles with gradient fills
- Maintains theme colors and daily variation
This commit is contained in:
Muhammad Ibrahim
2025-10-28 18:49:39 +00:00
parent 1d2c003830
commit f85721b292
2 changed files with 112 additions and 44 deletions

View File

@@ -236,7 +236,7 @@ const Layout = ({ children }) => {
navigate("/hosts?action=add"); navigate("/hosts?action=add");
}; };
// Generate geometric background pattern for dark mode // Generate low-poly triangular background pattern for dark mode
useEffect(() => { useEffect(() => {
const generateBackground = () => { const generateBackground = () => {
if ( if (
@@ -265,6 +265,7 @@ const Layout = ({ children }) => {
"#f093fb", "#f093fb",
"#4facfe", "#4facfe",
]; ];
const allColors = [...xColors, ...yColors];
// Use date for daily variation // Use date for daily variation
const today = new Date(); const today = new Date();
@@ -277,31 +278,64 @@ const Layout = ({ children }) => {
return x - Math.floor(x); return x - Math.floor(x);
}; };
// Draw gradient mesh // Create a grid of points with some variance
const cellSize = themeConfig.login.cellSize || 75; const cellSize = themeConfig.login.cellSize || 150; // Larger cells for more subtle effect
const cols = Math.ceil(canvas.width / cellSize) + 1; const variance = themeConfig.login.variance || 0.5;
const rows = Math.ceil(canvas.height / cellSize) + 1; const cols = Math.ceil(canvas.width / cellSize) + 2;
const rows = Math.ceil(canvas.height / cellSize) + 2;
for (let y = 0; y < rows; y++) { const points = [];
for (let x = 0; x < cols; x++) { for (let y = -1; y < rows; y++) {
for (let x = -1; x < cols; x++) {
const idx = y * cols + x; const idx = y * cols + x;
const color1 = const offsetX = (random(seed + idx * 2) - 0.5) * cellSize * variance;
xColors[Math.floor(random(seed + idx) * xColors.length)]; const offsetY =
const color2 = (random(seed + idx * 2 + 1000) - 0.5) * cellSize * variance;
yColors[Math.floor(random(seed + idx + 1000) * yColors.length)]; points.push({
x: x * cellSize + offsetX,
y: y * cellSize + offsetY,
color: allColors[Math.floor(random(seed + idx) * allColors.length)],
});
}
}
// Create gradient // Draw triangles between points
const gradient = ctx.createLinearGradient( for (let y = 0; y < rows - 1; y++) {
x * cellSize, for (let x = 0; x < cols - 1; x++) {
y * cellSize, const idx = y * cols + x;
(x + 1) * cellSize, const p1 = points[idx];
(y + 1) * cellSize, const p2 = points[idx + 1];
); const p3 = points[idx + cols];
gradient.addColorStop(0, color1); const p4 = points[idx + cols + 1];
gradient.addColorStop(1, color2);
ctx.fillStyle = gradient; // Draw two triangles per cell
ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize); // Triangle 1
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.lineTo(p3.x, p3.y);
ctx.closePath();
const gradient1 = ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
gradient1.addColorStop(0, p1.color);
gradient1.addColorStop(0.5, p2.color);
gradient1.addColorStop(1, p3.color);
ctx.fillStyle = gradient1;
ctx.fill();
// Triangle 2
ctx.beginPath();
ctx.moveTo(p2.x, p2.y);
ctx.lineTo(p4.x, p4.y);
ctx.lineTo(p3.x, p3.y);
ctx.closePath();
const gradient2 = ctx.createLinearGradient(p2.x, p2.y, p4.x, p4.y);
gradient2.addColorStop(0, p2.color);
gradient2.addColorStop(0.5, p4.color);
gradient2.addColorStop(1, p3.color);
ctx.fillStyle = gradient2;
ctx.fill();
} }
} }
}; };

View File

@@ -56,7 +56,7 @@ const Login = () => {
const navigate = useNavigate(); const navigate = useNavigate();
// Generate geometric background pattern based on selected theme // Generate low-poly triangular background pattern based on selected theme
useEffect(() => { useEffect(() => {
const generateBackground = () => { const generateBackground = () => {
if (!canvasRef.current || !themeConfig?.login) return; if (!canvasRef.current || !themeConfig?.login) return;
@@ -79,6 +79,7 @@ const Login = () => {
"#f093fb", "#f093fb",
"#4facfe", "#4facfe",
]; ];
const allColors = [...xColors, ...yColors];
// Use date for daily variation // Use date for daily variation
const today = new Date(); const today = new Date();
@@ -91,31 +92,64 @@ const Login = () => {
return x - Math.floor(x); return x - Math.floor(x);
}; };
// Draw gradient mesh // Create a grid of points with some variance
const cellSize = themeConfig.login.cellSize || 75; const cellSize = themeConfig.login.cellSize || 150; // Larger cells for more subtle effect
const cols = Math.ceil(canvas.width / cellSize) + 1; const variance = themeConfig.login.variance || 0.5;
const rows = Math.ceil(canvas.height / cellSize) + 1; const cols = Math.ceil(canvas.width / cellSize) + 2;
const rows = Math.ceil(canvas.height / cellSize) + 2;
for (let y = 0; y < rows; y++) { const points = [];
for (let x = 0; x < cols; x++) { for (let y = -1; y < rows; y++) {
for (let x = -1; x < cols; x++) {
const idx = y * cols + x; const idx = y * cols + x;
const color1 = const offsetX = (random(seed + idx * 2) - 0.5) * cellSize * variance;
xColors[Math.floor(random(seed + idx) * xColors.length)]; const offsetY =
const color2 = (random(seed + idx * 2 + 1000) - 0.5) * cellSize * variance;
yColors[Math.floor(random(seed + idx + 1000) * yColors.length)]; points.push({
x: x * cellSize + offsetX,
y: y * cellSize + offsetY,
color: allColors[Math.floor(random(seed + idx) * allColors.length)],
});
}
}
// Create gradient // Draw triangles between points
const gradient = ctx.createLinearGradient( for (let y = 0; y < rows - 1; y++) {
x * cellSize, for (let x = 0; x < cols - 1; x++) {
y * cellSize, const idx = y * cols + x;
(x + 1) * cellSize, const p1 = points[idx];
(y + 1) * cellSize, const p2 = points[idx + 1];
); const p3 = points[idx + cols];
gradient.addColorStop(0, color1); const p4 = points[idx + cols + 1];
gradient.addColorStop(1, color2);
ctx.fillStyle = gradient; // Draw two triangles per cell
ctx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize); // Triangle 1
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.lineTo(p3.x, p3.y);
ctx.closePath();
const gradient1 = ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y);
gradient1.addColorStop(0, p1.color);
gradient1.addColorStop(0.5, p2.color);
gradient1.addColorStop(1, p3.color);
ctx.fillStyle = gradient1;
ctx.fill();
// Triangle 2
ctx.beginPath();
ctx.moveTo(p2.x, p2.y);
ctx.lineTo(p4.x, p4.y);
ctx.lineTo(p3.x, p3.y);
ctx.closePath();
const gradient2 = ctx.createLinearGradient(p2.x, p2.y, p4.x, p4.y);
gradient2.addColorStop(0, p2.color);
gradient2.addColorStop(0.5, p4.color);
gradient2.addColorStop(1, p3.color);
ctx.fillStyle = gradient2;
ctx.fill();
} }
} }
}; };