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 |
173
www/index.html
173
www/index.html
@ -66,7 +66,30 @@
|
|||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<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>
|
</div>
|
||||||
<small>click image to view in full resolution</small>
|
<small>click image to view in full resolution</small>
|
||||||
</div>
|
</div>
|
||||||
@ -87,10 +110,62 @@
|
|||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<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>
|
<div class="project-image">
|
||||||
<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>
|
<label for="lio">
|
||||||
<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>
|
<img src="/img/ilo-overview-thumb.webp" alt="overview of my ILO dashboard in grafana">
|
||||||
<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>
|
</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>
|
</div>
|
||||||
<small>click image to view in full resolution</small>
|
<small>click image to view in full resolution</small>
|
||||||
</div>
|
</div>
|
||||||
@ -111,7 +186,34 @@
|
|||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<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>
|
</div>
|
||||||
<small>click image to view in full resolution</small>
|
<small>click image to view in full resolution</small>
|
||||||
</div>
|
</div>
|
||||||
@ -126,7 +228,34 @@
|
|||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<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>
|
</div>
|
||||||
<small>click image to view in full resolution</small>
|
<small>click image to view in full resolution</small>
|
||||||
</div>
|
</div>
|
||||||
@ -142,11 +271,39 @@
|
|||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<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>
|
</div>
|
||||||
<small>click image to view in full resolution</small>
|
<small>click image to view in full resolution</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="/image-modal.js"></script>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -190,9 +190,81 @@ h3 {
|
|||||||
.double-screenshot img {
|
.double-screenshot img {
|
||||||
width: 450px;
|
width: 450px;
|
||||||
max-width: 100%;
|
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;
|
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 {
|
@keyframes color-change-1 {
|
||||||
0% {
|
0% {
|
||||||
background-color: #29BDBD;
|
background-color: #29BDBD;
|
||||||
|
Loading…
Reference in New Issue
Block a user