一些奇怪的更改

This commit is contained in:
2025-09-28 23:12:40 +08:00
parent b3a378bc79
commit d4af01a678
25 changed files with 5243 additions and 5072 deletions

View File

@@ -1,315 +1,315 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var gsap = require('gsap');
class CursorRainEffect {
constructor(options = {}) {
this.rainContainer = null;
this.drops = [];
this.isInitialized = false;
this.mouseMoveHandler = null;
this.timeoutId = null;
this.animationPool = [];
this.options = {
maxDrops: options.maxDrops ?? 50,
dropSize: options.dropSize ?? [2, 8],
color: options.color ?? 'rgba(173, 216, 230, 0.8)',
duration: options.duration ?? [0.8, 1.5],
delay: options.delay ?? 100,
enabled: options.enabled ?? true,
zIndex: options.zIndex ?? 9999,
container: options.container ?? document.body
};
this.container = this.options.container;
}
init() {
if (this.isInitialized) {
return;
}
this.createRainContainer();
this.setupEventListeners();
this.preCreateDrops();
this.isInitialized = true;
}
destroy() {
if (!this.isInitialized) {
return;
}
this.cleanup();
this.isInitialized = false;
}
enable() {
this.options.enabled = true;
if (this.isInitialized) {
this.setupEventListeners();
}
}
disable() {
this.options.enabled = false;
this.removeEventListeners();
}
updateOptions(newOptions) {
this.options = { ...this.options, ...newOptions };
if (newOptions.container && newOptions.container !== this.container) {
this.container = newOptions.container;
if (this.isInitialized) {
this.destroy();
this.init();
}
}
}
createRainContainer() {
this.rainContainer = document.createElement('div');
this.rainContainer.className = 'cursor-rain-container';
this.rainContainer.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
pointer-events: none;
z-index: ${this.options.zIndex};
overflow: hidden;
`;
this.container.appendChild(this.rainContainer);
}
preCreateDrops() {
// Pre-create drop elements for better performance
for (let i = 0; i < this.options.maxDrops; i++) {
const drop = this.createDropElement();
this.animationPool.push(drop);
if (this.rainContainer) {
this.rainContainer.appendChild(drop);
}
}
}
createDropElement() {
const drop = document.createElement('div');
drop.className = 'rain-drop';
drop.style.cssText = `
position: absolute;
background: ${this.options.color};
border-radius: 50% 50% 50% 50% / 90% 90% 10% 10%;
pointer-events: none;
opacity: 0;
transform-origin: center bottom;
`;
return drop;
}
setupEventListeners() {
if (!this.options.enabled) {
return;
}
this.removeEventListeners();
this.mouseMoveHandler = this.throttle((e) => {
this.createRainAtPosition(e.clientX, e.clientY);
}, 16); // ~60fps throttling
document.addEventListener('mousemove', this.mouseMoveHandler, { passive: true });
}
removeEventListeners() {
if (this.mouseMoveHandler) {
document.removeEventListener('mousemove', this.mouseMoveHandler);
this.mouseMoveHandler = null;
}
if (this.timeoutId) {
clearTimeout(this.timeoutId);
this.timeoutId = null;
}
}
createRainAtPosition(x, y) {
if (!this.rainContainer || this.drops.length >= this.options.maxDrops) {
return;
}
// Get available drop from pool
const dropElement = this.getAvailableDrop();
if (!dropElement) {
return;
}
const size = this.randomBetween(this.options.dropSize[0], this.options.dropSize[1]);
const duration = this.randomBetween(this.options.duration[0], this.options.duration[1]);
// Add some randomness to position
const offsetX = this.randomBetween(-20, 20);
const offsetY = this.randomBetween(-10, 10);
const finalX = x + offsetX;
const finalY = y + offsetY;
const drop = {
element: dropElement,
x: finalX,
y: finalY,
size,
isAnimating: true
};
this.drops.push(drop);
// Set initial position and size
gsap.gsap.set(dropElement, {
x: finalX - size / 4, // 调整X偏移因为宽度变小了
y: finalY - size / 2,
width: size * 0.3, // 宽度减小到原来的30%,让雨滴更细
height: size * 4, // 高度增加到4倍让雨滴更长
opacity: 0,
scaleY: 0.1,
rotation: this.randomBetween(-15, 15)
});
// Animate the raindrop - continuous fall with gradual rotation change
const initialRotation = this.randomBetween(-15, 15); // 初始随机角度
const fallDistance = window.innerHeight - finalY + 100;
const tl = gsap.gsap.timeline({
onComplete: () => {
this.returnDropToPool(drop);
}
});
// 快速出现
tl.to(dropElement, {
opacity: 1,
scaleY: 1,
duration: 0.1,
ease: 'power2.out'
})
// 连续下落:一次性完成整个下落过程,同时角度逐渐变垂直
.to(dropElement, {
y: `+=${fallDistance}`, // 一次性完成所有下落距离
x: `+=${initialRotation * 0.3}`, // 轻微的水平漂移
scaleY: 1.5, // 逐渐拉长
opacity: 0.3, // 逐渐变透明
rotation: 0, // 角度从初始角度平滑变为垂直
duration: duration,
ease: 'power1.in' // 重力加速效果
}, 0.05);
}
getAvailableDrop() {
return this.animationPool.find(drop => gsap.gsap.getTweensOf(drop).length === 0) || null;
}
returnDropToPool(drop) {
const index = this.drops.indexOf(drop);
if (index > -1) {
this.drops.splice(index, 1);
}
drop.isAnimating = false;
// Reset the element
gsap.gsap.set(drop.element, {
opacity: 0,
x: 0,
y: 0,
scaleY: 1,
rotation: 0
});
}
randomBetween(min, max) {
return Math.random() * (max - min) + min;
}
throttle(func, delay) {
let timeoutId = null;
let lastExecTime = 0;
return (...args) => {
const currentTime = Date.now();
if (currentTime - lastExecTime > delay) {
func(...args);
lastExecTime = currentTime;
}
else {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = window.setTimeout(() => {
func(...args);
lastExecTime = Date.now();
}, delay - (currentTime - lastExecTime));
}
};
}
cleanup() {
this.removeEventListeners();
// Kill all GSAP animations
this.drops.forEach(drop => {
gsap.gsap.killTweensOf(drop.element);
});
this.drops = [];
this.animationPool = [];
if (this.rainContainer && this.rainContainer.parentNode) {
this.rainContainer.parentNode.removeChild(this.rainContainer);
this.rainContainer = null;
}
}
}
/**
* Create a new cursor rain effect instance
*/
function createCursorRainEffect(options) {
return new CursorRainEffect(options);
}
/**
* Initialize cursor rain effect with default options
* This is a convenience function for quick setup
*/
function initCursorRain(options) {
const effect = createCursorRainEffect(options);
// Auto-initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
effect.init();
});
}
else {
// DOM is already ready
effect.init();
}
return effect;
}
/**
* VitePress compatible initialization
* This function ensures the effect works correctly in VitePress environment
*/
function initCursorRainForVitePress(options) {
const effect = createCursorRainEffect({
container: document.body,
zIndex: 1000, // Lower z-index to avoid conflicts with VitePress UI
...options
});
// Handle VitePress page navigation
const initEffect = () => {
// Small delay to ensure VitePress has finished rendering
setTimeout(() => {
effect.init();
}, 100);
};
// Handle both initial load and client-side navigation
if (typeof window !== 'undefined') {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initEffect);
}
else {
initEffect();
}
// Handle VitePress client-side navigation
window.addEventListener('popstate', () => {
effect.destroy();
initEffect();
});
// Handle programmatic navigation (if using Vue Router)
if (window.history && window.history.pushState) {
const originalPushState = window.history.pushState;
window.history.pushState = function (...args) {
originalPushState.apply(window.history, args);
effect.destroy();
initEffect();
};
}
}
return effect;
}
// Default export for convenience
var index = {
createCursorRainEffect,
initCursorRain,
initCursorRainForVitePress,
CursorRainEffect
};
exports.CursorRainEffect = CursorRainEffect;
exports.createCursorRainEffect = createCursorRainEffect;
exports.default = index;
exports.initCursorRain = initCursorRain;
exports.initCursorRainForVitePress = initCursorRainForVitePress;
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var gsap = require('gsap');
class CursorRainEffect {
constructor(options = {}) {
this.rainContainer = null;
this.drops = [];
this.isInitialized = false;
this.mouseMoveHandler = null;
this.timeoutId = null;
this.animationPool = [];
this.options = {
maxDrops: options.maxDrops ?? 50,
dropSize: options.dropSize ?? [2, 8],
color: options.color ?? 'rgba(173, 216, 230, 0.8)',
duration: options.duration ?? [0.8, 1.5],
delay: options.delay ?? 100,
enabled: options.enabled ?? true,
zIndex: options.zIndex ?? 9999,
container: options.container ?? document.body
};
this.container = this.options.container;
}
init() {
if (this.isInitialized) {
return;
}
this.createRainContainer();
this.setupEventListeners();
this.preCreateDrops();
this.isInitialized = true;
}
destroy() {
if (!this.isInitialized) {
return;
}
this.cleanup();
this.isInitialized = false;
}
enable() {
this.options.enabled = true;
if (this.isInitialized) {
this.setupEventListeners();
}
}
disable() {
this.options.enabled = false;
this.removeEventListeners();
}
updateOptions(newOptions) {
this.options = { ...this.options, ...newOptions };
if (newOptions.container && newOptions.container !== this.container) {
this.container = newOptions.container;
if (this.isInitialized) {
this.destroy();
this.init();
}
}
}
createRainContainer() {
this.rainContainer = document.createElement('div');
this.rainContainer.className = 'cursor-rain-container';
this.rainContainer.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
pointer-events: none;
z-index: ${this.options.zIndex};
overflow: hidden;
`;
this.container.appendChild(this.rainContainer);
}
preCreateDrops() {
// Pre-create drop elements for better performance
for (let i = 0; i < this.options.maxDrops; i++) {
const drop = this.createDropElement();
this.animationPool.push(drop);
if (this.rainContainer) {
this.rainContainer.appendChild(drop);
}
}
}
createDropElement() {
const drop = document.createElement('div');
drop.className = 'rain-drop';
drop.style.cssText = `
position: absolute;
background: ${this.options.color};
border-radius: 50% 50% 50% 50% / 90% 90% 10% 10%;
pointer-events: none;
opacity: 0;
transform-origin: center bottom;
`;
return drop;
}
setupEventListeners() {
if (!this.options.enabled) {
return;
}
this.removeEventListeners();
this.mouseMoveHandler = this.throttle((e) => {
this.createRainAtPosition(e.clientX, e.clientY);
}, 16); // ~60fps throttling
document.addEventListener('mousemove', this.mouseMoveHandler, { passive: true });
}
removeEventListeners() {
if (this.mouseMoveHandler) {
document.removeEventListener('mousemove', this.mouseMoveHandler);
this.mouseMoveHandler = null;
}
if (this.timeoutId) {
clearTimeout(this.timeoutId);
this.timeoutId = null;
}
}
createRainAtPosition(x, y) {
if (!this.rainContainer || this.drops.length >= this.options.maxDrops) {
return;
}
// Get available drop from pool
const dropElement = this.getAvailableDrop();
if (!dropElement) {
return;
}
const size = this.randomBetween(this.options.dropSize[0], this.options.dropSize[1]);
const duration = this.randomBetween(this.options.duration[0], this.options.duration[1]);
// Add some randomness to position
const offsetX = this.randomBetween(-20, 20);
const offsetY = this.randomBetween(-10, 10);
const finalX = x + offsetX;
const finalY = y + offsetY;
const drop = {
element: dropElement,
x: finalX,
y: finalY,
size,
isAnimating: true
};
this.drops.push(drop);
// Set initial position and size
gsap.gsap.set(dropElement, {
x: finalX - size / 4, // 调整X偏移因为宽度变小了
y: finalY - size / 2,
width: size * 0.3, // 宽度减小到原来的30%,让雨滴更细
height: size * 4, // 高度增加到4倍让雨滴更长
opacity: 0,
scaleY: 0.1,
rotation: this.randomBetween(-15, 15)
});
// Animate the raindrop - continuous fall with gradual rotation change
const initialRotation = this.randomBetween(-15, 15); // 初始随机角度
const fallDistance = window.innerHeight - finalY + 100;
const tl = gsap.gsap.timeline({
onComplete: () => {
this.returnDropToPool(drop);
}
});
// 快速出现
tl.to(dropElement, {
opacity: 1,
scaleY: 1,
duration: 0.1,
ease: 'power2.out'
})
// 连续下落:一次性完成整个下落过程,同时角度逐渐变垂直
.to(dropElement, {
y: `+=${fallDistance}`, // 一次性完成所有下落距离
x: `+=${initialRotation * 0.3}`, // 轻微的水平漂移
scaleY: 1.5, // 逐渐拉长
opacity: 0.3, // 逐渐变透明
rotation: 0, // 角度从初始角度平滑变为垂直
duration: duration,
ease: 'power1.in' // 重力加速效果
}, 0.05);
}
getAvailableDrop() {
return this.animationPool.find(drop => gsap.gsap.getTweensOf(drop).length === 0) || null;
}
returnDropToPool(drop) {
const index = this.drops.indexOf(drop);
if (index > -1) {
this.drops.splice(index, 1);
}
drop.isAnimating = false;
// Reset the element
gsap.gsap.set(drop.element, {
opacity: 0,
x: 0,
y: 0,
scaleY: 1,
rotation: 0
});
}
randomBetween(min, max) {
return Math.random() * (max - min) + min;
}
throttle(func, delay) {
let timeoutId = null;
let lastExecTime = 0;
return (...args) => {
const currentTime = Date.now();
if (currentTime - lastExecTime > delay) {
func(...args);
lastExecTime = currentTime;
}
else {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = window.setTimeout(() => {
func(...args);
lastExecTime = Date.now();
}, delay - (currentTime - lastExecTime));
}
};
}
cleanup() {
this.removeEventListeners();
// Kill all GSAP animations
this.drops.forEach(drop => {
gsap.gsap.killTweensOf(drop.element);
});
this.drops = [];
this.animationPool = [];
if (this.rainContainer && this.rainContainer.parentNode) {
this.rainContainer.parentNode.removeChild(this.rainContainer);
this.rainContainer = null;
}
}
}
/**
* Create a new cursor rain effect instance
*/
function createCursorRainEffect(options) {
return new CursorRainEffect(options);
}
/**
* Initialize cursor rain effect with default options
* This is a convenience function for quick setup
*/
function initCursorRain(options) {
const effect = createCursorRainEffect(options);
// Auto-initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
effect.init();
});
}
else {
// DOM is already ready
effect.init();
}
return effect;
}
/**
* VitePress compatible initialization
* This function ensures the effect works correctly in VitePress environment
*/
function initCursorRainForVitePress(options) {
const effect = createCursorRainEffect({
container: document.body,
zIndex: 1000, // Lower z-index to avoid conflicts with VitePress UI
...options
});
// Handle VitePress page navigation
const initEffect = () => {
// Small delay to ensure VitePress has finished rendering
setTimeout(() => {
effect.init();
}, 100);
};
// Handle both initial load and client-side navigation
if (typeof window !== 'undefined') {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initEffect);
}
else {
initEffect();
}
// Handle VitePress client-side navigation
window.addEventListener('popstate', () => {
effect.destroy();
initEffect();
});
// Handle programmatic navigation (if using Vue Router)
if (window.history && window.history.pushState) {
const originalPushState = window.history.pushState;
window.history.pushState = function (...args) {
originalPushState.apply(window.history, args);
effect.destroy();
initEffect();
};
}
}
return effect;
}
// Default export for convenience
var index = {
createCursorRainEffect,
initCursorRain,
initCursorRainForVitePress,
CursorRainEffect
};
exports.CursorRainEffect = CursorRainEffect;
exports.createCursorRainEffect = createCursorRainEffect;
exports.default = index;
exports.initCursorRain = initCursorRain;
exports.initCursorRainForVitePress = initCursorRainForVitePress;