fix: remove dependency on gsap library (#5330)
gsap's highly limited use in this codebase can easily be achieved using the native JS Web Animations API.
This commit is contained in:
Generated
-7
@@ -38,7 +38,6 @@
|
|||||||
"electron-updater": "^6.6.2",
|
"electron-updater": "^6.6.2",
|
||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"gsap": "^3.13.0",
|
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lucide-react": "^0.546.0",
|
"lucide-react": "^0.546.0",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
@@ -11550,12 +11549,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/gsap": {
|
|
||||||
"version": "3.13.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/gsap/-/gsap-3.13.0.tgz",
|
|
||||||
"integrity": "sha512-QL7MJ2WMjm1PHWsoFrAQH/J8wUeqZvMtHO58qdekHpCfhvhSL4gSiz6vJf5EeMP0LOn3ZCprL2ki/gjED8ghVw==",
|
|
||||||
"license": "Standard 'no charge' license: https://gsap.com/standard-license."
|
|
||||||
},
|
|
||||||
"node_modules/handlebars": {
|
"node_modules/handlebars": {
|
||||||
"version": "4.7.8",
|
"version": "4.7.8",
|
||||||
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
||||||
|
|||||||
@@ -68,7 +68,6 @@
|
|||||||
"electron-updater": "^6.6.2",
|
"electron-updater": "^6.6.2",
|
||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"gsap": "^3.13.0",
|
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lucide-react": "^0.546.0",
|
"lucide-react": "^0.546.0",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { gsap } from 'gsap';
|
|
||||||
import SplitType from 'split-type';
|
import SplitType from 'split-type';
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
@@ -110,6 +109,8 @@ export class TextAnimator {
|
|||||||
textElement: HTMLElement;
|
textElement: HTMLElement;
|
||||||
splitter!: TextSplitter;
|
splitter!: TextSplitter;
|
||||||
originalChars!: string[];
|
originalChars!: string[];
|
||||||
|
activeAnimations: globalThis.Animation[] = [];
|
||||||
|
activeTimeouts: ReturnType<typeof setTimeout>[] = [];
|
||||||
|
|
||||||
constructor(textElement: HTMLElement) {
|
constructor(textElement: HTMLElement) {
|
||||||
if (!textElement || !(textElement instanceof HTMLElement)) {
|
if (!textElement || !(textElement instanceof HTMLElement)) {
|
||||||
@@ -124,7 +125,7 @@ export class TextAnimator {
|
|||||||
this.splitter = new TextSplitter(this.textElement, {
|
this.splitter = new TextSplitter(this.textElement, {
|
||||||
splitTypeTypes: ['words', 'chars'],
|
splitTypeTypes: ['words', 'chars'],
|
||||||
});
|
});
|
||||||
this.originalChars = this.splitter.getChars().map((char) => char.innerHTML);
|
this.originalChars = this.splitter.getChars().map((char) => char.textContent || '');
|
||||||
}
|
}
|
||||||
|
|
||||||
animate() {
|
animate() {
|
||||||
@@ -133,64 +134,83 @@ export class TextAnimator {
|
|||||||
const chars = this.splitter.getChars();
|
const chars = this.splitter.getChars();
|
||||||
|
|
||||||
chars.forEach((char, position) => {
|
chars.forEach((char, position) => {
|
||||||
const initialHTML = char.innerHTML;
|
const initialText = char.textContent || '';
|
||||||
let repeatCount = 0;
|
|
||||||
|
|
||||||
// Set initial state
|
char.style.opacity = '1';
|
||||||
gsap.set(char, {
|
char.style.display = 'inline-block';
|
||||||
opacity: 1,
|
char.style.position = 'relative';
|
||||||
display: 'inline-block',
|
|
||||||
position: 'relative',
|
|
||||||
});
|
|
||||||
|
|
||||||
gsap.fromTo(
|
const animation = char.animate(
|
||||||
char,
|
[
|
||||||
|
{
|
||||||
|
opacity: 1,
|
||||||
|
color: '#666',
|
||||||
|
fontFamily: 'Cash Sans Mono',
|
||||||
|
fontWeight: '300',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
opacity: 0.5,
|
||||||
|
color: '#999',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
opacity: 1,
|
||||||
|
color: 'inherit',
|
||||||
|
fontFamily: 'inherit',
|
||||||
|
fontWeight: 'inherit',
|
||||||
|
},
|
||||||
|
],
|
||||||
{
|
{
|
||||||
opacity: 1,
|
duration: 300, // Total duration for all iterations
|
||||||
},
|
easing: 'ease-in-out',
|
||||||
{
|
delay: position * 30, // Stagger the start of each animation
|
||||||
duration: 0.1, // Increased duration
|
iterations: 1,
|
||||||
ease: 'power2.out',
|
|
||||||
onStart: () => {
|
|
||||||
gsap.set(char, {
|
|
||||||
fontFamily: 'Cash Sans Mono',
|
|
||||||
fontWeight: 300,
|
|
||||||
color: '#666', // Add color change
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onComplete: () => {
|
|
||||||
gsap.set(char, {
|
|
||||||
innerHTML: initialHTML,
|
|
||||||
color: '',
|
|
||||||
fontFamily: '',
|
|
||||||
opacity: 1,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
repeat: 2, // Reduced repeats
|
|
||||||
onRepeat: () => {
|
|
||||||
repeatCount++;
|
|
||||||
if (repeatCount === 1) {
|
|
||||||
gsap.set(char, {
|
|
||||||
opacity: 0.5,
|
|
||||||
color: '#999',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
repeatRefresh: true,
|
|
||||||
repeatDelay: 0.05, // Increased delay
|
|
||||||
delay: position * 0.03, // Reduced delay between chars
|
|
||||||
innerHTML: () => lettersAndSymbols[Math.floor(Math.random() * lettersAndSymbols.length)],
|
|
||||||
opacity: 1,
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.activeAnimations.push(animation);
|
||||||
|
|
||||||
|
let iteration = 0;
|
||||||
|
const maxIterations = 2;
|
||||||
|
|
||||||
|
const animateCharacterChange = () => {
|
||||||
|
if (iteration < maxIterations) {
|
||||||
|
char.textContent =
|
||||||
|
lettersAndSymbols[Math.floor(Math.random() * lettersAndSymbols.length)];
|
||||||
|
const timeoutId = setTimeout(animateCharacterChange, 100);
|
||||||
|
this.activeTimeouts.push(timeoutId);
|
||||||
|
iteration++;
|
||||||
|
} else {
|
||||||
|
char.textContent = initialText;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const timeoutId = setTimeout(animateCharacterChange, position * 30);
|
||||||
|
this.activeTimeouts.push(timeoutId);
|
||||||
|
|
||||||
|
animation.onfinish = () => {
|
||||||
|
char.textContent = initialText;
|
||||||
|
char.style.color = '';
|
||||||
|
char.style.fontFamily = '';
|
||||||
|
char.style.opacity = '1';
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
|
// Clear all timeouts
|
||||||
|
this.activeTimeouts.forEach((timeoutId) => clearTimeout(timeoutId));
|
||||||
|
this.activeTimeouts = [];
|
||||||
|
|
||||||
|
// Cancel all animations
|
||||||
|
this.activeAnimations.forEach((animation) => animation.cancel());
|
||||||
|
this.activeAnimations = [];
|
||||||
|
|
||||||
|
// Reset text content
|
||||||
const chars = this.splitter.getChars();
|
const chars = this.splitter.getChars();
|
||||||
chars.forEach((char, index) => {
|
chars.forEach((char, index) => {
|
||||||
gsap.killTweensOf(char);
|
if (this.originalChars[index]) {
|
||||||
char.innerHTML = this.originalChars[index];
|
char.textContent = this.originalChars[index];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user