Showing
1 changed file
with
172 additions
and
3 deletions
| @@ -486,7 +486,7 @@ class HTMLRenderer: | @@ -486,7 +486,7 @@ class HTMLRenderer: | ||
| 486 | {self._render_tagline()} | 486 | {self._render_tagline()} |
| 487 | </div> | 487 | </div> |
| 488 | <div class="header-actions"> | 488 | <div class="header-actions"> |
| 489 | - <button id="theme-toggle" class="action-btn" type="button">🌗 主题切换</button> | 489 | + <theme-button value="light" id="theme-toggle" size="1.5"></theme-button> |
| 490 | <button id="print-btn" class="action-btn" type="button">🖨️ 打印</button> | 490 | <button id="print-btn" class="action-btn" type="button">🖨️ 打印</button> |
| 491 | <button id="export-btn" class="action-btn" type="button" style="display: none;">⬇️ 导出PDF</button> | 491 | <button id="export-btn" class="action-btn" type="button" style="display: none;">⬇️ 导出PDF</button> |
| 492 | </div> | 492 | </div> |
| @@ -2907,6 +2907,11 @@ body {{ | @@ -2907,6 +2907,11 @@ body {{ | ||
| 2907 | display: flex; | 2907 | display: flex; |
| 2908 | gap: 12px; | 2908 | gap: 12px; |
| 2909 | flex-wrap: wrap; | 2909 | flex-wrap: wrap; |
| 2910 | + align-items: center; | ||
| 2911 | +}} | ||
| 2912 | +theme-button {{ | ||
| 2913 | + display: inline-block; | ||
| 2914 | + vertical-align: middle; | ||
| 2910 | }} | 2915 | }} |
| 2911 | .cover {{ | 2916 | .cover {{ |
| 2912 | text-align: center; | 2917 | text-align: center; |
| @@ -3797,6 +3802,166 @@ img, canvas, svg {{ | @@ -3797,6 +3802,166 @@ img, canvas, svg {{ | ||
| 3797 | document.documentElement.classList.remove('no-js'); | 3802 | document.documentElement.classList.remove('no-js'); |
| 3798 | document.documentElement.classList.add('js-ready'); | 3803 | document.documentElement.classList.add('js-ready'); |
| 3799 | 3804 | ||
| 3805 | +/* ========== Theme Button Web Component ========== */ | ||
| 3806 | +(() => { | ||
| 3807 | + const themeButtonFunc = (root, initTheme, changeTheme) => { | ||
| 3808 | + const $ = (s) => { | ||
| 3809 | + let dom = root.querySelectorAll(s); | ||
| 3810 | + return dom.length == 1 ? dom[0] : dom; | ||
| 3811 | + }; | ||
| 3812 | + let mainButton = $(".main-button"); | ||
| 3813 | + let daytimeBackground = $(".daytime-background"); | ||
| 3814 | + let cloud = $(".cloud"); | ||
| 3815 | + let cloudList = $(".cloud-son"); | ||
| 3816 | + let cloudLight = $(".cloud-light"); | ||
| 3817 | + let components = $(".components"); | ||
| 3818 | + let moon = $(".moon"); | ||
| 3819 | + let stars = $(".stars"); | ||
| 3820 | + let star = $(".star"); | ||
| 3821 | + let isMoved = false; | ||
| 3822 | + let isClicked = false; | ||
| 3823 | + | ||
| 3824 | + components.onclick = () => { | ||
| 3825 | + if (isMoved) { | ||
| 3826 | + mainButton.style.transform = "translateX(0)"; | ||
| 3827 | + mainButton.style.backgroundColor = "rgba(255, 195, 35,1)"; | ||
| 3828 | + mainButton.style.boxShadow = "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)"; | ||
| 3829 | + daytimeBackground[0].style.transform = "translateX(0)"; | ||
| 3830 | + daytimeBackground[1].style.transform = "translateX(0)"; | ||
| 3831 | + daytimeBackground[2].style.transform = "translateX(0)"; | ||
| 3832 | + cloud.style.transform = "translateY(10em)"; | ||
| 3833 | + cloudLight.style.transform = "translateY(10em)"; | ||
| 3834 | + components.style.backgroundColor = "rgba(70, 133, 192,1)"; | ||
| 3835 | + moon[0].style.opacity = "0"; | ||
| 3836 | + moon[1].style.opacity = "0"; | ||
| 3837 | + moon[2].style.opacity = "0"; | ||
| 3838 | + stars.style.transform = "translateY(-125em)"; | ||
| 3839 | + stars.style.opacity = "0"; | ||
| 3840 | + changeTheme("light"); | ||
| 3841 | + } else { | ||
| 3842 | + mainButton.style.transform = "translateX(110em)"; | ||
| 3843 | + mainButton.style.backgroundColor = "rgba(195, 200,210,1)"; | ||
| 3844 | + mainButton.style.boxShadow = "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)"; | ||
| 3845 | + daytimeBackground[0].style.transform = "translateX(110em)"; | ||
| 3846 | + daytimeBackground[1].style.transform = "translateX(80em)"; | ||
| 3847 | + daytimeBackground[2].style.transform = "translateX(50em)"; | ||
| 3848 | + cloud.style.transform = "translateY(80em)"; | ||
| 3849 | + cloudLight.style.transform = "translateY(80em)"; | ||
| 3850 | + components.style.backgroundColor = "rgba(25,30,50,1)"; | ||
| 3851 | + moon[0].style.opacity = "1"; | ||
| 3852 | + moon[1].style.opacity = "1"; | ||
| 3853 | + moon[2].style.opacity = "1"; | ||
| 3854 | + stars.style.transform = "translateY(-62.5em)"; | ||
| 3855 | + stars.style.opacity = "1"; | ||
| 3856 | + changeTheme("dark"); | ||
| 3857 | + } | ||
| 3858 | + isClicked = true; | ||
| 3859 | + setTimeout(function () { isClicked = false; }, 500); | ||
| 3860 | + isMoved = !isMoved; | ||
| 3861 | + }; | ||
| 3862 | + | ||
| 3863 | + mainButton.addEventListener("mousemove", function () { | ||
| 3864 | + if (isClicked) return; | ||
| 3865 | + if (isMoved) { | ||
| 3866 | + mainButton.style.transform = "translateX(100em)"; | ||
| 3867 | + daytimeBackground[0].style.transform = "translateX(100em)"; | ||
| 3868 | + daytimeBackground[1].style.transform = "translateX(73em)"; | ||
| 3869 | + daytimeBackground[2].style.transform = "translateX(46em)"; | ||
| 3870 | + star[0].style.top = "10em"; star[0].style.left = "36em"; | ||
| 3871 | + star[1].style.top = "40em"; star[1].style.left = "87em"; | ||
| 3872 | + star[2].style.top = "26em"; star[2].style.left = "16em"; | ||
| 3873 | + star[3].style.top = "38em"; star[3].style.left = "63em"; | ||
| 3874 | + star[4].style.top = "20.5em"; star[4].style.left = "72em"; | ||
| 3875 | + star[5].style.top = "51.5em"; star[5].style.left = "35em"; | ||
| 3876 | + } else { | ||
| 3877 | + mainButton.style.transform = "translateX(10em)"; | ||
| 3878 | + daytimeBackground[0].style.transform = "translateX(10em)"; | ||
| 3879 | + daytimeBackground[1].style.transform = "translateX(7em)"; | ||
| 3880 | + daytimeBackground[2].style.transform = "translateX(4em)"; | ||
| 3881 | + cloudList[0].style.right = "-24em"; cloudList[0].style.bottom = "10em"; | ||
| 3882 | + cloudList[1].style.right = "-12em"; cloudList[1].style.bottom = "-27em"; | ||
| 3883 | + cloudList[2].style.right = "17em"; cloudList[2].style.bottom = "-43em"; | ||
| 3884 | + cloudList[3].style.right = "46em"; cloudList[3].style.bottom = "-39em"; | ||
| 3885 | + cloudList[4].style.right = "70em"; cloudList[4].style.bottom = "-65em"; | ||
| 3886 | + cloudList[5].style.right = "109em"; cloudList[5].style.bottom = "-54em"; | ||
| 3887 | + cloudList[6].style.right = "-23em"; cloudList[6].style.bottom = "10em"; | ||
| 3888 | + cloudList[7].style.right = "-11em"; cloudList[7].style.bottom = "-26em"; | ||
| 3889 | + cloudList[8].style.right = "18em"; cloudList[8].style.bottom = "-42em"; | ||
| 3890 | + cloudList[9].style.right = "47em"; cloudList[9].style.bottom = "-38em"; | ||
| 3891 | + cloudList[10].style.right = "74em"; cloudList[10].style.bottom = "-64em"; | ||
| 3892 | + cloudList[11].style.right = "110em"; cloudList[11].style.bottom = "-55em"; | ||
| 3893 | + } | ||
| 3894 | + }); | ||
| 3895 | + | ||
| 3896 | + mainButton.addEventListener("mouseout", function () { | ||
| 3897 | + if (isClicked) return; | ||
| 3898 | + if (isMoved) { | ||
| 3899 | + mainButton.style.transform = "translateX(110em)"; | ||
| 3900 | + daytimeBackground[0].style.transform = "translateX(110em)"; | ||
| 3901 | + daytimeBackground[1].style.transform = "translateX(80em)"; | ||
| 3902 | + daytimeBackground[2].style.transform = "translateX(50em)"; | ||
| 3903 | + star[0].style.top = "11em"; star[0].style.left = "39em"; | ||
| 3904 | + star[1].style.top = "39em"; star[1].style.left = "91em"; | ||
| 3905 | + star[2].style.top = "26em"; star[2].style.left = "19em"; | ||
| 3906 | + star[3].style.top = "37em"; star[3].style.left = "66em"; | ||
| 3907 | + star[4].style.top = "21em"; star[4].style.left = "75em"; | ||
| 3908 | + star[5].style.top = "51em"; star[5].style.left = "38em"; | ||
| 3909 | + } else { | ||
| 3910 | + mainButton.style.transform = "translateX(0em)"; | ||
| 3911 | + daytimeBackground[0].style.transform = "translateX(0em)"; | ||
| 3912 | + daytimeBackground[1].style.transform = "translateX(0em)"; | ||
| 3913 | + daytimeBackground[2].style.transform = "translateX(0em)"; | ||
| 3914 | + cloudList[0].style.right = "-20em"; cloudList[0].style.bottom = "10em"; | ||
| 3915 | + cloudList[1].style.right = "-10em"; cloudList[1].style.bottom = "-25em"; | ||
| 3916 | + cloudList[2].style.right = "20em"; cloudList[2].style.bottom = "-40em"; | ||
| 3917 | + cloudList[3].style.right = "50em"; cloudList[3].style.bottom = "-35em"; | ||
| 3918 | + cloudList[4].style.right = "75em"; cloudList[4].style.bottom = "-60em"; | ||
| 3919 | + cloudList[5].style.right = "110em"; cloudList[5].style.bottom = "-50em"; | ||
| 3920 | + cloudList[6].style.right = "-20em"; cloudList[6].style.bottom = "10em"; | ||
| 3921 | + cloudList[7].style.right = "-10em"; cloudList[7].style.bottom = "-25em"; | ||
| 3922 | + cloudList[8].style.right = "20em"; cloudList[8].style.bottom = "-40em"; | ||
| 3923 | + cloudList[9].style.right = "50em"; cloudList[9].style.bottom = "-35em"; | ||
| 3924 | + cloudList[10].style.right = "75em"; cloudList[10].style.bottom = "-60em"; | ||
| 3925 | + cloudList[11].style.right = "110em"; cloudList[11].style.bottom = "-50em"; | ||
| 3926 | + } | ||
| 3927 | + }); | ||
| 3928 | + | ||
| 3929 | + const getRandomDirection = () => ["2em", "-2em"][Math.floor(Math.random() * 2)]; | ||
| 3930 | + const moveElementRandomly = (element) => { | ||
| 3931 | + element.style.transform = `translate(${getRandomDirection()}, ${getRandomDirection()})`; | ||
| 3932 | + }; | ||
| 3933 | + const cloudSons = root.querySelectorAll(".cloud-son"); | ||
| 3934 | + setInterval(() => { cloudSons.forEach(moveElementRandomly); }, 1000); | ||
| 3935 | + | ||
| 3936 | + if (initTheme === "dark") { | ||
| 3937 | + components.onclick(); | ||
| 3938 | + } | ||
| 3939 | + }; | ||
| 3940 | + | ||
| 3941 | + class ThemeButton extends HTMLElement { | ||
| 3942 | + constructor() { super(); } | ||
| 3943 | + connectedCallback() { | ||
| 3944 | + const initTheme = this.getAttribute("value") || "light"; | ||
| 3945 | + const size = +this.getAttribute("size") || 3; | ||
| 3946 | + const shadow = this.attachShadow({ mode: "closed" }); | ||
| 3947 | + const container = document.createElement("div"); | ||
| 3948 | + container.setAttribute("class", "container"); | ||
| 3949 | + container.setAttribute("style", `font-size: ${(size / 3).toFixed(2)}px`); | ||
| 3950 | + container.innerHTML = '<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>'; | ||
| 3951 | + const style = document.createElement("style"); | ||
| 3952 | + style.textContent = "* { margin: 0; padding: 0; transition: 0.7s; -webkit-tap-highlight-color:rgba(0,0,0,0); } .container { position: relative; width: 180em; height: 70em; display: inline-block; vertical-align: bottom; transform: translate3d(0, 0, 0); } .components{ position: relative; 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; } .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); }"; | ||
| 3953 | + const changeTheme = (detail) => { | ||
| 3954 | + this.dispatchEvent(new CustomEvent("change", { detail })); | ||
| 3955 | + }; | ||
| 3956 | + themeButtonFunc(container, initTheme, changeTheme); | ||
| 3957 | + shadow.appendChild(style); | ||
| 3958 | + shadow.appendChild(container); | ||
| 3959 | + } | ||
| 3960 | + } | ||
| 3961 | + customElements.define("theme-button", ThemeButton); | ||
| 3962 | +})(); | ||
| 3963 | +/* ========== End Theme Button Web Component ========== */ | ||
| 3964 | + | ||
| 3800 | const chartRegistry = []; | 3965 | const chartRegistry = []; |
| 3801 | const wordCloudRegistry = new Map(); | 3966 | const wordCloudRegistry = new Map(); |
| 3802 | const STABLE_CHART_TYPES = ['line', 'bar']; | 3967 | const STABLE_CHART_TYPES = ['line', 'bar']; |
| @@ -4934,8 +5099,12 @@ document.addEventListener('DOMContentLoaded', () => { | @@ -4934,8 +5099,12 @@ document.addEventListener('DOMContentLoaded', () => { | ||
| 4934 | }, 260); | 5099 | }, 260); |
| 4935 | const themeBtn = document.getElementById('theme-toggle'); | 5100 | const themeBtn = document.getElementById('theme-toggle'); |
| 4936 | if (themeBtn) { | 5101 | if (themeBtn) { |
| 4937 | - themeBtn.addEventListener('click', () => { | ||
| 4938 | - document.body.classList.toggle('dark-mode'); | 5102 | + themeBtn.addEventListener('change', (e) => { |
| 5103 | + if (e.detail === 'dark') { | ||
| 5104 | + document.body.classList.add('dark-mode'); | ||
| 5105 | + } else { | ||
| 5106 | + document.body.classList.remove('dark-mode'); | ||
| 5107 | + } | ||
| 4939 | chartRegistry.forEach(applyChartTheme); | 5108 | chartRegistry.forEach(applyChartTheme); |
| 4940 | rerenderWordclouds(); | 5109 | rerenderWordclouds(); |
| 4941 | }); | 5110 | }); |
-
Please register or login to post a comment