bloodspatter-js
Version:
Blood effects library for web applications - realistic blood cells, drips, reveals, and animations
156 lines (128 loc) • 4.71 kB
JavaScript
// ================================
// BLOODSPATTER.JS LIBRARY v1.0
// ================================
const BloodSpatter = {
// Add realistic blood cells to any element
addBloodCells: function (container, count = 3) {
for (let i = 0; i < count; i++) {
const cell = document.createElement('div');
const cellType = Math.floor(Math.random() * 4) + 1;
cell.className = `blood-cell blood-cell-${cellType} blood-cell-animated`;
const rect = container.getBoundingClientRect();
cell.style.left = Math.random() * (rect.width - 30) + 'px';
cell.style.top = Math.random() * (rect.height - 30) + 'px';
cell.style.animationDelay = Math.random() * 2 + 's';
cell.style.animationDuration = (Math.random() * 2 + 3) + 's';
container.appendChild(cell);
// Auto-remove after animation (longer for downward movement)
setTimeout(() => {
if (cell.parentNode) cell.remove();
}, 6000);
}
},
// Clear all blood cells from container
clearBloodCells: function (container) {
const cells = container.querySelectorAll('.blood-cell');
cells.forEach(cell => cell.remove());
},
// Trigger blood reveal with REAL typing animation
triggerBloodReveal: function (container, text) {
console.log('blood reveal')
container.classList.add('blood-reveal');
container.classList.add('scanning');
const textEl = container.querySelector('.blood-reveal-text') ||
container.querySelector('.chat-content') ||
container;
// Get the text to type
const fullText = text || textEl.textContent;
// Clear text and start typing
textEl.textContent = '';
textEl.classList.add('typing');
// Start scanning animation
setTimeout(() => {
// Real typing animation - character by character
let i = 0;
const typeInterval = setInterval(() => {
if (i < fullText.length) {
textEl.textContent += fullText.charAt(i);
i++;
} else {
clearInterval(typeInterval);
// Remove typing cursor and mark as revealed
textEl.classList.remove('typing');
textEl.classList.add('revealed');
}
}, 50); // 50ms per character
}, 500);
},
// Reset blood reveal effect
resetBloodReveal: function (container) {
container.classList.remove('blood-reveal', 'scanning');
const textEl = container.querySelector('.blood-reveal-text') ||
container.querySelector('.chat-content') ||
container;
textEl.classList.remove('typing', 'revealed');
// Restore original text
const originalText = "The victim's blood spatter pattern suggests they were standing when struck... defensive wounds on the arms indicate a struggle.";
textEl.textContent = originalText;
},
// Add blood drips
addBloodDrips: function (container, count = 5) {
for (let i = 0; i < count; i++) {
setTimeout(() => {
const drip = document.createElement('div');
drip.className = 'blood-drip blood-drip-animated';
const rect = container.getBoundingClientRect();
drip.style.left = Math.random() * rect.width + 'px';
drip.style.top = '0px';
drip.style.position = 'absolute';
container.appendChild(drip);
// Remove after animation
setTimeout(() => {
if (drip.parentNode) drip.remove();
}, 3000);
}, i * 300); // Stagger drips
}
},
// Add blood background to chat messages
addChatBloodBG: function (messageElement) {
messageElement.classList.add('chat-blood-background');
},
// Add blood smear hover effect
addBloodSmear: function (element) {
element.classList.add('blood-smear-hover');
},
// Initialize library on page load
init: function () {
// Add blood smear to all existing hover elements
document.querySelectorAll('.blood-smear-hover').forEach(el => {
// Already has class, just ensure it's active
});
// Auto blood drips on page load
this.addBloodDrips(document.body, 3);
console.log('🩸 BloodSpatter.js v1.0 initialized');
}
};
// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
BloodSpatter.init();
});
// Auto blood drips every 10 seconds
setInterval(() => {
BloodSpatter.addBloodDrips(document.body, 2);
}, 10000);
// Export for module systems
if (typeof module !== 'undefined' && module.exports) {
module.exports = BloodSpatter;
}
// AMD support
if (typeof define === 'function' && define.amd) {
define(function () {
return BloodSpatter;
});
}
// Browser global
if (typeof window !== 'undefined') {
window.BloodSpatter = BloodSpatter;
}
export default BloodSpatter;