Compare commits

...

4 Commits

Author SHA1 Message Date
Benjamin Wiegand
5254596ce5 fix images not shrinking on mobile 2024-09-08 14:19:05 -07:00
Benjamin Wiegand
bd1e958207 resize image boundary to match aspect ratio to reduce jank 2024-09-08 13:40:36 -07:00
Benjamin Wiegand
ca036ad6ed close image viewer on escape key 2024-09-08 12:45:17 -07:00
Benjamin Wiegand
dc5acea909 reduce cls by fitting thumbnails to 16x9 2024-09-08 12:31:27 -07:00
5 changed files with 89 additions and 31 deletions

View File

@ -5,6 +5,8 @@ for (const image of images) {
const close = image.querySelector('.close') const close = image.querySelector('.close')
const lazy_image = image.querySelector('.lazy-image') const lazy_image = image.querySelector('.lazy-image')
const zoom = modal.querySelector('input') const zoom = modal.querySelector('input')
const open = image.querySelector('input');
const thumbnail = image.querySelector('img');
// for pan // for pan
let grabbed = false; let grabbed = false;
@ -16,47 +18,84 @@ for (const image of images) {
let clickY = 0; let clickY = 0;
let initW = lazy_image.clientWidth; let initW = lazy_image.clientWidth;
let initH = lazy_image.clientHeight; let initH = lazy_image.clientHeight;
// for aspect
function fixAspectRatio() {
let img_aspect = thumbnail.clientWidth / thumbnail.clientHeight
let window_aspect = window.innerWidth / window.innerHeight;
let base = zoom.checked ? 200 : 90;
if (img_aspect > window_aspect) {
// img wider than window
lazy_image.style['min-width'] = base + 'vw';
lazy_image.style['min-height'] = (base * thumbnail.clientHeight / thumbnail.clientWidth) + 'vw';
} else {
// window wider than img
lazy_image.style['min-width'] = (base * img_aspect) + 'vh';
lazy_image.style['min-height'] = base + 'vh';
}
}
thumbnail.addEventListener('load', fixAspectRatio);
// pan the image // pan the image
lazy_image.addEventListener('mouseleave', () => {grabbed = false;}); lazy_image.addEventListener('mouseleave', () => {grabbed = false;});
lazy_image.addEventListener('mouseup', () => { lazy_image.addEventListener('mouseup', () => {
grabbed = false; grabbed = false;
}); });
lazy_image.addEventListener('mousedown', (e) => { lazy_image.addEventListener('mousedown', e => {
grabbed = true; grabbed = true;
startX = modal.scrollLeft + e.pageX; startX = modal.scrollLeft + e.pageX;
startY = modal.scrollTop + e.pageY; startY = modal.scrollTop + e.pageY;
// set stuff for zoom // set stuff for zoom
clickX = e.clientX - lazy_image.offsetLeft; clickX = e.clientX - lazy_image.offsetLeft;
clickY = e.clientY - lazy_image.offsetTop; clickY = e.clientY - lazy_image.offsetTop;
initW = lazy_image.clientWidth; initW = lazy_image.clientWidth;
initH = lazy_image.clientHeight; initH = lazy_image.clientHeight;
}); });
lazy_image.addEventListener('mousemove', (e) => { lazy_image.addEventListener('mousemove', e => {
if(!grabbed) return; if(!grabbed) return;
modal.scrollLeft = startX - e.pageX; modal.scrollLeft = startX - e.pageX;
modal.scrollTop = startY - e.pageY; modal.scrollTop = startY - e.pageY;
}); });
// unzoom on close // unzoom on close
close.addEventListener('click', () => { open.addEventListener('change', () => {
zoom.checked = false; if (!open.checked) zoom.checked = false;
}); });
// zoom to click target // zoom to click target
zoom.addEventListener('change', e => { zoom.addEventListener('change', e => {
fixAspectRatio();
if (zoom.checked) { if (zoom.checked) {
zoom_factor = Math.max( zoom_factor = Math.max(
lazy_image.clientWidth / initW, lazy_image.clientWidth / initW,
lazy_image.clientHeight / initH lazy_image.clientHeight / initH
); );
console.log(zoom_factor);
x = clickX * zoom_factor - (window.innerWidth / 2); x = clickX * zoom_factor - (window.innerWidth / 2);
y = clickY * zoom_factor - (window.innerHeight / 2); y = clickY * zoom_factor - (window.innerHeight / 2);
console.log('zoom 2 ' + x + ', ' + y);
modal.scrollLeft = x; modal.scrollLeft = x;
modal.scrollTop = y; modal.scrollTop = y;
} }
}) });
}
// resize image plane to match image aspect ratio
open.addEventListener('change', e => {
if (open.checked) {
fixAspectRatio();
window.addEventListener('resize', fixAspectRatio);
} else {
window.removeEventListener('resize', fixAspectRatio);
}
});
// close image on escape key
document.addEventListener('keydown', e => {
if (e.key == 'Escape') {
open.checked = false;
zoom.checked = false;
}
});
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -67,9 +67,13 @@
</details> </details>
<div class="double-screenshot"> <div class="double-screenshot">
<div class="project-image"> <div class="project-image">
<label for="lpcl"><img src="/img/peercord-login-thumb.webp" alt="PeerCord login screen"></label> <label for="lpcl" class="thumbnail">
<img src="/img/peercord-login-thumb.webp" alt="PeerCord login screen">
</label>
<input type="checkbox" id="lpcl"> <input type="checkbox" id="lpcl">
<div class="modal"><label for="lpcl" class="modal-bg"></label><label for="lpcl" class="close"></label> <div class="modal">
<label for="lpcl" class="modal-bg"></label>
<label for="lpcl" class="close"></label>
<label> <label>
<input type="checkbox"> <input type="checkbox">
<div class="lazy-image" style="background-image: url('/img/peercord-login.png')"></div> <div class="lazy-image" style="background-image: url('/img/peercord-login.png')"></div>
@ -77,7 +81,7 @@
</div> </div>
</div> </div>
<div class="project-image"> <div class="project-image">
<label for="lpcc"> <label for="lpcc" class="thumbnail">
<img src="/img/peercord-chat-thumb.webp" alt="PeerCord login screen"> <img src="/img/peercord-chat-thumb.webp" alt="PeerCord login screen">
</label> </label>
<input type="checkbox" id="lpcc"> <input type="checkbox" id="lpcc">
@ -111,7 +115,7 @@
</details> </details>
<div class="double-screenshot"> <div class="double-screenshot">
<div class="project-image"> <div class="project-image">
<label for="lio"> <label for="lio" class="thumbnail">
<img src="/img/ilo-overview-thumb.webp" alt="overview of my ILO dashboard in grafana"> <img src="/img/ilo-overview-thumb.webp" alt="overview of my ILO dashboard in grafana">
</label> </label>
<input type="checkbox" id="lio"> <input type="checkbox" id="lio">
@ -125,7 +129,7 @@
</div> </div>
</div> </div>
<div class="project-image"> <div class="project-image">
<label for="lit"> <label for="lit" class="thumbnail">
<img src="/img/ilo-temperatures-thumb.webp" alt="temperature sensor data shown in my ILO dashboard in grafana"> <img src="/img/ilo-temperatures-thumb.webp" alt="temperature sensor data shown in my ILO dashboard in grafana">
</label> </label>
<input type="checkbox" id="lit"> <input type="checkbox" id="lit">
@ -139,7 +143,7 @@
</div> </div>
</div> </div>
<div class="project-image"> <div class="project-image">
<label for="lid"> <label for="lid" class="thumbnail">
<img src="/img/ilo-drives-thumb.webp" alt="drive health, status, and temperature shown in my ILO dashboard in grafana"> <img src="/img/ilo-drives-thumb.webp" alt="drive health, status, and temperature shown in my ILO dashboard in grafana">
</label> </label>
<input type="checkbox" id="lid"> <input type="checkbox" id="lid">
@ -153,7 +157,7 @@
</div> </div>
</div> </div>
<div class="project-image"> <div class="project-image">
<label for="lifci"> <label for="lifci" class="thumbnail">
<img src="/img/ilo-fan-and-cpu-info-thumb.webp" alt="fan speed, fan health, fan status, and cpu status shown in my ILO dashboard in grafana"> <img src="/img/ilo-fan-and-cpu-info-thumb.webp" alt="fan speed, fan health, fan status, and cpu status shown in my ILO dashboard in grafana">
</label> </label>
<input type="checkbox" id="lifci"> <input type="checkbox" id="lifci">
@ -187,7 +191,7 @@
</details> </details>
<div class="double-screenshot"> <div class="double-screenshot">
<div class="project-image"> <div class="project-image">
<label for="sma"> <label for="sma" class="thumbnail">
<img src="/img/smbus-mitm-arduino-thumb.webp" alt="the arduino leonardo that's attached to my battery, complete with small OLED display"> <img src="/img/smbus-mitm-arduino-thumb.webp" alt="the arduino leonardo that's attached to my battery, complete with small OLED display">
</label> </label>
<input type="checkbox" id="sma"> <input type="checkbox" id="sma">
@ -201,7 +205,7 @@
</div> </div>
</div> </div>
<div class="project-image"> <div class="project-image">
<label for="smw"> <label for="smw" class="thumbnail">
<img src="/img/smbus-mitm-wiring-thumb.webp" alt="wiring to intercept communications between the BMS and the laptop"> <img src="/img/smbus-mitm-wiring-thumb.webp" alt="wiring to intercept communications between the BMS and the laptop">
</label> </label>
<input type="checkbox" id="smw"> <input type="checkbox" id="smw">
@ -229,7 +233,7 @@
</details> </details>
<div class="double-screenshot"> <div class="double-screenshot">
<div class="project-image"> <div class="project-image">
<label for="scst"> <label for="scst" class="thumbnail">
<img src="/img/security-camera-stream-thumb.webp" alt="two phones, one streaming video to another over the network"> <img src="/img/security-camera-stream-thumb.webp" alt="two phones, one streaming video to another over the network">
</label> </label>
<input type="checkbox" id="scst"> <input type="checkbox" id="scst">
@ -243,7 +247,7 @@
</div> </div>
</div> </div>
<div class="project-image"> <div class="project-image">
<label for="scsc"> <label for="scsc" class="thumbnail no-crop">
<img src="/img/security-camera-screenshot-thumb.webp" alt="screenshot of the app while it's recording video"> <img src="/img/security-camera-screenshot-thumb.webp" alt="screenshot of the app while it's recording video">
</label> </label>
<input type="checkbox" id="scsc"> <input type="checkbox" id="scsc">
@ -272,7 +276,7 @@
<div class="double-screenshot"> <div class="double-screenshot">
<div class="project-image"> <div class="project-image">
<label for="r"> <label for="r" class="thumbnail">
<img src="/img/roomba-thumb.webp" alt="a normal Roomba with a webcam, Raspberry pi, Arduino, and a voltage regulator mounted on it"> <img src="/img/roomba-thumb.webp" alt="a normal Roomba with a webcam, Raspberry pi, Arduino, and a voltage regulator mounted on it">
</label> </label>
<input type="checkbox" id="r"> <input type="checkbox" id="r">
@ -286,7 +290,7 @@
</div> </div>
</div> </div>
<div class="project-image"> <div class="project-image">
<label for="rc"> <label for="rc" class="thumbnail">
<img src="/img/roomba-control-thumb.webp" alt="webpage for controlling the Roomba and viewing the live feed"> <img src="/img/roomba-control-thumb.webp" alt="webpage for controlling the Roomba and viewing the live feed">
</label> </label>
<input type="checkbox" id="rc"> <input type="checkbox" id="rc">

View File

@ -187,20 +187,37 @@ h3 {
align-items: center; align-items: center;
} }
.double-screenshot img { .double-screenshot .thumbnail {
width: 450px; display: flex;
align-items: center;
justify-content: center;
width: 444px;
max-width: calc(min(450px,calc(100vw - 100px)));
max-height: 253.125px;
overflow: hidden;
margin: 3px;
cursor: pointer;
}
.double-screenshot .thumbnail img {
min-width: calc(min(450px,calc(100vw - 100px)));
min-height: calc(min(450px,calc(100vw - 100px)) * 0.5625);
}
.double-screenshot .no-crop img {
min-width: auto;
max-width: calc(min(450px,calc(100vw - 100px)));
min-height: auto;
max-height: 253.125px;
}
.project-image {
max-width: 100%; max-width: 100%;
vertical-align: middle;
} }
.project-image input { .project-image input {
display: none; display: none;
} }
.project-image img {
cursor: pointer;
}
.modal { .modal {
display: none; display: none;
} }
@ -220,8 +237,6 @@ input:checked + .modal {
} }
.lazy-image { .lazy-image {
width: 500px;
height: 500px;
min-width: 90vw; min-width: 90vw;
min-height: 90vh; min-height: 90vh;
background-size: contain; background-size: contain;