diff --git a/www/image-modal.js b/www/image-modal.js new file mode 100644 index 0000000..bdd696c --- /dev/null +++ b/www/image-modal.js @@ -0,0 +1,62 @@ +const images = document.getElementsByClassName('project-image'); + +for (const image of images) { + const modal = image.querySelector('.modal') + const close = image.querySelector('.close') + const lazy_image = image.querySelector('.lazy-image') + const zoom = modal.querySelector('input') + + // for pan + let grabbed = false; + let startX = 0; + let startY = 0; + + // for zoom + let clickX = 0; + let clickY = 0; + let initW = lazy_image.clientWidth; + let initH = lazy_image.clientHeight; + + // pan the image + lazy_image.addEventListener('mouseleave', () => {grabbed = false;}); + lazy_image.addEventListener('mouseup', () => { + grabbed = false; + }); + lazy_image.addEventListener('mousedown', (e) => { + grabbed = true; + startX = modal.scrollLeft + e.pageX; + startY = modal.scrollTop + e.pageY; + + // set stuff for zoom + clickX = e.clientX - lazy_image.offsetLeft; + clickY = e.clientY - lazy_image.offsetTop; + initW = lazy_image.clientWidth; + initH = lazy_image.clientHeight; + }); + lazy_image.addEventListener('mousemove', (e) => { + if(!grabbed) return; + modal.scrollLeft = startX - e.pageX; + modal.scrollTop = startY - e.pageY; + }); + + // unzoom on close + close.addEventListener('click', () => { + zoom.checked = false; + }); + + // zoom to click target + zoom.addEventListener('change', e => { + if (zoom.checked) { + zoom_factor = Math.max( + lazy_image.clientWidth / initW, + lazy_image.clientHeight / initH + ); + console.log(zoom_factor); + x = clickX * zoom_factor - (window.innerWidth / 2); + y = clickY * zoom_factor - (window.innerHeight / 2); + console.log('zoom 2 ' + x + ', ' + y); + modal.scrollLeft = x; + modal.scrollTop = y; + } + }) +} \ No newline at end of file diff --git a/www/img/modal-close.svg b/www/img/modal-close.svg new file mode 100644 index 0000000..4537467 --- /dev/null +++ b/www/img/modal-close.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + diff --git a/www/index.html b/www/index.html index f55297c..4b840ff 100644 --- a/www/index.html +++ b/www/index.html @@ -55,7 +55,7 @@

Projects

- +

PeerCord (2023)

An end-to-end encrypted client/server messaging application.

@@ -66,7 +66,30 @@

- PeerCord login screenPeerCord chat screen +
+ + + +
+
+ + + +
click image to view in full resolution
@@ -87,10 +110,62 @@

- overview of my ILO dashboard in grafana - temperature sensor data shown in my ILO dashboard in grafana - drive health, status, and temperature shown in my ILO dashboard in grafana - fan speed, fan health, fan status, and cpu status shown in my ILO dashboard in grafana +
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
click image to view in full resolution
@@ -111,7 +186,34 @@

- the arduino leonardo that's attached to my battery, complete with small OLED displaywiring to intercept communications between the BMS and the laptop +
+ + + +
+
+ + + +
click image to view in full resolution @@ -126,7 +228,34 @@

- two phones, one streaming video to another over the networkscreenshot of the app while it's recording video +
+ + + +
+
+ + + +
click image to view in full resolution @@ -142,11 +271,39 @@
- a normal Roomba with a webcam, Raspberry pi, Arduino, and a voltage regulator mounted on itwebpage for controlling the Roomba and viewing the live feed +
+ + + +
+
+ + + +
click image to view in full resolution + diff --git a/www/style.css b/www/style.css index 614357a..531d20a 100644 --- a/www/style.css +++ b/www/style.css @@ -190,9 +190,81 @@ h3 { .double-screenshot img { width: 450px; max-width: 100%; + vertical-align: middle; } -.text-section * { +.project-image input { + display: none; +} + +.project-image img { + cursor: pointer; +} + +.modal { + display: none; +} + +input:checked + .modal { + animation: fly-forward .5s ease-out 0s 1 normal none; + display: flex; + justify-content: safe center; + align-items: safe center; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #00000066; + overflow: auto; +} + +.lazy-image { + width: 500px; + height: 500px; + min-width: 90vw; + min-height: 90vh; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + cursor: zoom-in; +} + +input:checked + .lazy-image { + cursor: zoom-out; + min-width: 200vw; + min-height: 200vh; + scroll-snap-align: center; +} + +body:has(.project-image > input:checked) { + overflow: hidden; +} + +.modal .close { + cursor: pointer; + position: fixed; + top: 0; + right: 0; + margin: 20px; + width: 60px; + height: 60px; + background-image: url('/img/modal-close.svg'); + background-size: 30px 30px; + background-position: center; + background-repeat: no-repeat; +} + +.modal-bg { + position: fixed; + z-index: -1; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.text-section > * { animation: fly-up .5s ease-out 0s 1 normal none; } @@ -230,6 +302,23 @@ h3 { } +@keyframes fly-forward { + 0% { + transform: scale(0); + opacity: 0%; + } + + 20% { + transform: scale(1); + opacity: 70%; + } + + 100% { + opacity: 100%; + } + +} + @keyframes color-change-1 { 0% { background-color: #29BDBD;