马一丁

Add source code for day/night mode toggle button

  1 +ISC License
  2 +
  3 +Copyright(c)2024,Xiumuzaidiao
  4 +
  5 +Permission to use, copy, modify, and/or distribute this software for any
  6 +purpose with or without fee is hereby granted, provided that the above
  7 +copyright notice and this permission notice appear in all copies.
  8 +
  9 +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10 +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11 +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12 +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13 +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14 +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15 +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16 +
  17 +
  1 +<!DOCTYPE html>
  2 +<html>
  3 + <head>
  4 + <meta charset="utf-8" />
  5 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6 + <title>白天黑夜切换按钮</title>
  7 + <style>
  8 + body{
  9 + transition: 0.5s;
  10 + }
  11 + </style>
  12 + </head>
  13 + <body>
  14 + <theme-button value="dark" id="btn" size="3"></theme-button>
  15 + <script>
  16 + document.body.style.backgroundColor = "#424242";
  17 + btn.addEventListener("change", e => {
  18 + if (e.detail === 'dark') {
  19 + document.body.style.backgroundColor = "#424242";
  20 + }
  21 + else {
  22 + document.body.style.backgroundColor = "aliceblue";
  23 + }
  24 + });
  25 + </script>
  26 + <script src="js/script.js"></script>
  27 + </body>
  28 +</html>
  1 +(() => {
  2 + const func = (root, initTheme, changeTheme) => {
  3 + const $ = (s) => {
  4 + let dom = root.querySelectorAll(s);
  5 + return dom.length == 1 ? dom[0] : dom;
  6 + };
  7 + let mainButton = $(".main-button");
  8 + let daytimeBackground = $(".daytime-background");
  9 + let cloud = $(".cloud");
  10 + let cloudList = $(".cloud-son");
  11 + let cloudLight = $(".cloud-light");
  12 + let components = $(".components");
  13 + let moon = $(".moon");
  14 + let stars = $(".stars");
  15 + let star = $(".star");
  16 + let isMoved = false;
  17 + let isClicked = false;
  18 + window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
  19 + toggleThemeBasedOnSystem();
  20 + });
  21 + const toggleThemeBasedOnSystem = () => {
  22 + if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
  23 + if (!isMoved) {
  24 + components.onclick();
  25 + }
  26 + } else {
  27 + if (isMoved) {
  28 + components.onclick();
  29 + }
  30 + }
  31 + };
  32 + components.onclick = () => {
  33 + if (isMoved) {
  34 + mainButton.style.transform = "translateX(0)";
  35 + mainButton.style.backgroundColor = "rgba(255, 195, 35,1)";
  36 +
  37 + mainButton.style.boxShadow =
  38 + "3em 3em 5em rgba(0, 0, 0, 0.5), inset -3em -5em 3em -3em rgba(0, 0, 0, 0.5), inset 4em 5em 2em -2em rgba(255, 230, 80,1)";
  39 +
  40 + daytimeBackground[0].style.transform = "translateX(0)";
  41 + daytimeBackground[1].style.transform = "translateX(0)";
  42 + daytimeBackground[2].style.transform = "translateX(0)";
  43 + cloud.style.transform = "translateY(10em)";
  44 + cloudLight.style.transform = "translateY(10em)";
  45 + components.style.backgroundColor = "rgba(70, 133, 192,1)";
  46 +
  47 + moon[0].style.opacity = "0";
  48 + moon[1].style.opacity = "0";
  49 + moon[2].style.opacity = "0";
  50 +
  51 + stars.style.transform = "translateY(-125em)";
  52 + stars.style.opacity = "0";
  53 +
  54 + changeTheme("light");
  55 + } else {
  56 + mainButton.style.transform = "translateX(110em)";
  57 + mainButton.style.backgroundColor = "rgba(195, 200,210,1)";
  58 +
  59 + mainButton.style.boxShadow =
  60 + "3em 3em 5em rgba(0, 0, 0, 0.5), inset -3em -5em 3em -3em rgba(0, 0, 0, 0.5), inset 4em 5em 2em -2em rgba(255, 255, 210,1)";
  61 +
  62 + daytimeBackground[0].style.transform = "translateX(110em)";
  63 + daytimeBackground[1].style.transform = "translateX(80em)";
  64 + daytimeBackground[2].style.transform = "translateX(50em)";
  65 + cloud.style.transform = "translateY(80em)";
  66 + cloudLight.style.transform = "translateY(80em)";
  67 + components.style.backgroundColor = "rgba(25,30,50,1)";
  68 +
  69 + moon[0].style.opacity = "1";
  70 + moon[1].style.opacity = "1";
  71 + moon[2].style.opacity = "1";
  72 +
  73 + stars.style.transform = "translateY(-62.5em)";
  74 + stars.style.opacity = "1";
  75 +
  76 + changeTheme("dark");
  77 + }
  78 +
  79 + isClicked = true;
  80 +
  81 + setTimeout(function () {
  82 + isClicked = false;
  83 + }, 500);
  84 + isMoved = !isMoved;
  85 + };
  86 +
  87 + mainButton.addEventListener("mousemove", function () {
  88 + if (isClicked) return;
  89 +
  90 + if (isMoved) {
  91 + mainButton.style.transform = "translateX(100em)";
  92 + daytimeBackground[0].style.transform = "translateX(100em)";
  93 + daytimeBackground[1].style.transform = "translateX(73em)";
  94 + daytimeBackground[2].style.transform = "translateX(46em)";
  95 +
  96 + star[0].style.top = "10em";
  97 + star[0].style.left = "36em";
  98 + star[1].style.top = "40em";
  99 + star[1].style.left = "87em";
  100 + star[2].style.top = "26em";
  101 + star[2].style.left = "16em";
  102 + star[3].style.top = "38em";
  103 + star[3].style.left = "63em";
  104 + star[4].style.top = "20.5em";
  105 + star[4].style.left = "72em";
  106 + star[5].style.top = "51.5em";
  107 + star[5].style.left = "35em";
  108 + } else {
  109 + mainButton.style.transform = "translateX(10em)";
  110 + daytimeBackground[0].style.transform = "translateX(10em)";
  111 + daytimeBackground[1].style.transform = "translateX(7em)";
  112 + daytimeBackground[2].style.transform = "translateX(4em)";
  113 +
  114 + cloudList[0].style.right = "-24em";
  115 + cloudList[0].style.bottom = "10em";
  116 + cloudList[1].style.right = "-12em";
  117 + cloudList[1].style.bottom = "-27em";
  118 + cloudList[2].style.right = "17em";
  119 + cloudList[2].style.bottom = "-43em";
  120 + cloudList[3].style.right = "46em";
  121 + cloudList[3].style.bottom = "-39em";
  122 + cloudList[4].style.right = "70em";
  123 + cloudList[4].style.bottom = "-65em";
  124 + cloudList[5].style.right = "109em";
  125 + cloudList[5].style.bottom = "-54em";
  126 + cloudList[6].style.right = "-23em";
  127 + cloudList[6].style.bottom = "10em";
  128 + cloudList[7].style.right = "-11em";
  129 + cloudList[7].style.bottom = "-26em";
  130 + cloudList[8].style.right = "18em";
  131 + cloudList[8].style.bottom = "-42em";
  132 + cloudList[9].style.right = "47em";
  133 + cloudList[9].style.bottom = "-38em";
  134 + cloudList[10].style.right = "74em";
  135 + cloudList[10].style.bottom = "-64em";
  136 + cloudList[11].style.right = "110em";
  137 + cloudList[11].style.bottom = "-55em";
  138 + }
  139 + });
  140 +
  141 + mainButton.addEventListener("mouseout", function () {
  142 + if (isClicked) {
  143 + return;
  144 + }
  145 + if (isMoved) {
  146 + mainButton.style.transform = "translateX(110em)";
  147 + daytimeBackground[0].style.transform = "translateX(110em)";
  148 + daytimeBackground[1].style.transform = "translateX(80em)";
  149 + daytimeBackground[2].style.transform = "translateX(50em)";
  150 +
  151 + star[0].style.top = "11em";
  152 + star[0].style.left = "39em";
  153 + star[1].style.top = "39em";
  154 + star[1].style.left = "91em";
  155 + star[2].style.top = "26em";
  156 + star[2].style.left = "19em";
  157 + star[3].style.top = "37em";
  158 + star[3].style.left = "66em";
  159 + star[4].style.top = "21em";
  160 + star[4].style.left = "75em";
  161 + star[5].style.top = "51em";
  162 + star[5].style.left = "38em";
  163 + } else {
  164 + mainButton.style.transform = "translateX(0em)";
  165 + daytimeBackground[0].style.transform = "translateX(0em)";
  166 + daytimeBackground[1].style.transform = "translateX(0em)";
  167 + daytimeBackground[2].style.transform = "translateX(0em)";
  168 +
  169 + cloudList[0].style.right = "-20em";
  170 + cloudList[0].style.bottom = "10em";
  171 + cloudList[1].style.right = "-10em";
  172 + cloudList[1].style.bottom = "-25em";
  173 + cloudList[2].style.right = "20em";
  174 + cloudList[2].style.bottom = "-40em";
  175 + cloudList[3].style.right = "50em";
  176 + cloudList[3].style.bottom = "-35em";
  177 + cloudList[4].style.right = "75em";
  178 + cloudList[4].style.bottom = "-60em";
  179 + cloudList[5].style.right = "110em";
  180 + cloudList[5].style.bottom = "-50em";
  181 + cloudList[6].style.right = "-20em";
  182 + cloudList[6].style.bottom = "10em";
  183 + cloudList[7].style.right = "-10em";
  184 + cloudList[7].style.bottom = "-25em";
  185 + cloudList[8].style.right = "20em";
  186 + cloudList[8].style.bottom = "-40em";
  187 + cloudList[9].style.right = "50em";
  188 + cloudList[9].style.bottom = "-35em";
  189 + cloudList[10].style.right = "75em";
  190 + cloudList[10].style.bottom = "-60em";
  191 + cloudList[11].style.right = "110em";
  192 + cloudList[11].style.bottom = "-50em";
  193 + }
  194 + });
  195 +
  196 + const getRandomDirection = () => {
  197 + const directions = ["2em", "-2em"];
  198 + return directions[Math.floor(Math.random() * directions.length)];
  199 + };
  200 +
  201 + const moveElementRandomly = (element) => {
  202 + const randomDirectionX = getRandomDirection();
  203 + const randomDirectionY = getRandomDirection();
  204 + element.style.transform = `translate(${randomDirectionX}, ${randomDirectionY})`;
  205 + };
  206 +
  207 + const cloudSons = root.querySelectorAll(".cloud-son");
  208 + setInterval(() => {
  209 + cloudSons.forEach(moveElementRandomly);
  210 + }, 1000);
  211 +
  212 + if (initTheme === "dark") {
  213 + components.onclick();
  214 + }
  215 + };
  216 +
  217 + class ThemeButton extends HTMLElement {
  218 + constructor() {
  219 + super();
  220 + }
  221 + connectedCallback() {
  222 + const initTheme = this.getAttribute("value") || "light";
  223 + const size = +this.getAttribute("size") || 3;
  224 + const shadow = this.attachShadow({ mode: "closed" });
  225 + const container = document.createElement("div");
  226 + container.setAttribute("class", "container");
  227 + container.setAttribute("style", `font-size: ${(size / 3).toFixed(2)}px`);
  228 + container.innerHTML =
  229 + '<div class="components"><div class="main-button"><div class="moon"></div><div class="moon"></div><div class="moon"></div></div><div class="daytime-background"></div><div class="daytime-background"></div><div class="daytime-background"></div><div class="cloud"><div class="cloud-son"></div><div class="cloud-son"></div><div class="cloud-son"></div><div class="cloud-son"></div><div class="cloud-son"></div><div class="cloud-son"></div></div><div class="cloud-light"><div class="cloud-son"></div><div class="cloud-son"></div><div class="cloud-son"></div><div class="cloud-son"></div><div class="cloud-son"></div><div class="cloud-son"></div></div><div class="stars"><div class="star big"><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div></div><div class="star big"><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div></div><div class="star medium"><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div></div><div class="star medium"><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div></div><div class="star small"><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div></div><div class="star small"><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div><div class="star-son"></div></div></div></div>';
  230 + const style = document.createElement("style");
  231 + style.textContent =
  232 + "* { margin: 0; padding: 0; transition: 0.7s; -webkit-tap-highlight-color:rgba(0,0,0,0); } .container { position: absolute;top: 50%;left: 50%;margin-top: -35em;margin-left: -90em;width: 180em; height: 70em; display: inline-block; vertical-align: bottom; transform: translate3d(0, 0, 0); } .components{ position:fixed; width: 180em; height: 70em; background-color: rgba(70, 133, 192,1); border-radius: 100em; box-shadow: inset 0 0 5em 3em rgba(0, 0, 0, 0.5); overflow: hidden; transition: 0.7s; transition-timing-function: cubic-bezier( 0,0.5, 1,1); cursor: pointer; } .main-button{ margin: 7.5em 0 0 7.5em; width: 55em; height:55em; background-color: rgba(255, 195, 35,1); border-radius: 50%; box-shadow:3em 3em 5em rgba(0, 0, 0, 0.5), inset -3em -5em 3em -3em rgba(0, 0, 0, 0.5), inset 4em 5em 2em -2em rgba(255, 230, 80,1); transition: 1.0s; transition-timing-function: cubic-bezier(0.56, 1.35, 0.52, 1.00); } .moon{ position: absolute; background-color: rgba(150, 160, 180, 1); box-shadow:inset 0em 0em 1em 1em rgba(0, 0, 0, 0.3) ; border-radius: 50%; transition: 0.5s; opacity: 0; } .moon:nth-child(1){ top: 7.5em; left: 25em; width: 12.5em; height: 12.5em; } .moon:nth-child(2){ top: 20em; left: 7.5em; width: 20em; height: 20em; } .moon:nth-child(3){ top: 32.5em; left: 32.5em; width: 12.5em; height: 12.5em; } .daytime-background { position: absolute; border-radius: 50%; transition: 1.0s; transition-timing-function: cubic-bezier(0.56, 1.35, 0.52, 1.00); } .daytime-background:nth-child(2){ top: -20em; left: -20em; width: 110em; height:110em; background-color: rgba(255, 255, 255,0.2); z-index: -2; } .daytime-background:nth-child(3){ top: -32.5em; left: -17.5em; width: 135em; height:135em; background-color: rgba(255, 255, 255,0.1); z-index: -3; } .daytime-background:nth-child(4){ top: -45em; left: -15em; width: 160em; height:160em; background-color: rgba(255, 255, 255,0.05); z-index: -4; } .cloud,.cloud-light{ transform: translateY(10em); transition: 1.0s; transition-timing-function: cubic-bezier(0.56, 1.35, 0.52, 1.00); } .cloud-son{ position: absolute; background-color: #fff; border-radius: 50%; z-index: -1; transition: transform 6s,right 1s,bottom 1s; } .cloud-son:nth-child(6n+1){ right: -20em; bottom: 10em; width: 50em; height: 50em; } .cloud-son:nth-child(6n+2) { right: -10em; bottom: -25em; width: 60em; height: 60em; } .cloud-son:nth-child(6n+3) { right: 20em; bottom: -40em; width: 60em; height: 60em; } .cloud-son:nth-child(6n+4) { right: 50em; bottom: -35em; width: 60em; height: 60em; } .cloud-son:nth-child(6n+5) { right: 75em; bottom: -60em; width: 75em; height: 75em; } .cloud-son:nth-child(6n+6) { right: 110em; bottom: -50em; width: 60em; height: 60em; } .cloud{ z-index: -2; } .cloud-light{ position: absolute; right: 0em; bottom: 25em; opacity: 0.5; z-index: -3; /*transform: rotate(-5deg);*/ } .stars{ transform: translateY(-125em); z-index: -2; transition: 1.0s; transition-timing-function: cubic-bezier(0.56, 1.35, 0.52, 1.00); } .big { --size: 7.5em; } .medium { --size: 5em; } .small { --size: 3em; } .star { position: absolute; width: calc(2*var(--size)); height: calc(2*var(--size)); } .star:nth-child(1){ top: 11em; left: 39em; animation-name: star; animation-duration: 3.5s; } .star:nth-child(2){ top: 39em; left: 91em; animation-name: star; animation-duration: 4.1s; } .star:nth-child(3){ top: 26em; left: 19em; animation-name: star; animation-duration: 4.9s; } .star:nth-child(4){ top: 37em; left: 66em; animation-name: star; animation-duration: 5.3s; } .star:nth-child(5){ top: 21em; left: 75em; animation-name: star; animation-duration: 3s; } .star:nth-child(6){ top: 51em; left: 38em; animation-name: star; animation-duration: 2.2s; } @keyframes star { 0%,20%{ transform: scale(0); } 20%,100% { transform: scale(1); } } .star-son{ float: left; } .star-son:nth-child(1) { --pos: left 0; } .star-son:nth-child(2) { --pos: right 0; } .star-son:nth-child(3) { --pos: 0 bottom; } .star-son:nth-child(4) { --pos: right bottom; } .star-son { width: var(--size); height: var(--size); background-image: radial-gradient(circle var(--size) at var(--pos), transparent var(--size), #fff); } .star{ transform: scale(1); transition-timing-function: cubic-bezier(0.56, 1.35, 0.52, 1.00); transition: 1s; animation-iteration-count:infinite; animation-direction: alternate; animation-timing-function: linear; } .twinkle { transform: scale(0); }";
  233 + const changeTheme = (detail) => {
  234 + this.dispatchEvent(new CustomEvent("change", { detail }));
  235 + };
  236 + func(container, initTheme, changeTheme);
  237 + shadow.appendChild(style);
  238 + shadow.appendChild(container);
  239 + }
  240 + }
  241 +
  242 + customElements.define("theme-button", ThemeButton);
  243 +})();