mirror of
https://github.com/multipleofnpm/tiny-ripple.git
synced 2026-01-13 16:17:57 +00:00
Update index.js
This commit is contained in:
215
index.js
215
index.js
@@ -1,2 +1,215 @@
|
||||
if(window.__tinyRippleInit) throw new Error('tiny-ripple already initialized') window.__tinyRippleInit = true var __tr_style = document.createElement('style') __tr_style.textContent = ".r{position:fixed;border-radius:50%;pointer-events:none;background:transparent;box-shadow:0 8px 18px rgba(0,0,0,0.14);transform:translate(-50%,-50%) scale(.15);opacity:1;transition:transform .42s cubic-bezier(.2,.8,.2,1),opacity .42s linear,box-shadow .42s linear;z-index:9999999}.r.a{transform:translate(-50%,-50%) scale(1);opacity:0;box-shadow:0 0 0 rgba(0,0,0,0)}" document.head.appendChild(__tr_style) var __tr_dur = 420 function __tr_make(x,y){var dx=Math.max(x,innerWidth-x),dy=Math.max(y,innerHeight-y),r=Math.hypot(dx,dy),s=Math.max(48,Math.ceil(r*2));var e=document.createElement('div');e.className='r';e.style.width=e.style.height=s+'px';e.style.left=x+'px';e.style.top=y+'px';document.body.appendChild(e);void e.offsetWidth;e.classList.add('a');setTimeout(function(){if(e.parentNode) e.parentNode.removeChild(e)},__tr_dur+60)} var __tr_h = function(ev){var x=('clientX' in ev && ev.clientX!=null)?ev.clientX:(ev.touches&&ev.touches[0]&&ev.touches[0].clientX)||0;var y=('clientY' in ev && ev.clientY!=null)?ev.clientY:(ev.touches&&ev.touches[0]&&ev.touches[0].clientY)||0;__tr_make(x,y)} if(window.PointerEvent) addEventListener('pointerdown',__tr_h,{passive:true}); else{addEventListener('touchstart',__tr_h,{passive:true});addEventListener('mousedown',__tr_h,{passive:true})} window.tinyRipple={disable:function(){if(window.PointerEvent) removeEventListener('pointerdown',__tr_h);else{removeEventListener('touchstart',__tr_h);removeEventListener('mousedown',__tr_h)}if(__tr_style.parentNode) __tr_style.parentNode.removeChild(__tr_style);window.__tinyRippleInit=false}}
|
||||
/*!
|
||||
* tiny-ripple v0.1.0
|
||||
* A lightweight library that adds subtle ripple effects on touch/click interactions
|
||||
* https://github.com/yourusername/tiny-ripple
|
||||
*
|
||||
* Copyright (c) 2025
|
||||
* Licensed under MIT
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
const defaultOptions = {
|
||||
size: 60,
|
||||
duration: 500,
|
||||
color: 'rgba(0,0,0,0.3)',
|
||||
zIndex: 9999,
|
||||
debounceDelay: 100
|
||||
};
|
||||
|
||||
let isInitialized = false;
|
||||
let lastRippleTime = 0;
|
||||
let touchStartY = null;
|
||||
let touchStartTime = null;
|
||||
|
||||
/**
|
||||
* Create a ripple effect at specified coordinates
|
||||
* @param {number} x - X coordinate
|
||||
* @param {number} y - Y coordinate
|
||||
* @param {Object} options - Custom options
|
||||
*/
|
||||
function createRipple(x, y, options = {}) {
|
||||
const opts = { ...defaultOptions, ...options };
|
||||
|
||||
const ripple = document.createElement('div');
|
||||
ripple.setAttribute('data-tiny-ripple', '');
|
||||
|
||||
// Set position and initial size
|
||||
const size = opts.size;
|
||||
ripple.style.cssText = `
|
||||
position: fixed;
|
||||
left: ${x - size/2}px;
|
||||
top: ${y - size/2}px;
|
||||
width: ${size}px;
|
||||
height: ${size}px;
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
z-index: ${opts.zIndex};
|
||||
background: radial-gradient(circle, ${opts.color} 0%, ${opts.color.replace('0.3', '0.05')} 70%, transparent 100%);
|
||||
animation: tiny-ripple-animation ${opts.duration}ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
||||
mix-blend-mode: multiply;
|
||||
`;
|
||||
|
||||
document.body.appendChild(ripple);
|
||||
|
||||
// Remove the ripple after animation
|
||||
setTimeout(() => {
|
||||
if (ripple.parentNode) {
|
||||
ripple.parentNode.removeChild(ripple);
|
||||
}
|
||||
}, opts.duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle touch start to track potential scrolling
|
||||
*/
|
||||
function handleTouchStart(e) {
|
||||
if (e.touches.length === 1) {
|
||||
touchStartY = e.touches[0].clientY;
|
||||
touchStartTime = Date.now();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle touch move to detect if user is scrolling
|
||||
*/
|
||||
function handleTouchMove(e) {
|
||||
if (touchStartY !== null && e.touches.length === 1) {
|
||||
const currentY = e.touches[0].clientY;
|
||||
const deltaY = Math.abs(currentY - touchStartY);
|
||||
const deltaTime = Date.now() - touchStartTime;
|
||||
|
||||
// If moved more than 10px vertically in less than 300ms, it's likely scrolling
|
||||
if (deltaY > 10 && deltaTime < 300) {
|
||||
touchStartY = null; // Mark as scrolling gesture
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle touch end - create ripple if it wasn't a scroll gesture
|
||||
*/
|
||||
function handleTouchEnd(e) {
|
||||
// Only create ripple if touchStartY is still set (meaning no scroll detected)
|
||||
if (touchStartY !== null && e.changedTouches.length === 1) {
|
||||
const now = Date.now();
|
||||
|
||||
// Debounce check
|
||||
if (now - lastRippleTime >= defaultOptions.debounceDelay) {
|
||||
lastRippleTime = now;
|
||||
|
||||
const touch = e.changedTouches[0];
|
||||
createRipple(touch.clientX, touch.clientY);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset tracking
|
||||
touchStartY = null;
|
||||
touchStartTime = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle mouse events (desktop)
|
||||
*/
|
||||
function handleMouseDown(e) {
|
||||
const now = Date.now();
|
||||
|
||||
// Debounce check
|
||||
if (now - lastRippleTime < defaultOptions.debounceDelay) {
|
||||
return;
|
||||
}
|
||||
lastRippleTime = now;
|
||||
|
||||
createRipple(e.clientX, e.clientY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add required CSS keyframes
|
||||
*/
|
||||
function addCSS() {
|
||||
if (document.querySelector('#tiny-ripple-styles')) return;
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.id = 'tiny-ripple-styles';
|
||||
style.textContent = `
|
||||
@keyframes tiny-ripple-animation {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(4);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the ripple effect library
|
||||
*/
|
||||
function init(options = {}) {
|
||||
if (isInitialized) return;
|
||||
|
||||
// Merge custom options
|
||||
Object.assign(defaultOptions, options);
|
||||
|
||||
// Add CSS
|
||||
addCSS();
|
||||
|
||||
// Add event listeners
|
||||
document.addEventListener('touchstart', handleTouchStart, { passive: true });
|
||||
document.addEventListener('touchmove', handleTouchMove, { passive: true });
|
||||
document.addEventListener('touchend', handleTouchEnd, { passive: true });
|
||||
document.addEventListener('mousedown', handleMouseDown, { passive: true });
|
||||
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the ripple effect (remove event listeners and styles)
|
||||
*/
|
||||
function destroy() {
|
||||
if (!isInitialized) return;
|
||||
|
||||
document.removeEventListener('touchstart', handleTouchStart);
|
||||
document.removeEventListener('touchmove', handleTouchMove);
|
||||
document.removeEventListener('touchend', handleTouchEnd);
|
||||
document.removeEventListener('mousedown', handleMouseDown);
|
||||
|
||||
// Remove existing ripples
|
||||
const ripples = document.querySelectorAll('[data-tiny-ripple]');
|
||||
ripples.forEach(ripple => ripple.remove());
|
||||
|
||||
// Remove styles
|
||||
const styles = document.querySelector('#tiny-ripple-styles');
|
||||
if (styles) styles.remove();
|
||||
|
||||
isInitialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-initialize when DOM is ready
|
||||
*/
|
||||
function autoInit() {
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
// Public API
|
||||
window.TinyRipple = {
|
||||
init,
|
||||
destroy,
|
||||
createRipple,
|
||||
isInitialized: () => isInitialized,
|
||||
version: '0.1.0'
|
||||
};
|
||||
|
||||
// Auto-initialize immediately
|
||||
autoInit();
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user