improve image modals
This commit is contained in:
parent
a88483796f
commit
05d9c9de42
@ -5,7 +5,6 @@ for (const image of images) {
|
|||||||
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 open = image.querySelector('input');
|
||||||
const thumbnail = image.querySelector('img');
|
|
||||||
|
|
||||||
// for pan
|
// for pan
|
||||||
let grabbed = false;
|
let grabbed = false;
|
||||||
@ -18,24 +17,6 @@ for (const image of images) {
|
|||||||
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', () => {
|
||||||
@ -65,7 +46,6 @@ for (const image of images) {
|
|||||||
|
|
||||||
// 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,
|
||||||
@ -78,16 +58,6 @@ for (const image of images) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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
|
// close image on escape key
|
||||||
document.addEventListener('keydown', e => {
|
document.addEventListener('keydown', e => {
|
||||||
if (e.key == 'Escape') {
|
if (e.key == 'Escape') {
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
  PeerCord is a project I worked on during freshman year with my fellow classmates at University of The Pacific for the Application Design course. It is an end-to-end alternative to the popular chat app known as Discord. It has a similar server/client model, but the key advantage over Discord is that the messages are end-to-end encrypted keeping them private from even the server that hosts Peercord, or any data breaches. It is written 100% in Java, per the course requirements. It was a very large project and my key role was to write the entire server application. I also wrote the code to connect the client to the server. We completed the project and did very well.
|
  PeerCord is a project I worked on during freshman year with my fellow classmates at University of The Pacific for the Application Design course. It is an end-to-end alternative to the popular chat app known as Discord. It has a similar server/client model, but the key advantage over Discord is that the messages are end-to-end encrypted keeping them private from even the server that hosts Peercord, or any data breaches. It is written 100% in Java, per the course requirements. It was a very large project and my key role was to write the entire server application. I also wrote the code to connect the client to the server. We completed the project and did very well.
|
||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<div class="screenshot-collection">
|
||||||
<div class="project-image">
|
<div class="project-image">
|
||||||
<label for="lpcl" class="thumbnail">
|
<label for="lpcl" class="thumbnail">
|
||||||
<img src="/img/peercord-login-thumb.webp" alt="PeerCord login screen">
|
<img src="/img/peercord-login-thumb.webp" alt="PeerCord login screen">
|
||||||
@ -80,7 +80,7 @@
|
|||||||
<label for="lpcl" class="close"></label>
|
<label for="lpcl" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/peercord-login.png')"></span>
|
<span class="lazy-image" id="lpcl-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -94,7 +94,7 @@
|
|||||||
<label for="lpcc" class="close"></label>
|
<label for="lpcc" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/peercord-chat.png')"></span>
|
<span class="lazy-image" id="lpcc-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -117,7 +117,7 @@
|
|||||||
  I also took the time to make this project publicly available too. You can view the source code <a href="https://github.com/Benjamin-Wiegand/ilo_exporter" target="_blank">on GitHub</a> or <a href="https://git.wiegand.pw/ben/fast_ilo_exporter" target="_blank">my personal git server</a>.
|
  I also took the time to make this project publicly available too. You can view the source code <a href="https://github.com/Benjamin-Wiegand/ilo_exporter" target="_blank">on GitHub</a> or <a href="https://git.wiegand.pw/ben/fast_ilo_exporter" target="_blank">my personal git server</a>.
|
||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<div class="screenshot-collection">
|
||||||
<div class="project-image">
|
<div class="project-image">
|
||||||
<label for="lio" class="thumbnail">
|
<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">
|
||||||
@ -128,7 +128,7 @@
|
|||||||
<label for="lio" class="close"></label>
|
<label for="lio" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/ilo-overview.jpg');"></span>
|
<span class="lazy-image" id="lio-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -142,7 +142,7 @@
|
|||||||
<label for="lit" class="close"></label>
|
<label for="lit" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/ilo-temperatures.jpg');"></span>
|
<span class="lazy-image" id="lit-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -156,7 +156,7 @@
|
|||||||
<label for="lid" class="close"></label>
|
<label for="lid" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/ilo-drives.jpg');"></span>
|
<span class="lazy-image" id="lid-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -170,7 +170,7 @@
|
|||||||
<label for="lifci" class="close"></label>
|
<label for="lifci" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/ilo-fan-and-cpu-info.jpg');"></span>
|
<span class="lazy-image" id="lifci-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -193,7 +193,7 @@
|
|||||||
  Using this knowledge, I added an Arduino which captures and relays the data sent between the laptop and the BMS. The Arduino also requests and captures some extra information intended for the laptop's EC (embedded controller). This information includes cell voltages, temperature, instant pack voltage, instant current draw, charge/discharge cycle count, alarms, and more, some of which is very useful for verifying the health, age, and balance of my custom battery pack. Finally, I added a small OLED display and a button to show all this info without needing a USB serial cable.
|
  Using this knowledge, I added an Arduino which captures and relays the data sent between the laptop and the BMS. The Arduino also requests and captures some extra information intended for the laptop's EC (embedded controller). This information includes cell voltages, temperature, instant pack voltage, instant current draw, charge/discharge cycle count, alarms, and more, some of which is very useful for verifying the health, age, and balance of my custom battery pack. Finally, I added a small OLED display and a button to show all this info without needing a USB serial cable.
|
||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<div class="screenshot-collection">
|
||||||
<div class="project-image">
|
<div class="project-image">
|
||||||
<label for="sma" class="thumbnail">
|
<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">
|
||||||
@ -204,7 +204,7 @@
|
|||||||
<label for="sma" class="close"></label>
|
<label for="sma" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/smbus-mitm-arduino.jpg');"></span>
|
<span class="lazy-image" id="sma-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -218,7 +218,7 @@
|
|||||||
<label for="smw" class="close"></label>
|
<label for="smw" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/smbus-mitm-wiring.jpg');"></span>
|
<span class="lazy-image" id="smw-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -235,7 +235,7 @@
|
|||||||
  This is a project I worked on for my AP Computer Programming course in highschool. I wrote an Android app in Java which turns any Android smartphone into a security camera. It syncs with a server (also written in Java) over an encrypted TCP connection to store recordings and motion events. The cameras can also be viewed live by another phone over an encrypted UDP connection. This differs from many readily-available solutions as the server is on your local network, ensuring the likely very personal footage can only be viewed by you. Additionally, the recordings still happen even if the network drops out, unlike with traditional IP cameras.
|
  This is a project I worked on for my AP Computer Programming course in highschool. I wrote an Android app in Java which turns any Android smartphone into a security camera. It syncs with a server (also written in Java) over an encrypted TCP connection to store recordings and motion events. The cameras can also be viewed live by another phone over an encrypted UDP connection. This differs from many readily-available solutions as the server is on your local network, ensuring the likely very personal footage can only be viewed by you. Additionally, the recordings still happen even if the network drops out, unlike with traditional IP cameras.
|
||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<div class="screenshot-collection">
|
||||||
<div class="project-image">
|
<div class="project-image">
|
||||||
<label for="scst" class="thumbnail">
|
<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">
|
||||||
@ -246,7 +246,7 @@
|
|||||||
<label for="scst" class="close"></label>
|
<label for="scst" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/security-camera-stream.jpg');"></span>
|
<span class="lazy-image" id="scst-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -260,7 +260,7 @@
|
|||||||
<label for="scsc" class="close"></label>
|
<label for="scsc" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/security-camera-screenshot.png');"></span>
|
<span class="lazy-image" id="scsc-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -277,7 +277,7 @@
|
|||||||
  This is a personal project I worked on in middle school where I wanted to remotely control my Roomba from my laptop with a video feed. I connected an Arduino to the Roomba's diagnostic port, paired with a Raspberry pi running an Apache2 web server with PHP and a motion video server. The pi hosts a website over Wi-Fi which allows any modern web browser to view the video feed and send serial commands to the Arduino. The Arduino then sends its own commands outlined in iRobot's SCI specification to carry out control of the Roomba. The Arduino also receives and parses data from the Roomba for safety features such as cliff detection.
|
  This is a personal project I worked on in middle school where I wanted to remotely control my Roomba from my laptop with a video feed. I connected an Arduino to the Roomba's diagnostic port, paired with a Raspberry pi running an Apache2 web server with PHP and a motion video server. The pi hosts a website over Wi-Fi which allows any modern web browser to view the video feed and send serial commands to the Arduino. The Arduino then sends its own commands outlined in iRobot's SCI specification to carry out control of the Roomba. The Arduino also receives and parses data from the Roomba for safety features such as cliff detection.
|
||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<div class="double-screenshot">
|
<div class="screenshot-collection">
|
||||||
|
|
||||||
<div class="project-image">
|
<div class="project-image">
|
||||||
<label for="r" class="thumbnail">
|
<label for="r" class="thumbnail">
|
||||||
@ -289,7 +289,7 @@
|
|||||||
<label for="r" class="close"></label>
|
<label for="r" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/roomba.jpg');"></span>
|
<span class="lazy-image" id="r-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -303,7 +303,7 @@
|
|||||||
<label for="rc" class="close"></label>
|
<label for="rc" class="close"></label>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox">
|
<input type="checkbox">
|
||||||
<span class="lazy-image" style="background-image: url('/img/roomba-control.jpg');"></span>
|
<span class="lazy-image" id="rc-fr"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -180,14 +180,18 @@ h3 {
|
|||||||
min-height: 90vh;
|
min-height: 90vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.double-screenshot {
|
.screenshot-collection {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.double-screenshot .thumbnail {
|
.screenshot-collection input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-image .thumbnail {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -199,11 +203,10 @@ h3 {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.double-screenshot .thumbnail img {
|
.screenshot-collection .thumbnail img {
|
||||||
min-width: calc(min(450px,calc(100vw - 100px)));
|
min-width: calc(min(450px,calc(100vw - 100px)));
|
||||||
min-height: calc(min(450px,calc(100vw - 100px)) * 0.5625);
|
|
||||||
}
|
}
|
||||||
.double-screenshot .no-crop img {
|
.screenshot-collection .no-crop img {
|
||||||
min-width: auto;
|
min-width: auto;
|
||||||
max-width: calc(min(450px,calc(100vw - 100px)));
|
max-width: calc(min(450px,calc(100vw - 100px)));
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
@ -238,8 +241,10 @@ input:checked + .modal {
|
|||||||
|
|
||||||
.lazy-image {
|
.lazy-image {
|
||||||
display: block;
|
display: block;
|
||||||
min-width: 90vw;
|
--ratioH: calc(var(--height) / var(--width));
|
||||||
min-height: 90vh;
|
--ratioW: calc(var(--width) / var(--height));
|
||||||
|
width: calc(min(90vw, 90vh * var(--ratioW)));
|
||||||
|
height: calc(min(90vh, 90vw * var(--ratioH)));
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
@ -248,8 +253,10 @@ input:checked + .modal {
|
|||||||
|
|
||||||
input:checked + .lazy-image {
|
input:checked + .lazy-image {
|
||||||
cursor: zoom-out;
|
cursor: zoom-out;
|
||||||
min-width: 200vw;
|
--zwidth: calc(min(200vw, 200vh * var(--ratioW))*2);
|
||||||
min-height: 200vh;
|
--zheight: calc(min(200vh, 200vw * var(--ratioH))*2);
|
||||||
|
width: var(--zwidth);
|
||||||
|
height: var(--zheight);
|
||||||
scroll-snap-align: center;
|
scroll-snap-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,3 +406,76 @@ body:has(.project-image > input:checked) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* full-res images */
|
||||||
|
#lpcl-fr {
|
||||||
|
background-image: url(/img/peercord-login.png);
|
||||||
|
--width: 2004;
|
||||||
|
--height: 1262;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lpcc-fr {
|
||||||
|
background-image: url(/img/peercord-chat.png);
|
||||||
|
--width: 2004;
|
||||||
|
--height: 1262;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lio-fr {
|
||||||
|
background-image: url(/img/ilo-overview.jpg);
|
||||||
|
--width: 1913;
|
||||||
|
--height: 921;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lit-fr {
|
||||||
|
background-image: url(/img/ilo-temperatures.jpg);
|
||||||
|
--width: 1907;
|
||||||
|
--height: 923;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lid-fr {
|
||||||
|
background-image: url(/img/ilo-drives.jpg);
|
||||||
|
--width: 1916;
|
||||||
|
--height: 917;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lifci-fr {
|
||||||
|
background-image: url(/img/ilo-fan-and-cpu-info.jpg);
|
||||||
|
--width: 1188;
|
||||||
|
--height: 823;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sma-fr {
|
||||||
|
background-image: url(/img/smbus-mitm-arduino.jpg);
|
||||||
|
--width: 1920;
|
||||||
|
--height: 1440;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smw-fr {
|
||||||
|
background-image: url(/img/smbus-mitm-wiring.jpg);
|
||||||
|
--width: 1920;
|
||||||
|
--height: 1440;
|
||||||
|
}
|
||||||
|
|
||||||
|
#scst-fr {
|
||||||
|
background-image: url(/img/security-camera-stream.jpg);
|
||||||
|
--width: 1764;
|
||||||
|
--height: 1004;
|
||||||
|
}
|
||||||
|
|
||||||
|
#scsc-fr {
|
||||||
|
background-image: url(/img/security-camera-screenshot.png);
|
||||||
|
--width: 1440;
|
||||||
|
--height: 3120;
|
||||||
|
}
|
||||||
|
|
||||||
|
#r-fr {
|
||||||
|
background-image: url(/img/roomba.jpg);
|
||||||
|
--width: 1233;
|
||||||
|
--height: 925;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rc-fr {
|
||||||
|
background-image: url(/img/roomba-control.jpg);
|
||||||
|
--width: 1185;
|
||||||
|
--height: 655;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user