Dark Mode Toggle - Js
Dark Mode Toggle - Js
(function() {
'use strict';
// Constants
const BUTTON_ID = 'darkModeToggle';
// SVG Icons
const moonIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21
12.79z"></path></svg>`;
const sunIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-
linejoin="round"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1"
x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22"
y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78"
y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12"
x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line
x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>`;
// Styles
const style = document.createElement('style');
style.textContent = `
#${BUTTON_ID} {
position: fixed;
bottom: 30px;
right: 30px;
width: 80px;
height: 40px;
background-color: #fff;
border-radius: 20px;
border: none;
cursor: pointer;
z-index: 1000;
opacity: 0.8;
/* 明確指定要動畫的屬性,並調整 easing */
transition-property: transform, opacity, box-shadow, background-color;
transition-duration: 0.3s; /* Reduced duration for snappier feel */
transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1), ease,
ease, ease; /* More bouncy cubic-bezier */
display: flex;
align-items: center;
padding: 0 4px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
}
#${BUTTON_ID}:hover {
opacity: 1;
/* 使用 translate, 並調整 scale 的 easing */
transform: scale(1.1);
transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275),
box-shadow 0.2s; /* 調整 hover transition */
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
}
#${BUTTON_ID}::before {
content: ''; /* Remove text content */
width: 32px;
height: 32px;
border-radius: 50%;
/* 明確指定要動畫的屬性,並調整 easing */
transition-property: transform, background-color, -webkit-mask-image,
mask-image;
transition-duration: 0.3s; /* Reduced duration for snappier feel */
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55),
ease, ease, ease; /* "Overshoot" cubic-bezier */
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
color: #333;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
background: none;
/* Add SVG as background */
-webkit-mask-image: url('data:image/svg+xml;utf8,${moonIcon}');
mask-image: url('data:image/svg+xml;utf8,${moonIcon}');
-webkit-mask-size: cover;
mask-size: cover;
background-color: #333; /* Set moon color */
}
#${BUTTON_ID}.dark {
background-color: #000;
}
#${BUTTON_ID}.dark::before {
/* 使用 translate,而非 left/right */
transform: translateX(40px);
/* content: '☀️'; Remove text content */
color: #ffeb3b;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
background: none;
/* Add SVG as background */
-webkit-mask-image: url('data:image/svg+xml;utf8,${sunIcon}');
mask-image: url('data:image/svg+xml;utf8,${sunIcon}');
-webkit-mask-size: cover;
mask-size: cover;
background-color: #fff; /* Set sun color */
}
`;
document.head.appendChild(style);
button.addEventListener('click', toggleDarkMode);
}
if (isDark) {
DarkReader.disable();
await GM.setValue('darkMode', false);
button.classList.remove('dark');
} else {
DarkReader.enable({
brightness: 100,
contrast: 90,
sepia: 10
});
await GM.setValue('darkMode', true);
button.classList.add('dark');
}
}
if (isDark) {
DarkReader.enable({
brightness: 100,
contrast: 90,
sepia: 10
});
button.classList.add('dark');
}
}
init();
})();