Add the buttons, add the background made my ari, add some basic css and basic index design.
44
assets/css/style.css
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* CSS Document */
|
||||||
|
body {
|
||||||
|
background-color: #0e0016;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons img {
|
||||||
|
width: 88px;
|
||||||
|
height: 31px;
|
||||||
|
border: none;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
-webkit-transition: none !important;
|
||||||
|
-o-transition: none !important;
|
||||||
|
transition: none !important;
|
||||||
|
-webkit-animation: none !important;
|
||||||
|
animation: none !important;
|
||||||
|
-webkit-animation-play-state: paused !important;
|
||||||
|
animation-play-state: paused !important;
|
||||||
|
scroll-behavior: auto !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#night {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #0e0016;
|
||||||
|
z-index: -9999;
|
||||||
|
}
|
||||||
BIN
assets/images/buttons/Purplebored_button.png
Normal file
|
After Width: | Height: | Size: 941 B |
BIN
assets/images/buttons/aagaming.png
Normal file
|
After Width: | Height: | Size: 999 B |
BIN
assets/images/buttons/airvpn_userbar.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
assets/images/buttons/aleksey.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
assets/images/buttons/any_browser.gif
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
assets/images/buttons/ari.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/images/buttons/authen.gif
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/images/buttons/dark-mode.gif
Normal file
|
After Width: | Height: | Size: 552 B |
BIN
assets/images/buttons/eclipsecx.png
Normal file
|
After Width: | Height: | Size: 1001 B |
BIN
assets/images/buttons/firefox.gif
Normal file
|
After Width: | Height: | Size: 975 B |
BIN
assets/images/buttons/freebsd.gif
Normal file
|
After Width: | Height: | Size: 965 B |
BIN
assets/images/buttons/fsky_night.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
assets/images/buttons/georgemoody.png
Normal file
|
After Width: | Height: | Size: 556 B |
BIN
assets/images/buttons/k327.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/images/buttons/mcneb10.gif
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
assets/images/buttons/midgard.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/images/buttons/telepath.png
Normal file
|
After Width: | Height: | Size: 510 B |
BIN
assets/images/buttons/tobskep.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/images/buttons/trace.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
assets/images/buttons/unpato.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/buttons/valid-atom.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/images/buttons/valid-rss.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
assets/images/buttons/xameren.png
Normal file
|
After Width: | Height: | Size: 426 B |
164
assets/js/script.js
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
"use strict";
|
||||||
|
function create_night(canvas_element) {
|
||||||
|
const context = canvas_element.getContext("2d");
|
||||||
|
const star_range = 0.7; /* Variation in star size */
|
||||||
|
const star_spread = 0.002; /* Star density per pixel */
|
||||||
|
const concentration_corner = "top-left"; /* Concentration corner position */
|
||||||
|
const concentration_strength = 5.0; /* How much should it be concentrated? */
|
||||||
|
const twinkle_intensity = 5.0; /* How noticeable should the twinkle be? */
|
||||||
|
const interaction_radius = 150; /* Radius around mouse/touch where stars react */
|
||||||
|
const interaction_brightness_factor = 5.0; /* How much brightness increases */
|
||||||
|
const interaction_size_factor = 1.5; /* How much the stars should grow in size (only during interaction) */
|
||||||
|
const magic = [
|
||||||
|
16.31189, 32454.4619, 9371.1474, 6848, 1544, 6848, 2156,
|
||||||
|
]; /* Just some magic numbers */
|
||||||
|
/* Seeded "random" number */
|
||||||
|
function seeded_random(seed) {
|
||||||
|
const value = Math.sin(seed) * 10000;
|
||||||
|
return value - Math.floor(value);
|
||||||
|
}
|
||||||
|
let stars = [];
|
||||||
|
let time = 0;
|
||||||
|
let mouse_x = -1,
|
||||||
|
mouse_y = -1;
|
||||||
|
/* Determine corner position for concentration */
|
||||||
|
function get_corner(width, height) {
|
||||||
|
switch (concentration_corner) {
|
||||||
|
case "top-right":
|
||||||
|
return { x: width, y: 0 };
|
||||||
|
case "bottom-left":
|
||||||
|
return { x: 0, y: height };
|
||||||
|
case "bottom-right":
|
||||||
|
return { x: width, y: height };
|
||||||
|
default:
|
||||||
|
return { x: 0, y: 0 }; /* top-left */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Function to generate star shape */
|
||||||
|
function draw_star(x, y, radius, alpha) {
|
||||||
|
const num_points = 5 + Math.floor(Math.random() * 3);
|
||||||
|
const angle = Math.PI / num_points;
|
||||||
|
context.beginPath();
|
||||||
|
for (let idx = 0; idx < num_points; idx++) {
|
||||||
|
const angle_offset = (idx * 2 * Math.PI) / num_points;
|
||||||
|
const outer_x = x + radius * Math.cos(angle_offset);
|
||||||
|
const outer_y = y + radius * Math.sin(angle_offset);
|
||||||
|
context.lineTo(outer_x, outer_y);
|
||||||
|
/* Inner points for star shape */
|
||||||
|
const inner_radius = radius / 2 + Math.random() * 0.2;
|
||||||
|
const inner_x = x + inner_radius * Math.cos(angle_offset + angle);
|
||||||
|
const inner_y = y + inner_radius * Math.sin(angle_offset + angle);
|
||||||
|
context.lineTo(inner_x, inner_y);
|
||||||
|
}
|
||||||
|
context.closePath();
|
||||||
|
context.fillStyle = `rgba(255, 255, 180, ${alpha})`;
|
||||||
|
context.fill();
|
||||||
|
}
|
||||||
|
/* Function to generate star background */
|
||||||
|
function generate_stars() {
|
||||||
|
const { width, height } = canvas_element;
|
||||||
|
const star_count = Math.floor(width * height * star_spread);
|
||||||
|
const corner = get_corner(width, height);
|
||||||
|
stars = [];
|
||||||
|
for (let idx = 0; idx < star_count; idx++) {
|
||||||
|
const base_random = seeded_random(idx * magic[0]);
|
||||||
|
/* Uniform random position */
|
||||||
|
const raw_x = seeded_random(base_random * magic[1]) * width;
|
||||||
|
const raw_y = seeded_random(base_random * magic[2]) * height;
|
||||||
|
/* Calculate distance from the corner to control concentration */
|
||||||
|
const dx = raw_x - corner.x;
|
||||||
|
const dy = raw_y - corner.y;
|
||||||
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
/* Apply exponential falloff based on distance (closer = more likely to be drawn) */
|
||||||
|
const max_distance = Math.sqrt(width * width + height * height);
|
||||||
|
const weight = Math.exp(
|
||||||
|
-concentration_strength * (distance / max_distance),
|
||||||
|
);
|
||||||
|
/* Skip stars that don't meet the concentration threshold */
|
||||||
|
if (seeded_random(base_random * magic[3]) > weight) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Randomized star properties */
|
||||||
|
const radius =
|
||||||
|
seeded_random(base_random * magic[4]) * star_range +
|
||||||
|
0.4 +
|
||||||
|
Math.random() * 0.2;
|
||||||
|
const twinkle_speed =
|
||||||
|
seeded_random(base_random * magic[5]) * 1.5 + 0.3;
|
||||||
|
const twinkle_phase =
|
||||||
|
seeded_random(base_random * magic[6]) * Math.PI * 2;
|
||||||
|
stars.push({
|
||||||
|
x: raw_x,
|
||||||
|
y: raw_y,
|
||||||
|
radius,
|
||||||
|
twinkle_speed,
|
||||||
|
twinkle_phase,
|
||||||
|
original_radius: radius,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Resize canvas and regenerate stars on window resize */
|
||||||
|
function resize_canvas() {
|
||||||
|
canvas_element.width = window.innerWidth;
|
||||||
|
canvas_element.height = window.innerHeight;
|
||||||
|
generate_stars();
|
||||||
|
}
|
||||||
|
window.addEventListener("resize", resize_canvas);
|
||||||
|
resize_canvas();
|
||||||
|
/* Handle mouse/touch movement effects */
|
||||||
|
function handle_interaction(event) {
|
||||||
|
if (event.touches) {
|
||||||
|
mouse_x = event.touches[0].clientX;
|
||||||
|
mouse_y = event.touches[0].clientY;
|
||||||
|
} else {
|
||||||
|
mouse_x = event.clientX;
|
||||||
|
mouse_y = event.clientY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener("mousemove", handle_interaction);
|
||||||
|
window.addEventListener("touchmove", handle_interaction);
|
||||||
|
/* Animate stars (twinke) */
|
||||||
|
function animate() {
|
||||||
|
time += 0.01;
|
||||||
|
const { width, height } = canvas_element;
|
||||||
|
context.fillStyle = "#0e0016";
|
||||||
|
context.fillRect(0, 0, width, height);
|
||||||
|
for (const star of stars) {
|
||||||
|
const twinkle = Math.sin(
|
||||||
|
time * star.twinkle_speed + star.twinkle_phase,
|
||||||
|
);
|
||||||
|
let alpha = 0.6 + twinkle_intensity * (0.5 + 0.5 * twinkle);
|
||||||
|
/* Interaction effect based on mouse/touch proximity */
|
||||||
|
if (mouse_x !== -1 && mouse_y !== -1) {
|
||||||
|
const dx = mouse_x - star.x;
|
||||||
|
const dy = mouse_y - star.y;
|
||||||
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
if (distance < interaction_radius) {
|
||||||
|
const effect = Math.max(
|
||||||
|
0,
|
||||||
|
1 - distance / interaction_radius,
|
||||||
|
);
|
||||||
|
alpha *=
|
||||||
|
1 +
|
||||||
|
effect *
|
||||||
|
interaction_brightness_factor; /* Make the star brighter */
|
||||||
|
star.radius =
|
||||||
|
star.original_radius *
|
||||||
|
(1 +
|
||||||
|
effect *
|
||||||
|
interaction_size_factor); /* Grow the star size */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_star(star.x, star.y, star.radius, alpha);
|
||||||
|
}
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
animate();
|
||||||
|
}
|
||||||
|
function base_main() {
|
||||||
|
const night = document.getElementById("night");
|
||||||
|
create_night(night);
|
||||||
|
}
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
base_main();
|
||||||
|
});
|
||||||
74
index.html
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="og:url" content="https://purplebored.pl/" />
|
||||||
|
<meta name="og:title" content="Purplebored.pl" />
|
||||||
|
<meta name="og:description" content="Just my personal website where I share cool stuff, the things I like, and the things I do :D" />
|
||||||
|
<meta name="description" content="Just my personal website :-)" />
|
||||||
|
<meta name="keywords" content="purplebored, poland, polish, personal website, website, buttons, niko, self-hosted, open source, foss, murder drones, tobacco, md, nicotine" />
|
||||||
|
<meta name="color-scheme" content="dark" />
|
||||||
|
<meta name="theme-color" content="black" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="assets/css/style.css">
|
||||||
|
<title>Purplebored</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>Purplebored.pl</h1>
|
||||||
|
<p>Hi, I am Purplebored, o/ also known as Niko. Right now you are on my own little website which I call my home on the World Wide Web! </p>
|
||||||
|
|
||||||
|
<p>I like making simple websites, and I am also a privacy advocate. I also love tobacco, and I am a big nicotine addict. I speak Polish and English, but I am also learning Russian. Regarding programming, I currently only know basic HTML. From other stuff, I also know some Linux and quite a lot about Windows — especially the older versions like Windows 7.</p>
|
||||||
|
|
||||||
|
<!-- Badges / Buttons / 88x31s -->
|
||||||
|
<div class="buttons">
|
||||||
|
<a href="https://purplebored.pl/" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/Purplebored_button.png" alt="Purplebored button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://unpato.neocities.org/" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/unpato.png" alt="Unpato writing button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://eclipse.cx" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/eclipsecx.png" alt="Eclipse Community button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://aagaming.me/" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/aagaming.png" alt="AAgaming button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://themcgovern.net" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/mcneb10.gif" alt="Mcneb10 button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://moody.im/" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/georgemoody.png" alt="Georgemoody button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://xameren.fsky.io" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/xameren.png" alt="Xameren button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://fsky.io" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/fsky_night.png" alt="FSKY.io button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://ari.lt/" title="ari-web badge" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/ari.png" alt="ari-web badge" />
|
||||||
|
</a>
|
||||||
|
<a href="https://telepath.im" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/telepath.png" alt="Telepath.im button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://aleksey-kon-games.fsky.io/" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/aleksey.png" alt="Aleksey Kon Games button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://k327.eu/" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/k327.png" alt="k327.eu button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://vaporwavefox.neocities.org" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/trace.png" alt="Trace button" />
|
||||||
|
</a>
|
||||||
|
<a href="https://authenyo.xyz" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/authen.gif" alt="Authen button" />
|
||||||
|
</a>
|
||||||
|
<a href="http://[300:5506:25eb:d0d9::]" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="assets/images/buttons/midgard.png" alt="Midgard button" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<canvas id="night"></canvas>
|
||||||
|
<script src="assets/js/script.js" defer></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||