Added spark animations to main logo
This commit is contained in:
parent
45224fd9c8
commit
4a491d2d72
8 changed files with 143 additions and 15 deletions
|
|
@ -166,3 +166,15 @@ article video {
|
|||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Main page logo with programmatically generated sparks */
|
||||
body:has(.background-container) article.glass figure:first-of-type {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
body:has(.background-container) article.glass figure:first-of-type img {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
118
assets/js/logo-sparks.js
Normal file
118
assets/js/logo-sparks.js
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
// Programmatic spark generation for homepage logo
|
||||
(function() {
|
||||
const config = {
|
||||
numSparks: 9,
|
||||
minSize: 1.5,
|
||||
maxSize: 3.5,
|
||||
minRadius: 180,
|
||||
maxRadius: 350,
|
||||
minDuration: 23,
|
||||
maxDuration: 49,
|
||||
pathComplexity: 17,
|
||||
behindLogoFraction: 0.75,
|
||||
minOpacity: 0.5,
|
||||
maxOpacity: 0.8,
|
||||
staggerAnimations: true
|
||||
};
|
||||
|
||||
function random(min, max) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
function generatePath(radius, complexity) {
|
||||
const points = [];
|
||||
for (let i = 0; i <= complexity; i++) {
|
||||
const angle = (i / complexity) * Math.PI * 2;
|
||||
const r = random(radius * 0.8, radius * 1.2);
|
||||
const x = Math.cos(angle) * r + random(-50, 50);
|
||||
const y = Math.sin(angle) * r + random(-50, 50);
|
||||
points.push({ x, y, scale: random(0.7, 1.3) });
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
function createKeyframes(id, path, isBehind) {
|
||||
const steps = path.length;
|
||||
let keyframes = '@keyframes spark' + id + ' {\n';
|
||||
|
||||
path.forEach((point, i) => {
|
||||
const percent = (i / (steps - 1)) * 100;
|
||||
const opacity = (i > 1 && i < steps - 2) ? random(config.minOpacity, config.maxOpacity) : 0;
|
||||
|
||||
let opacityValue = opacity;
|
||||
if (isBehind) {
|
||||
const hiddenStart = random(30, 45);
|
||||
const hiddenEnd = random(55, 70);
|
||||
if (percent > hiddenStart && percent < hiddenEnd) {
|
||||
opacityValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
keyframes += ` ${percent.toFixed(1)}% {\n`;
|
||||
keyframes += ` transform: translate(-50%, -50%) translateX(${point.x.toFixed(1)}px) translateY(${point.y.toFixed(1)}px) scale(${point.scale.toFixed(2)});\n`;
|
||||
keyframes += ` opacity: ${opacityValue.toFixed(2)};\n`;
|
||||
keyframes += ` }\n`;
|
||||
});
|
||||
|
||||
keyframes += '}\n';
|
||||
return keyframes;
|
||||
}
|
||||
|
||||
function initSparks() {
|
||||
const logoFigure = document.querySelector('body:has(.background-container) article.glass figure:first-of-type');
|
||||
if (!logoFigure) return;
|
||||
|
||||
let allKeyframes = '';
|
||||
const sparks = [];
|
||||
|
||||
for (let i = 0; i < config.numSparks; i++) {
|
||||
const spark = document.createElement('span');
|
||||
spark.className = 'logo-spark';
|
||||
spark.dataset.sparkId = i;
|
||||
|
||||
const size = random(config.minSize, config.maxSize);
|
||||
const duration = random(config.minDuration, config.maxDuration);
|
||||
const radius = random(config.minRadius, config.maxRadius);
|
||||
const isBehind = Math.random() < config.behindLogoFraction;
|
||||
|
||||
const delay = config.staggerAnimations
|
||||
? random(0, config.maxDuration)
|
||||
: 0;
|
||||
|
||||
spark.style.cssText = `
|
||||
position: absolute;
|
||||
width: ${size}px;
|
||||
height: ${size}px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(255, 255, 255, 0.9), rgba(74, 158, 255, 0.6), transparent);
|
||||
box-shadow: 0 0 8px rgba(74, 158, 255, 0.8), 0 0 4px rgba(255, 255, 255, 0.6);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
pointer-events: none;
|
||||
z-index: ${isBehind ? -1 : 1};
|
||||
animation: spark${i} ${duration}s linear infinite;
|
||||
animation-delay: -${delay.toFixed(2)}s;
|
||||
`;
|
||||
|
||||
const path = generatePath(radius, config.pathComplexity);
|
||||
allKeyframes += createKeyframes(i, path, isBehind);
|
||||
|
||||
sparks.push(spark);
|
||||
}
|
||||
|
||||
// Inject keyframes
|
||||
const style = document.createElement('style');
|
||||
style.textContent = allKeyframes;
|
||||
document.head.appendChild(style);
|
||||
|
||||
// Inject sparks
|
||||
sparks.forEach(spark => logoFigure.appendChild(spark));
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initSparks);
|
||||
} else {
|
||||
initSparks();
|
||||
}
|
||||
})();
|
||||
|
||||
|
|
@ -7,9 +7,6 @@ categories = ['USM', 'BlueIQ', "Acoustics"]
|
|||
tags = ['data science', 'KarstTech', 'sonar', 'TDOA']
|
||||
+++
|
||||
|
||||
Using low-cost AI enabled acoustic buoys to detect and track vessels
|
||||
<!--more-->
|
||||
|
||||
{{< katex >}}
|
||||
|
||||
# Summary of "Enhancing Maritime Domain Awareness Through AI-Enabled Acoustic Buoys"
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ categories = ['USM', 'magnetics']
|
|||
tags = ['data science', 'KarstTech', 'UUV', 'modeling', 'machine learning', 'AI']
|
||||
+++
|
||||
|
||||
Using machine learning to detect and localize magnetic targets underwater
|
||||
<!--more-->
|
||||
|
||||
{{< katex >}}
|
||||
|
||||
# Machine Learning for Target Classification and Localization
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ categories = ['USM', 'magnetics']
|
|||
tags = ['data science', 'KarstTech', 'UUV', 'modeling', 'machine learning', 'COMSOL']
|
||||
+++
|
||||
|
||||
Modeling magnetic targets to support machine learning applications in maritime environments
|
||||
<!--more-->
|
||||
|
||||
# Potential Fields Modeling to Support Machine Learning Applications in Maritime Environments
|
||||
|
||||
The summary below is from a published paper that I co-authored with my colleagues at USM Magnetics. If you would rather read the full paper, you can find it [here](https://www.comsol.com/paper/potential-fields-modeling-to-support-machine-learning-applications-in-maritime-environments-135922).
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ categories = ['USM', 'magnetics']
|
|||
tags = ['data science', 'KarstTech', 'modeling']
|
||||
+++
|
||||
|
||||
Estimating the position and magnetic moment of a dipole from a few field measurements
|
||||
<!--more-->
|
||||
|
||||
{{< katex >}}
|
||||
|
||||
# Magnetic Dipole Localization: Methods for Parametric Inversion
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@ categories = ['USM', 'magnetics']
|
|||
tags = ['data science', 'KarstTech', 'UUV', 'sensor fusion']
|
||||
+++
|
||||
|
||||
Combining data from multiple sensors to make them all more useful!
|
||||
<!--more-->
|
||||
|
||||
## Getting Started
|
||||
Several months ago I was referred to the University of Southern Mississippi [Marine Research Center](https://www.usm.edu/ocean-enterprise/marine-research-center.php) by a coworker. They wanted some assistance from someone with a physics and data science background to work on an autonomous underwater vehicle for the purpose of developing a magnetic sensing platform.
|
||||
|
||||
|
|
|
|||
13
layouts/partials/extend-head.html
Normal file
13
layouts/partials/extend-head.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{{ if .IsHome }}
|
||||
{{ $jsLogoSparks := resources.Get "js/logo-sparks.js" }}
|
||||
{{ if $jsLogoSparks }}
|
||||
{{ $jsLogoSparks = $jsLogoSparks | resources.Minify | resources.Fingerprint ($.Site.Params.fingerprintAlgorithm | default "sha256") }}
|
||||
<script
|
||||
defer
|
||||
type="text/javascript"
|
||||
src="{{ $jsLogoSparks.RelPermalink }}"
|
||||
integrity="{{ $jsLogoSparks.Data.Integrity }}"
|
||||
></script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
Loading…
Add table
Reference in a new issue