Add glitter
This commit is contained in:
170
app.js
170
app.js
@@ -30,17 +30,144 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var svgData = new XMLSerializer().serializeToString(svg);
|
// Trigger glitter effect on QR code
|
||||||
var svgBlob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" });
|
triggerQRGlitterEffect();
|
||||||
var svgUrl = URL.createObjectURL(svgBlob);
|
|
||||||
|
// Small delay to show the effect before download
|
||||||
|
setTimeout(function() {
|
||||||
|
var svgData = new XMLSerializer().serializeToString(svg);
|
||||||
|
var svgBlob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" });
|
||||||
|
var svgUrl = URL.createObjectURL(svgBlob);
|
||||||
|
|
||||||
var downloadLink = document.createElement("a");
|
var downloadLink = document.createElement("a");
|
||||||
downloadLink.href = svgUrl;
|
downloadLink.href = svgUrl;
|
||||||
downloadLink.download = "qrcode.svg";
|
downloadLink.download = "qrcode.svg";
|
||||||
document.body.appendChild(downloadLink);
|
document.body.appendChild(downloadLink);
|
||||||
downloadLink.click();
|
downloadLink.click();
|
||||||
document.body.removeChild(downloadLink);
|
document.body.removeChild(downloadLink);
|
||||||
URL.revokeObjectURL(svgUrl);
|
URL.revokeObjectURL(svgUrl);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRandomGlitterColor() {
|
||||||
|
const colors = [
|
||||||
|
'#FFD700', // Gold
|
||||||
|
'#FF69B4', // Hot Pink
|
||||||
|
'#00CED1', // Dark Turquoise
|
||||||
|
'#FF6347', // Tomato
|
||||||
|
'#9370DB', // Medium Purple
|
||||||
|
'#32CD32', // Lime Green
|
||||||
|
'#FF1493', // Deep Pink
|
||||||
|
'#00BFFF', // Deep Sky Blue
|
||||||
|
'#FFA500', // Orange
|
||||||
|
'#DA70D6', // Orchid
|
||||||
|
'#ADFF2F', // Green Yellow
|
||||||
|
'#FF4500', // Orange Red
|
||||||
|
'#7B68EE', // Medium Slate Blue
|
||||||
|
'#00FF7F', // Spring Green
|
||||||
|
'#DC143C', // Crimson
|
||||||
|
'#40E0D0' // Turquoise
|
||||||
|
];
|
||||||
|
return colors[Math.floor(Math.random() * colors.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function createGlitter(container) {
|
||||||
|
const glitter = document.createElement('div');
|
||||||
|
glitter.className = 'glitter';
|
||||||
|
|
||||||
|
// Random position within button
|
||||||
|
const x = Math.random() * container.offsetWidth;
|
||||||
|
const y = Math.random() * container.offsetHeight;
|
||||||
|
|
||||||
|
glitter.style.left = x + 'px';
|
||||||
|
glitter.style.top = y + 'px';
|
||||||
|
|
||||||
|
// Random color
|
||||||
|
const color = getRandomGlitterColor();
|
||||||
|
glitter.style.background = color;
|
||||||
|
glitter.style.boxShadow = `0 0 6px ${color}, 0 0 12px ${color}, 0 0 18px ${color}`;
|
||||||
|
|
||||||
|
// Random animation type
|
||||||
|
const animations = ['anim1', 'anim2', 'anim3'];
|
||||||
|
const randomAnim = animations[Math.floor(Math.random() * animations.length)];
|
||||||
|
glitter.classList.add(randomAnim);
|
||||||
|
|
||||||
|
// Random delay
|
||||||
|
glitter.style.animationDelay = Math.random() * 0.5 + 's';
|
||||||
|
|
||||||
|
container.appendChild(glitter);
|
||||||
|
|
||||||
|
// Remove glitter after animation
|
||||||
|
setTimeout(() => {
|
||||||
|
if (glitter.parentNode) {
|
||||||
|
glitter.parentNode.removeChild(glitter);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startGlitterEffect(button) {
|
||||||
|
const container = button.querySelector('.glitter-container');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
// Create multiple glitter particles
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
setTimeout(() => createGlitter(container), i * 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createQRGlitter(container) {
|
||||||
|
const glitter = document.createElement('div');
|
||||||
|
glitter.className = 'qr-glitter';
|
||||||
|
|
||||||
|
// Random position within QR code area
|
||||||
|
const x = Math.random() * container.offsetWidth;
|
||||||
|
const y = Math.random() * container.offsetHeight;
|
||||||
|
|
||||||
|
glitter.style.left = x + 'px';
|
||||||
|
glitter.style.top = y + 'px';
|
||||||
|
|
||||||
|
// Random color
|
||||||
|
const color = getRandomGlitterColor();
|
||||||
|
glitter.style.background = color;
|
||||||
|
glitter.style.boxShadow = `0 0 8px ${color}, 0 0 16px ${color}, 0 0 24px ${color}`;
|
||||||
|
|
||||||
|
// Random animation type
|
||||||
|
const animations = ['anim1', 'anim2', 'anim3'];
|
||||||
|
const randomAnim = animations[Math.floor(Math.random() * animations.length)];
|
||||||
|
glitter.classList.add(randomAnim);
|
||||||
|
|
||||||
|
// Random delay
|
||||||
|
glitter.style.animationDelay = Math.random() * 0.3 + 's';
|
||||||
|
|
||||||
|
container.appendChild(glitter);
|
||||||
|
|
||||||
|
// Remove glitter after animation
|
||||||
|
setTimeout(() => {
|
||||||
|
if (glitter.parentNode) {
|
||||||
|
glitter.parentNode.removeChild(glitter);
|
||||||
|
}
|
||||||
|
}, 2500);
|
||||||
|
}
|
||||||
|
|
||||||
|
function triggerQRGlitterEffect() {
|
||||||
|
const qrcode = document.getElementById('qrcode');
|
||||||
|
let container = qrcode.querySelector('.qr-glitter-container');
|
||||||
|
|
||||||
|
// Create container if it doesn't exist
|
||||||
|
if (!container) {
|
||||||
|
container = document.createElement('div');
|
||||||
|
container.className = 'qr-glitter-container';
|
||||||
|
qrcode.appendChild(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create multiple waves of glitter
|
||||||
|
for (let wave = 0; wave < 3; wave++) {
|
||||||
|
setTimeout(() => {
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
setTimeout(() => createQRGlitter(container), i * 100);
|
||||||
|
}
|
||||||
|
}, wave * 300);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeApp() {
|
function initializeApp() {
|
||||||
@@ -55,6 +182,11 @@
|
|||||||
var colorInput = document.getElementById("color");
|
var colorInput = document.getElementById("color");
|
||||||
var downloadButton = document.getElementById("download");
|
var downloadButton = document.getElementById("download");
|
||||||
|
|
||||||
|
// Create glitter container for download button
|
||||||
|
const glitterContainer = document.createElement('div');
|
||||||
|
glitterContainer.className = 'glitter-container';
|
||||||
|
downloadButton.appendChild(glitterContainer);
|
||||||
|
|
||||||
// Text input events
|
// Text input events
|
||||||
textInput.addEventListener('input', debouncedMakeCode);
|
textInput.addEventListener('input', debouncedMakeCode);
|
||||||
textInput.addEventListener('blur', makeCode);
|
textInput.addEventListener('blur', makeCode);
|
||||||
@@ -67,8 +199,24 @@
|
|||||||
// Color input events
|
// Color input events
|
||||||
colorInput.addEventListener('change', makeCode);
|
colorInput.addEventListener('change', makeCode);
|
||||||
|
|
||||||
// Download button event
|
// Download button events
|
||||||
downloadButton.addEventListener('click', downloadSVG);
|
downloadButton.addEventListener('click', downloadSVG);
|
||||||
|
|
||||||
|
// Glitter effect on hover
|
||||||
|
let glitterInterval;
|
||||||
|
downloadButton.addEventListener('mouseenter', function() {
|
||||||
|
startGlitterEffect(downloadButton);
|
||||||
|
glitterInterval = setInterval(() => {
|
||||||
|
startGlitterEffect(downloadButton);
|
||||||
|
}, 600);
|
||||||
|
});
|
||||||
|
|
||||||
|
downloadButton.addEventListener('mouseleave', function() {
|
||||||
|
if (glitterInterval) {
|
||||||
|
clearInterval(glitterInterval);
|
||||||
|
glitterInterval = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize when DOM is ready
|
// Initialize when DOM is ready
|
||||||
|
|||||||
180
styles.css
180
styles.css
@@ -75,6 +75,8 @@ h1 {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#download:hover {
|
#download:hover {
|
||||||
@@ -82,6 +84,94 @@ h1 {
|
|||||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.glitter-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glitter {
|
||||||
|
position: absolute;
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 50%;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes glitter1 {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(0) translateX(0) scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-20px) translateX(10px) scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-40px) translateX(20px) scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes glitter2 {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(0) translateX(0) scale(0) rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-15px) translateX(-15px) scale(1.2) rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-30px) translateX(-30px) scale(0) rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes glitter3 {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(0) translateX(0) scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
30% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-10px) translateX(5px) scale(0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
70% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-25px) translateX(-5px) scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-35px) translateX(-10px) scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.glitter.anim1 {
|
||||||
|
animation: glitter1 1.5s ease-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glitter.anim2 {
|
||||||
|
animation: glitter2 1.8s ease-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glitter.anim3 {
|
||||||
|
animation: glitter3 1.2s ease-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
.qr-container {
|
.qr-container {
|
||||||
margin: 30px 0;
|
margin: 30px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -91,12 +181,14 @@ h1 {
|
|||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qrcode {
|
#qrcode {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qrcode svg {
|
#qrcode svg {
|
||||||
@@ -111,6 +203,94 @@ h1 {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qr-glitter-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
overflow: visible;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-glitter {
|
||||||
|
position: absolute;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes qrGlitter1 {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(0) translateX(0) scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-30px) translateX(15px) scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-60px) translateX(30px) scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes qrGlitter2 {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(0) translateX(0) scale(0) rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-25px) translateX(-20px) scale(1.3) rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-50px) translateX(-40px) scale(0) rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes qrGlitter3 {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(0) translateX(0) scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
30% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-15px) translateX(8px) scale(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
70% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-35px) translateX(-8px) scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-55px) translateX(-15px) scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-glitter.anim1 {
|
||||||
|
animation: qrGlitter1 2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-glitter.anim2 {
|
||||||
|
animation: qrGlitter2 2.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-glitter.anim3 {
|
||||||
|
animation: qrGlitter3 1.8s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
color: #666;
|
color: #666;
|
||||||
|
|||||||
Reference in New Issue
Block a user