|
95 | 95 | {{ end }} |
96 | 96 |
|
97 | 97 | <style> |
98 | | -@media screen and (min-width: 769px) { |
99 | | - /* .post-content is a class which will be present only on single pages |
100 | | - and not lists and section pages in Hugo */ |
101 | | - .page-content input[type="checkbox"]:checked ~ label > img { |
102 | | - transform: scale(1.6); |
103 | | - cursor: zoom-out; |
104 | | - position: relative; |
105 | | - z-index: 999; |
106 | | - } |
| 98 | +img.zoomable { |
| 99 | + cursor: zoom-in; |
| 100 | +} |
107 | 101 |
|
108 | | - .page-content img.zoomCheck { |
109 | | - transition: transform 0.15s ease; |
110 | | - z-index: 999; |
111 | | - cursor: zoom-in; |
112 | | - } |
| 102 | +.zoom-overlay { |
| 103 | + position: fixed; |
| 104 | + inset: 0; |
| 105 | + z-index: 9998; |
| 106 | + background: rgba(0, 0, 0, 0.9); |
| 107 | + opacity: 0; |
| 108 | + transition: opacity 0.3s cubic-bezier(0.2, 0, 0.2, 1); |
| 109 | + cursor: zoom-out; |
| 110 | +} |
| 111 | + |
| 112 | +.zoom-overlay.active { |
| 113 | + opacity: 1; |
| 114 | +} |
| 115 | + |
| 116 | +.zoom-clone { |
| 117 | + position: fixed; |
| 118 | + z-index: 9999; |
| 119 | + cursor: zoom-out; |
| 120 | + will-change: transform; |
| 121 | + transition: transform 0.3s cubic-bezier(0.2, 0, 0.2, 1); |
113 | 122 | } |
114 | 123 | </style> |
| 124 | +<script> |
| 125 | +(function () { |
| 126 | + var overlay, clone, sourceImg, scrollStart, animating; |
| 127 | + |
| 128 | + function open(img) { |
| 129 | + if (animating || overlay) return; |
| 130 | + animating = true; |
| 131 | + sourceImg = img; |
| 132 | + scrollStart = window.scrollY; |
| 133 | + |
| 134 | + // Hide original to avoid doubling |
| 135 | + sourceImg.style.visibility = 'hidden'; |
| 136 | + |
| 137 | + // Create overlay backdrop |
| 138 | + overlay = document.createElement('div'); |
| 139 | + overlay.className = 'zoom-overlay'; |
| 140 | + document.body.appendChild(overlay); |
| 141 | + |
| 142 | + // Create clone at exact position of original |
| 143 | + var rect = img.getBoundingClientRect(); |
| 144 | + clone = document.createElement('img'); |
| 145 | + clone.src = img.src; |
| 146 | + clone.alt = img.alt; |
| 147 | + clone.className = 'zoom-clone'; |
| 148 | + clone.style.top = rect.top + 'px'; |
| 149 | + clone.style.left = rect.left + 'px'; |
| 150 | + clone.style.width = rect.width + 'px'; |
| 151 | + clone.style.height = rect.height + 'px'; |
| 152 | + document.body.appendChild(clone); |
| 153 | + |
| 154 | + // Force reflow, then animate |
| 155 | + clone.offsetHeight; |
| 156 | + overlay.classList.add('active'); |
| 157 | + |
| 158 | + // Calculate transform to center and scale |
| 159 | + var scale = Math.min( |
| 160 | + (window.innerWidth * 0.95) / rect.width, |
| 161 | + (window.innerHeight * 0.95) / rect.height |
| 162 | + ); |
| 163 | + var translateX = (window.innerWidth / 2) - (rect.left + rect.width / 2); |
| 164 | + var translateY = (window.innerHeight / 2) - (rect.top + rect.height / 2); |
| 165 | + |
| 166 | + clone.style.transform = 'translate(' + translateX + 'px, ' + translateY + 'px) scale(' + scale + ')'; |
| 167 | + |
| 168 | + clone.addEventListener('transitionend', function () { |
| 169 | + animating = false; |
| 170 | + }, { once: true }); |
| 171 | + } |
| 172 | + |
| 173 | + function close() { |
| 174 | + if (animating || !overlay) return; |
| 175 | + animating = true; |
| 176 | + |
| 177 | + overlay.classList.remove('active'); |
| 178 | + |
| 179 | + // Animate clone back to original position (accounting for scroll change) |
| 180 | + var scrollDelta = window.scrollY - scrollStart; |
| 181 | + clone.style.transform = 'translate(0, ' + (-scrollDelta) + 'px) scale(1)'; |
| 182 | + |
| 183 | + clone.addEventListener('transitionend', function () { |
| 184 | + overlay.remove(); |
| 185 | + clone.remove(); |
| 186 | + sourceImg.style.visibility = ''; |
| 187 | + overlay = clone = sourceImg = null; |
| 188 | + animating = false; |
| 189 | + }, { once: true }); |
| 190 | + } |
| 191 | + |
| 192 | + document.addEventListener('click', function (e) { |
| 193 | + if (overlay) { close(); return; } |
| 194 | + var img = e.target.closest('img.zoomable'); |
| 195 | + if (img) open(img); |
| 196 | + }); |
| 197 | + |
| 198 | + document.addEventListener('keydown', function (e) { |
| 199 | + if (e.key === 'Escape') close(); |
| 200 | + }); |
| 201 | + |
| 202 | + // Scroll to dismiss |
| 203 | + window.addEventListener('scroll', function () { |
| 204 | + if (!overlay || animating) return; |
| 205 | + if (Math.abs(window.scrollY - scrollStart) > 50) close(); |
| 206 | + }, { passive: true }); |
| 207 | +})(); |
| 208 | +</script> |
0 commit comments