add 38c3 theming
This commit is contained in:
parent
03c801ecc5
commit
13f6399fc0
@ -127,8 +127,8 @@
|
|||||||
"group": 2
|
"group": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "source code",
|
"name": "source code (38c3 branch)",
|
||||||
"href": "https://git.brulijam.com/brulijam/introduction-website",
|
"href": "https://git.brulijam.com/brulijam/introduction-website/src/branch/38c3-theme",
|
||||||
"group": "footer"
|
"group": "footer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
154
src/css/main.css
154
src/css/main.css
@ -1,22 +1,45 @@
|
|||||||
/* Root Variables */
|
/* Root Variables */
|
||||||
:root {
|
:root {
|
||||||
--bg-color: rgb(15, 15, 15);
|
|
||||||
--primary: rgb(240, 240, 240);
|
|
||||||
--secondary-color: hsl(210, 80%, 80%);
|
|
||||||
--secondary-color2: hsl(210, 60%, 40%);
|
|
||||||
--secondary-color-bg: hsl(210, 40%, 5%);
|
|
||||||
--font-weight: 350;
|
--font-weight: 350;
|
||||||
--font-family: "Lucida Console";
|
--font-family: 'space-mono';
|
||||||
--bigger-font-weight: 700;
|
--bigger-font-weight: 700;
|
||||||
--link-border-radius: 1000px;
|
--link-border-radius: 1000px;
|
||||||
--page-max-width: 700px;
|
--page-max-width: 700px;
|
||||||
|
|
||||||
|
--color-primary: #FF5053;
|
||||||
|
--color-highlight: #FEF2FF;
|
||||||
|
--color-accent-a: #B2AAFF;
|
||||||
|
--color-accent-b: #6A5FDB;
|
||||||
|
--color-accent-c: #29114C;
|
||||||
|
--color-accent-d: #261A66;
|
||||||
|
--color-accent-e: #190B2F;
|
||||||
|
--color-background: #0F000A;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'pilowlava';
|
||||||
|
/*src: URL('../fonts/pilowlava/Fonts/webfonts/Pilowlava-Regular.woff2') format('woff2');*/
|
||||||
|
src: url('../fonts/pilowlava/Fonts/webfonts/Pilowlava-Regular.woff2') format('woff2');
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'spacegrotesk';
|
||||||
|
src: url('../fonts/space-grotesk-1.1.4/webfont/SpaceGrotesk-Regular.woff2') format('woff2');
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'space-mono';
|
||||||
|
src: url('../fonts/space-mono/SpaceMono-Regular.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'uncut-sans';
|
||||||
|
src: url('../fonts/uncut-sans/Webfonts/UncutSans-Regular.woff2') format('woff2');
|
||||||
}
|
}
|
||||||
|
|
||||||
/* General Styles */
|
/* General Styles */
|
||||||
body {
|
body {
|
||||||
background-color: var(--secondary-color-bg);
|
background-color: var(--color-background);
|
||||||
color: var(--primary);
|
color: var(--color-accent-a);
|
||||||
/*color: var(--primary);*/
|
|
||||||
font-family: var(--font-family), monospace;
|
font-family: var(--font-family), monospace;
|
||||||
font-weight: var(--font-weight);
|
font-weight: var(--font-weight);
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
@ -31,23 +54,59 @@ h1, p {
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 2;
|
||||||
max-width: var(--page-max-width);
|
max-width: var(--page-max-width);
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
filter: drop-shadow(0 0 2px var(--secondary-color)) brightness(1);
|
/*filter: drop-shadow(0 0 2px var(--color-primary)) brightness(1);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
color: var(--bg-color);
|
color: var(--color-background);
|
||||||
background: var(--secondary-color);
|
background: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 38c3 */
|
||||||
|
.blobs {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1; /* Keep the container behind all content */
|
||||||
|
pointer-events: none; /* Prevent interaction */
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blobs img {
|
||||||
|
pointer-events: none; /* Ensure the images don't block anything */
|
||||||
|
will-change: transform; /* Improve performance for animations */
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -2; /* Ensure the grid is behind the blobs */
|
||||||
|
display: grid;
|
||||||
|
pointer-events: none; /* Prevent interaction */
|
||||||
|
opacity: 0.5;
|
||||||
|
background-image: linear-gradient(var(--color-accent-e) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, var(--color-accent-e) 1px, transparent 1px);
|
||||||
|
background-size: 60px 60px; /* Adjust the grid spacing */
|
||||||
|
background-color: var(--color-background); /* Base color for the grid */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Header Styles */
|
/* Header Styles */
|
||||||
header {
|
header {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
/*background-color: var(--color-background);*/
|
||||||
|
/*border: 1px var(--color-accent-e) solid;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
header .names {
|
header .names {
|
||||||
@ -57,7 +116,14 @@ header .names {
|
|||||||
|
|
||||||
header h1, header p {
|
header h1, header p {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: var(--secondary-color);
|
font-size: 35px;
|
||||||
|
color: var(--color-primary);
|
||||||
|
font-family: pilowlava, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
header p {
|
||||||
|
font-family: space-mono, monospace;
|
||||||
|
font-size: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
header img {
|
header img {
|
||||||
@ -66,10 +132,24 @@ header img {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Description */
|
||||||
|
header, .description, .linkGroup, .timer, footer {
|
||||||
|
background-color: rgba(15, 0, 10, 0.9);
|
||||||
|
/*border: 1px var(--color-primary) solid;*/
|
||||||
|
border: 1px var(--color-accent-c) solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
header, .description, .linkGroup, .timer {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Links Styles */
|
/* Links Styles */
|
||||||
h2 {
|
h2 {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
font-size: 30px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
color: var(--color-accent-a);
|
||||||
|
font-family: pilowlava, monospace;
|
||||||
|
|
||||||
@media only screen and (max-width: 480px) {
|
@media only screen and (max-width: 480px) {
|
||||||
text-align: center; /* slim */
|
text-align: center; /* slim */
|
||||||
@ -77,7 +157,7 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (min-width: 480px) {
|
@media only screen and (min-width: 480px) {
|
||||||
text-align: left; /* wide */
|
text-align: center; /* wide */
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +171,7 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.text-link {
|
.text-link {
|
||||||
color: var(--secondary-color);
|
color: var(--color-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
@ -100,13 +180,13 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.text-link:hover {
|
.text-link:hover {
|
||||||
filter: drop-shadow(0 0 5px var(--secondary-color2)) brightness(1.02);
|
filter: drop-shadow(0 0 5px var(--color-primary)) brightness(1.02);
|
||||||
top: -2px;
|
top: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Links Container */
|
/* Links Container */
|
||||||
.links {
|
.links {
|
||||||
padding: 0 10px;
|
padding: 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Link Group */
|
/* Link Group */
|
||||||
@ -119,6 +199,11 @@ h2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.linkGroup * {
|
||||||
|
color: var(--color-accent-a);
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Link Styles */
|
/* Link Styles */
|
||||||
.link {
|
.link {
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
@ -142,8 +227,8 @@ h2 {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-transform: lowercase;
|
text-transform: lowercase;
|
||||||
color: var(--bg-color);
|
color: var(--color-background);
|
||||||
background-color: var(--secondary-color);
|
background-color: var(--color-primary);
|
||||||
display: block;
|
display: block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
@ -152,6 +237,7 @@ h2 {
|
|||||||
|
|
||||||
@media only screen and (min-width: 480px) {
|
@media only screen and (min-width: 480px) {
|
||||||
width: auto; /* wide */
|
width: auto; /* wide */
|
||||||
|
padding: 5px 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +252,7 @@ h2 {
|
|||||||
/* Default Hover Effect */
|
/* Default Hover Effect */
|
||||||
.hoverHighlight:hover {
|
.hoverHighlight:hover {
|
||||||
@media only screen and (min-width: 480px) {
|
@media only screen and (min-width: 480px) {
|
||||||
filter: drop-shadow(0 0 8px var(--secondary-color)) brightness(1.1);
|
filter: drop-shadow(0 0 8px var(--color-primary)) brightness(1.1);
|
||||||
top: -2px;
|
top: -2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,7 +264,7 @@ h2 {
|
|||||||
|
|
||||||
/* Search Highlighting */
|
/* Search Highlighting */
|
||||||
.highlightSearch {
|
.highlightSearch {
|
||||||
filter: drop-shadow(0 0 8px var(--secondary-color)) brightness(1.1);
|
filter: drop-shadow(0 0 8px var(--color-primary)) brightness(1.1);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
@media only screen and (min-width: 480px) {
|
@media only screen and (min-width: 480px) {
|
||||||
top: -2px;
|
top: -2px;
|
||||||
@ -206,9 +292,9 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#link-search {
|
#link-search {
|
||||||
background-color: var(--secondary-color2);
|
background-color: var(--color-background);
|
||||||
color: var(--secondary-color);
|
color: var(--color-accent-a);
|
||||||
border: 2px solid var(--secondary-color2);
|
border: 2px solid var(--color-primary);
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -221,21 +307,21 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#link-search::placeholder {
|
#link-search::placeholder {
|
||||||
color: var(--secondary-color);
|
color: var(--color-accent-a);
|
||||||
opacity: 0.9; /* Placeholder text opacity */
|
opacity: 0.9; /* Placeholder text opacity */
|
||||||
}
|
}
|
||||||
|
|
||||||
#link-search:focus::placeholder {
|
#link-search:focus::placeholder {
|
||||||
color: var(--secondary-color);
|
color: var(--color-accent-e);
|
||||||
opacity: 0.9; /* Placeholder text opacity */
|
opacity: 0.9; /* Placeholder text opacity */
|
||||||
}
|
}
|
||||||
|
|
||||||
#link-search:focus {
|
#link-search:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
background-color: var(--secondary-color-bg);
|
background-color: var(--color-background);
|
||||||
box-shadow: 0 0 10px var(--secondary-color);
|
box-shadow: 0 0 10px var(--color-primary);
|
||||||
border-color: var(--secondary-color2);
|
border-color: var(--color-primary);
|
||||||
color: var(--secondary-color);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 480px) {
|
@media only screen and (max-width: 480px) {
|
||||||
@ -252,6 +338,9 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Timers Styles */
|
/* Timers Styles */
|
||||||
|
.timer {
|
||||||
|
}
|
||||||
|
|
||||||
.timer p {
|
.timer p {
|
||||||
@media only screen and (max-width: 480px) {
|
@media only screen and (max-width: 480px) {
|
||||||
margin-bottom: 20px; /* slim */
|
margin-bottom: 20px; /* slim */
|
||||||
@ -259,7 +348,8 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.timer p span {
|
.timer p span {
|
||||||
color: var(--secondary-color);
|
color: var(--color-primary);
|
||||||
|
/*color: var(--color-primary);*/
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
<title>Julian Brammer</title>
|
<title>Julian Brammer</title>
|
||||||
<link rel="stylesheet" href="css/main.css">
|
<link rel="stylesheet" href="css/main.css">
|
||||||
<link rel="me" href="https://social.brulijam.com/@brulijam">
|
<link rel="me" href="https://social.brulijam.com/@brulijam">
|
||||||
<script src="js/main.js"></script>
|
<!-- <script src="js/main.js"></script>-->
|
||||||
<script src="js/fuzzysearch.js" type="module"></script>
|
<script src="js/fuzzysearch.js" type="module"></script>
|
||||||
<script src="js/links.js"></script>
|
<script src="js/links.js"></script>
|
||||||
<script src="js/timer.js"></script>
|
<script src="js/timer.js"></script>
|
||||||
|
<script src="js/background.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
|
105
src/js/background.js
Normal file
105
src/js/background.js
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
function getRandomInt(min, max) {
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateGridPositions(rows, cols) {
|
||||||
|
const positions = [];
|
||||||
|
for (let row = 0; row < rows; row++) {
|
||||||
|
for (let col = 0; col < cols; col++) {
|
||||||
|
const top = (row + 0.5) * (100 / rows);
|
||||||
|
const left = (col + 0.5) * (100 / cols);
|
||||||
|
positions.push({ top, left });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRandomPosition(availablePositions) {
|
||||||
|
const index = Math.floor(Math.random() * availablePositions.length);
|
||||||
|
return availablePositions.splice(index, 1)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBlob(blobContainer, type, fileName, zIndex, position) {
|
||||||
|
const blob = document.createElement('img');
|
||||||
|
blob.src = `assets/blobs/${fileName}`;
|
||||||
|
blob.classList.add(type);
|
||||||
|
|
||||||
|
const randomRotation = getRandomInt(0, 360);
|
||||||
|
|
||||||
|
// blob.style.top = `${Math.random() * 100}%`;
|
||||||
|
// blob.style.left = `${Math.random() * 100}%`;
|
||||||
|
blob.style.top = `${position.top}%`;
|
||||||
|
blob.style.left = `${position.left}%`;
|
||||||
|
blob.style.transform = `translate(-50%, -50%) rotate(${randomRotation}deg)`;
|
||||||
|
blob.style.position = 'absolute';
|
||||||
|
blob.style.maxWidth = '300%';
|
||||||
|
blob.style.opacity = type === 'line' ? '0.5' : '0.8';
|
||||||
|
blob.style.zIndex = zIndex;
|
||||||
|
|
||||||
|
blob.dataset.rotation = randomRotation;
|
||||||
|
blobContainer.appendChild(blob);
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
function adjustBlobCount() {
|
||||||
|
const width = window.innerWidth;
|
||||||
|
const height = window.innerHeight;
|
||||||
|
const baseCount = 5;
|
||||||
|
const widthFactor = Math.max(1, Math.floor(width / 400));
|
||||||
|
const heightFactor = Math.max(1, Math.floor(height / 600));
|
||||||
|
const totalCount = Math.min(baseCount * widthFactor, baseCount * heightFactor);
|
||||||
|
|
||||||
|
const solidsCount = Math.max(1, Math.floor(totalCount * 0.5));
|
||||||
|
const linesCount = totalCount - solidsCount;
|
||||||
|
|
||||||
|
return { solidsCount, linesCount };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const grid = document.createElement('div');
|
||||||
|
grid.classList.add('grid');
|
||||||
|
document.body.prepend(grid);
|
||||||
|
|
||||||
|
const blobContainer = document.createElement('div');
|
||||||
|
blobContainer.classList.add('blobs');
|
||||||
|
document.body.prepend(blobContainer);
|
||||||
|
|
||||||
|
const { solidsCount, linesCount } = adjustBlobCount();
|
||||||
|
let zIndexCounter = 1;
|
||||||
|
|
||||||
|
const gridSize = Math.ceil(Math.sqrt(solidsCount + linesCount));
|
||||||
|
const positions = generateGridPositions(gridSize, gridSize);
|
||||||
|
|
||||||
|
for (let i = 0; i < solidsCount; i++) {
|
||||||
|
const x = getRandomInt(1, 13);
|
||||||
|
const position = getRandomPosition(positions);
|
||||||
|
createBlob(blobContainer,'solid', `blob-freeform-${x}_filled.svg`, zIndexCounter, position);
|
||||||
|
zIndexCounter += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < linesCount; i++) {
|
||||||
|
const x = getRandomInt(1, 13);
|
||||||
|
const position = getRandomPosition(positions);
|
||||||
|
const color = Math.random() > 0.5 ? '_red' : '';
|
||||||
|
createBlob(blobContainer, 'line', `blob-freeform-${x}${color}.svg`, zIndexCounter - 1, position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', (event) => {
|
||||||
|
const elements = [...document.querySelectorAll('.solid, .line')];
|
||||||
|
const { clientX: mouseX, clientY: mouseY } = event;
|
||||||
|
const { innerWidth: width, innerHeight: height } = window;
|
||||||
|
|
||||||
|
const xOffset = (mouseX / width - 0.5) * 200;
|
||||||
|
const yOffset = (mouseY / height - 0.5) * 200;
|
||||||
|
|
||||||
|
elements.forEach((element, i) => {
|
||||||
|
const strength = element.classList.contains('solid') ? 5 + i * 3 : 1 + i * 0.5;
|
||||||
|
const rotation = element.dataset.rotation || 0;
|
||||||
|
element.style.transform = `translate(-50%, -50%) translate(${xOffset / strength}px, ${yOffset / strength}px) rotate(${rotation}deg)`;
|
||||||
|
});
|
||||||
|
});
|
103
src/js/blobs.js
Normal file
103
src/js/blobs.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// Add the grid element to the body
|
||||||
|
const grid = document.createElement('div');
|
||||||
|
grid.classList.add('grid');
|
||||||
|
document.body.prepend(grid); // Add grid to the very back
|
||||||
|
|
||||||
|
const container = document.createElement('div');
|
||||||
|
container.classList.add('blobs'); // Use "blobs" as the container class
|
||||||
|
document.body.prepend(container);
|
||||||
|
|
||||||
|
// Function to get a weighted random value favoring edges
|
||||||
|
const getEdgeBiasedRandom = () => {
|
||||||
|
const rand = Math.random(); // Random number between 0 and 1
|
||||||
|
if (rand < 0.5) {
|
||||||
|
// Favor edges (closer to 10% or 90%)
|
||||||
|
return Math.random() < 0.5 ? getRandomInt(5, 25) : getRandomInt(75, 95);
|
||||||
|
} else {
|
||||||
|
// Occasionally place blobs elsewhere (30-70%)
|
||||||
|
return getRandomInt(25, 75);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to get a random integer between min and max (inclusive)
|
||||||
|
const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
|
||||||
|
// Function to adjust the number of blobs based on window size
|
||||||
|
const adjustBlobCount = () => {
|
||||||
|
const width = window.innerWidth;
|
||||||
|
const height = window.innerHeight;
|
||||||
|
|
||||||
|
// Base number of blobs, and scale based on window width and height
|
||||||
|
const baseCount = 5;
|
||||||
|
const widthMultiplier = Math.max(1, Math.floor(width / 500)); // Increase blobs per 500px width
|
||||||
|
const heightMultiplier = Math.max(1, Math.floor(height / 500)); // Increase blobs per 400px height
|
||||||
|
|
||||||
|
const totalCount = Math.min(baseCount * widthMultiplier, baseCount * heightMultiplier);
|
||||||
|
|
||||||
|
// Return number of solids and lines based on adjusted total count
|
||||||
|
const NUM_SOLIDS = Math.max(1, Math.floor(totalCount * 0.3)); // 30% solids
|
||||||
|
const NUM_LINES = totalCount - NUM_SOLIDS; // The rest are lines
|
||||||
|
|
||||||
|
return { NUM_SOLIDS, NUM_LINES };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the number of blobs based on the window size
|
||||||
|
const { NUM_SOLIDS, NUM_LINES } = adjustBlobCount();
|
||||||
|
|
||||||
|
// Create and position blobs with distinct z-index layers
|
||||||
|
let zIndexCounter = 1; // Start z-index at 1 to avoid overlap with default content
|
||||||
|
|
||||||
|
// Randomly select and create solids (background blobs)
|
||||||
|
for (let i = 0; i < NUM_SOLIDS; i++) {
|
||||||
|
const x = getRandomInt(1, 13); // Randomly pick a blob design
|
||||||
|
createBlob('background-blob', `blob-freeform-${x}_filled.svg`, zIndexCounter);
|
||||||
|
zIndexCounter += 2; // Increment by 2 to leave gaps for lines
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomly select and create lines (foreground blobs)
|
||||||
|
for (let i = 0; i < NUM_LINES; i++) {
|
||||||
|
const x = getRandomInt(1, 13); // Randomly pick a blob design
|
||||||
|
const color = Math.random() > 0.5 ? '_red' : ''; // 50% chance to pick the red variant
|
||||||
|
createBlob('background-line', `blob-freeform-${x}${color}.svg`, zIndexCounter - 1); // Ensure lines fit between solids
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to create and position a blob
|
||||||
|
function createBlob(type, fileName, zIndex) {
|
||||||
|
const blob = document.createElement('img');
|
||||||
|
blob.src = `assets/blobs/${fileName}`; // Corrected path to assets folder
|
||||||
|
blob.classList.add(type);
|
||||||
|
blob.style.top = `${getEdgeBiasedRandom()}%`; // Use edge-biased random for top
|
||||||
|
blob.style.left = `${getEdgeBiasedRandom()}%`; // Use edge-biased random for left
|
||||||
|
blob.style.transform = `translate(-50%, -50%)`;
|
||||||
|
blob.style.position = 'absolute';
|
||||||
|
blob.style.maxWidth = '300%'; // Adjust size
|
||||||
|
blob.style.opacity = type === 'background-line' ? '0.5' : '0.8'; // More transparent for lines
|
||||||
|
blob.style.zIndex = zIndex; // Set z-index dynamically
|
||||||
|
container.appendChild(blob);
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add mouse movement effect
|
||||||
|
document.addEventListener('mousemove', (event) => {
|
||||||
|
const blobs = document.querySelectorAll('.background-blob');
|
||||||
|
const lines = document.querySelectorAll('.background-line');
|
||||||
|
|
||||||
|
const { clientX: mouseX, clientY: mouseY } = event;
|
||||||
|
const { innerWidth: width, innerHeight: height } = window;
|
||||||
|
|
||||||
|
// Stronger movement scaling factors
|
||||||
|
const xOffset = (mouseX / width - 0.5) * 100; // Amplified to 100 for stronger movements
|
||||||
|
const yOffset = (mouseY / height - 0.5) * 100;
|
||||||
|
|
||||||
|
blobs.forEach((blob, i) => {
|
||||||
|
const strength = 3 + i; // Reduce divisor for stronger movements
|
||||||
|
blob.style.transform = `translate(-50%, -50%) translate(${xOffset / strength}px, ${yOffset / strength}px)`;
|
||||||
|
});
|
||||||
|
|
||||||
|
lines.forEach((line, i) => {
|
||||||
|
const strength = 2 + i * 0.5; // Even stronger for lines
|
||||||
|
line.style.transform = `translate(-50%, -50%) translate(${xOffset / strength}px, ${yOffset / strength}px)`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user