add a crappy image viewer that "90% works" without js
This commit is contained in:
parent
e470c4b6eb
commit
09134e8c36
62
www/image-modal.js
Normal file
62
www/image-modal.js
Normal file
@ -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;
|
||||
}
|
||||
})
|
||||
}
|
63
www/img/modal-close.svg
Normal file
63
www/img/modal-close.svg
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="120"
|
||||
height="120"
|
||||
viewBox="0 0 120 120"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
|
||||
sodipodi:docname="modal-close.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:zoom="4.8790368"
|
||||
inkscape:cx="48.165245"
|
||||
inkscape:cy="57.183418"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1010"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="16"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:34.7;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 24.536613,95.463387 95.463387,24.536613"
|
||||
id="path1" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:34.7;stroke-linecap:square;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 24.536613,24.536613 95.463387,95.463387"
|
||||
id="path2" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Layer 2">
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:13;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:5.4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 24.536606,95.463385 95.463385,24.536606"
|
||||
id="path1-5" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:13;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:5.4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 24.536606,24.536606 95.463385,95.463385"
|
||||
id="path2-3" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
175
www/index.html
175
www/index.html
@ -55,7 +55,7 @@
|
||||
|
||||
<div class="projects-section text-section">
|
||||
<h2>Projects</h2>
|
||||
|
||||
|
||||
<div class="project sub-section">
|
||||
<h3>PeerCord <small>(2023)</small></h3>
|
||||
<p>An end-to-end encrypted client/server messaging application.</p>
|
||||
@ -66,7 +66,30 @@
|
||||
</p>
|
||||
</details>
|
||||
<div class="double-screenshot">
|
||||
<a target="_blank" href="/img/peercord-login.png"><img src="/img/peercord-login-thumb.webp" alt="PeerCord login screen"></a><a target="_blank" href="/img/peercord-chat.png"><img src="/img/peercord-chat-thumb.webp" alt="PeerCord chat screen"></a>
|
||||
<div class="project-image">
|
||||
<label for="lpcl"><img src="/img/peercord-login-thumb.webp" alt="PeerCord login screen"></label>
|
||||
<input type="checkbox" id="lpcl">
|
||||
<div class="modal"><label for="lpcl" class="modal-bg"></label><label for="lpcl" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/peercord-login.png')"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-image">
|
||||
<label for="lpcc">
|
||||
<img src="/img/peercord-chat-thumb.webp" alt="PeerCord login screen">
|
||||
</label>
|
||||
<input type="checkbox" id="lpcc">
|
||||
<div class="modal">
|
||||
<label for="lpcc" class="modal-bg"></label>
|
||||
<label for="lpcc" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/peercord-chat.png')"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<small>click image to view in full resolution</small>
|
||||
</div>
|
||||
@ -87,10 +110,62 @@
|
||||
</p>
|
||||
</details>
|
||||
<div class="double-screenshot">
|
||||
<a target="_blank" href="/img/ilo-overview.jpg"><img src="/img/ilo-overview-thumb.webp" alt="overview of my ILO dashboard in grafana"></a>
|
||||
<a target="_blank" href="/img/ilo-temperatures.jpg"><img src="/img/ilo-temperatures-thumb.webp" alt="temperature sensor data shown in my ILO dashboard in grafana"></a>
|
||||
<a target="_blank" href="/img/ilo-drives.jpg"><img src="/img/ilo-drives-thumb.webp" alt="drive health, status, and temperature shown in my ILO dashboard in grafana"></a>
|
||||
<a target="_blank" href="/img/ilo-fan-and-cpu-info.jpg"><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"></a>
|
||||
<div class="project-image">
|
||||
<label for="lio">
|
||||
<img src="/img/ilo-overview-thumb.webp" alt="overview of my ILO dashboard in grafana">
|
||||
</label>
|
||||
<input type="checkbox" id="lio">
|
||||
<div class="modal">
|
||||
<label for="lio" class="modal-bg"></label>
|
||||
<label for="lio" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/ilo-overview.jpg');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-image">
|
||||
<label for="lit">
|
||||
<img src="/img/ilo-temperatures-thumb.webp" alt="temperature sensor data shown in my ILO dashboard in grafana">
|
||||
</label>
|
||||
<input type="checkbox" id="lit">
|
||||
<div class="modal">
|
||||
<label for="lit" class="modal-bg"></label>
|
||||
<label for="lit" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/ilo-temperatures.jpg');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-image">
|
||||
<label for="lid">
|
||||
<img src="/img/ilo-drives-thumb.webp" alt="drive health, status, and temperature shown in my ILO dashboard in grafana">
|
||||
</label>
|
||||
<input type="checkbox" id="lid">
|
||||
<div class="modal">
|
||||
<label for="lid" class="modal-bg"></label>
|
||||
<label for="lid" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/ilo-drives.jpg');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-image">
|
||||
<label for="lifci">
|
||||
<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>
|
||||
<input type="checkbox" id="lifci">
|
||||
<div class="modal">
|
||||
<label for="lifci" class="modal-bg"></label>
|
||||
<label for="lifci" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/ilo-fan-and-cpu-info.jpg');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<small>click image to view in full resolution</small>
|
||||
</div>
|
||||
@ -111,7 +186,34 @@
|
||||
</p>
|
||||
</details>
|
||||
<div class="double-screenshot">
|
||||
<a target="_blank" href="/img/smbus-mitm-arduino.jpg"><img src="/img/smbus-mitm-arduino-thumb.webp" alt="the arduino leonardo that's attached to my battery, complete with small OLED display"></a><a target="_blank" href="/img/smbus-mitm-wiring.jpg"><img src="/img/smbus-mitm-wiring-thumb.webp" alt="wiring to intercept communications between the BMS and the laptop"></a>
|
||||
<div class="project-image">
|
||||
<label for="sma">
|
||||
<img src="/img/smbus-mitm-arduino-thumb.webp" alt="the arduino leonardo that's attached to my battery, complete with small OLED display">
|
||||
</label>
|
||||
<input type="checkbox" id="sma">
|
||||
<div class="modal">
|
||||
<label for="sma" class="modal-bg"></label>
|
||||
<label for="sma" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/smbus-mitm-arduino.jpg');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-image">
|
||||
<label for="smw">
|
||||
<img src="/img/smbus-mitm-wiring-thumb.webp" alt="wiring to intercept communications between the BMS and the laptop">
|
||||
</label>
|
||||
<input type="checkbox" id="smw">
|
||||
<div class="modal">
|
||||
<label for="smw" class="modal-bg"></label>
|
||||
<label for="smw" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/smbus-mitm-wiring.jpg');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<small>click image to view in full resolution</small>
|
||||
</div>
|
||||
@ -126,7 +228,34 @@
|
||||
</p>
|
||||
</details>
|
||||
<div class="double-screenshot">
|
||||
<a target="_blank" href="/img/security-camera-stream.jpg"><img src="/img/security-camera-stream-thumb.webp" alt="two phones, one streaming video to another over the network"></a><a target="_blank" href="/img/security-camera-screenshot.png"><img src="/img/security-camera-screenshot-thumb.webp" alt="screenshot of the app while it's recording video"></a>
|
||||
<div class="project-image">
|
||||
<label for="scst">
|
||||
<img src="/img/security-camera-stream-thumb.webp" alt="two phones, one streaming video to another over the network">
|
||||
</label>
|
||||
<input type="checkbox" id="scst">
|
||||
<div class="modal">
|
||||
<label for="scst" class="modal-bg"></label>
|
||||
<label for="scst" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/security-camera-stream.jpg');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-image">
|
||||
<label for="scsc">
|
||||
<img src="/img/security-camera-screenshot-thumb.webp" alt="screenshot of the app while it's recording video">
|
||||
</label>
|
||||
<input type="checkbox" id="scsc">
|
||||
<div class="modal">
|
||||
<label for="scsc" class="modal-bg"></label>
|
||||
<label for="scsc" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/security-camera-screenshot.png');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<small>click image to view in full resolution</small>
|
||||
</div>
|
||||
@ -142,11 +271,39 @@
|
||||
</details>
|
||||
<div class="double-screenshot">
|
||||
|
||||
<a target="_blank" href="/img/roomba.jpg"><img src="/img/roomba-thumb.webp" alt="a normal Roomba with a webcam, Raspberry pi, Arduino, and a voltage regulator mounted on it"></a><a target="_blank" href="/img/roomba-control.jpg"><img src="/img/roomba-control-thumb.webp" alt="webpage for controlling the Roomba and viewing the live feed"></a>
|
||||
<div class="project-image">
|
||||
<label for="r">
|
||||
<img src="/img/roomba-thumb.webp" alt="a normal Roomba with a webcam, Raspberry pi, Arduino, and a voltage regulator mounted on it">
|
||||
</label>
|
||||
<input type="checkbox" id="r">
|
||||
<div class="modal">
|
||||
<label for="r" class="modal-bg"></label>
|
||||
<label for="r" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/roomba.jpg');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="project-image">
|
||||
<label for="rc">
|
||||
<img src="/img/roomba-control-thumb.webp" alt="webpage for controlling the Roomba and viewing the live feed">
|
||||
</label>
|
||||
<input type="checkbox" id="rc">
|
||||
<div class="modal">
|
||||
<label for="rc" class="modal-bg"></label>
|
||||
<label for="rc" class="close"></label>
|
||||
<label>
|
||||
<input type="checkbox">
|
||||
<div class="lazy-image" style="background-image: url('/img/roomba-control.jpg');"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<small>click image to view in full resolution</small>
|
||||
</div>
|
||||
|
||||
<script src="/image-modal.js"></script>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user