Skip to content

Commit

Permalink
feat:add image zoom
Browse files Browse the repository at this point in the history
  • Loading branch information
bigfa committed Sep 13, 2024
1 parent 6344c43 commit d87ce25
Show file tree
Hide file tree
Showing 8 changed files with 298 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ echo "theme = 'notability'" >> config.toml

## Release Note

### 0.3.9

- add post image zoom

### 0.3.8

- update comment module
Expand Down
4 changes: 4 additions & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ echo "theme = 'notability'" >> hugo.toml

## Release Note

### 0.3.9

- 增加图片灯箱效果

### 0.3.8

- 更新评论系统
Expand Down
1 change: 1 addition & 0 deletions assets/scss/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
@import "modules/article";
@import "modules/item";
@import "modules/comment";
@import "modules/zoom";

@import "template/db";
@import "template/category";
Expand Down
4 changes: 4 additions & 0 deletions assets/scss/modules/_variable.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
--background-white: #fff;
--main-border-color: rgba(0, 0, 0, 0.1);
--main-border-color-light: rgba(0, 0, 0, 0, 0.05);
--background-opacity: 0.9;
--background-white-opacity: rgba(255, 255, 255, var(--background-opacity));
}

@media (prefers-color-scheme: dark) {
Expand All @@ -32,6 +34,7 @@

--main-border-color: rgba(63, 63, 70, 0.6);
--main-border-color-light: rgba(63, 63, 70, 0.4);
--background-white-opacity: rgba(30, 30, 30, var(--background-opacity));
}
}

Expand All @@ -52,6 +55,7 @@

--main-border-color: rgba(63, 63, 70, 0.6);
--main-border-color-light: rgba(63, 63, 70, 0.4);
--background-white-opacity: rgba(30, 30, 30, var(--background-opacity));
}

@font-face {
Expand Down
129 changes: 129 additions & 0 deletions assets/scss/modules/zoom.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
.overlay {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
background-color: var(--background-white-opacity);
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
&-img-wrap {
position: relative;
opacity: 0;
transition: opacity 0.5s;
&.is-finieshed {
opacity: 1;
}
}
}

.zoomImgClose {
background-color: transparent;
border: 0;
color: var(--text-gray-medium);
font-size: 40px;
line-height: 1;
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
svg {
transition: 0.5s transform;
fill: currentColor;
}
&:hover {
svg {
transform: rotate(90deg);
}
}
}

.zoomNav {
display: flex;
justify-content: center;
}

.mfp-arrow-left {
position: absolute;
opacity: 0.65;
left: 0;
margin: 0;
top: 50%;
margin-top: -55px;
padding: 0;
width: 90px;
height: 110px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
border: 0;
background-color: rgba(0, 0, 0, 0);
color: var(--text-gray-medium);
cursor: pointer;
svg {
transform: rotate(180deg);
fill: currentColor;
}
}

.mfp-arrow-right {
border: 0;
background-color: rgba(0, 0, 0, 0);
color: var(--text-gray-medium);
position: absolute;
opacity: 0.65;
right: 0;
margin: 0;
top: 50%;
margin-top: -55px;
padding: 0;
width: 90px;
height: 110px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
cursor: pointer;
svg {
fill: currentColor;
}
}

.image--nav {
width: 120px;
display: flex;
flex-direction: column;
margin-left: 50px;
transform: rotate(90deg) translateX(4%);
text-align: right;
pointer-events: none;
font-size: 100px;
max-height: 80vh;
color: var(--text-gray-medium);
font-style: italic;
white-space: nowrap;
}

@media (max-width: 800px) {
.overlay {
flex-direction: column;
}

.image--nav {
transform: rotate(0deg) translateX(0);
width: 100%;
margin-left: 0;
overflow-x: auto;
flex-wrap: nowrap;
flex-direction: row;
justify-content: center;
font-size: 24px;
margin-top: 30px;
img {
width: 64px;
}
}
}

.grap--figure {
img {
cursor: zoom-in;
}
}
7 changes: 7 additions & 0 deletions assets/ts/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import noteDate from "./date.ts";
import farallonActions from "./action.ts";
import Douban from "./db.ts";
import { farallonComment } from "./comment.ts";
import imgZoom from "./zoom.ts";

declare global {
interface Window {
actionDomain: string;
timeFormat: string;
dbAPIBase: string;
viewText: string;
noComment: string;
zoom: boolean;
}
}

Expand Down Expand Up @@ -162,3 +165,7 @@ new Douban({
new farallonComment({
actionDomain: window.actionDomain,
});

if (window.zoom) {
new imgZoom();
}
148 changes: 148 additions & 0 deletions assets/ts/zoom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
class imgZoom {
selector: string;
selectorAttr: string;
currentIndex: number;
images: string[];
constructor() {
this.selector = ".grap--figure";
this.selectorAttr = "src";
this.currentIndex = 0;
this.images = [];
this.getZoomImages();
window.addEventListener("resize", () => {
if (document.querySelector(".overlay")) {
this.loadImage(this.images[this.currentIndex]);
}
});
}

getZoomImages() {
const images = Array.from(document.querySelectorAll(this.selector));
this.images = [...images]
.map((image) =>
image.querySelector("img")?.getAttribute(this.selectorAttr)
)
.filter((url) => url !== null) as string[];
images.forEach((image) => {
image.addEventListener("click", (e: any) => {
e.preventDefault();
const url = image
.querySelector("img")
?.getAttribute(this.selectorAttr) as string;
this.showOverlay(url);
});
});
}

renderNav() {
const nav = `${this.currentIndex + 1}/${this.images.length}`;
const imageNav = document.querySelector(".image--nav");
if (imageNav) {
imageNav.innerHTML = nav;
}
}

prevImage() {
if (this.currentIndex === 0) {
return;
}
this.currentIndex = this.currentIndex - 1;
this.loadImage(this.images[this.currentIndex]);
this.renderNav();
}

nextImage() {
if (this.currentIndex === this.images.length - 1) {
return;
}
this.currentIndex = this.currentIndex + 1;
this.loadImage(this.images[this.currentIndex]);
this.renderNav();
}

showOverlay(url: string) {
const self = this;
let currentIndex = this.images.indexOf(url);
this.currentIndex = currentIndex;
let nav =
this.images.length > 1
? `<div class="image--nav">${currentIndex + 1}/${
this.images.length
}</div><button title="Prev" type="button" class="mfp-arrow mfp-arrow-left mfp-prevent-close"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
<path d="M14.4998 7.80903C14.4742 7.74825 14.4372 7.69292 14.3908 7.64603L8.68084 1.93803C8.58696 1.84427 8.45967 1.79165 8.32699 1.79175C8.19431 1.79184 8.0671 1.84464 7.97334 1.93853C7.87959 2.03241 7.82697 2.1597 7.82707 2.29238C7.82716 2.42506 7.87996 2.55227 7.97384 2.64603L12.8278 7.50003H1.96484C1.83224 7.50003 1.70506 7.5527 1.61129 7.64647C1.51752 7.74024 1.46484 7.86742 1.46484 8.00003C1.46484 8.13263 1.51752 8.25981 1.61129 8.35358C1.70506 8.44735 1.83224 8.50003 1.96484 8.50003H12.8278L7.97384 13.354C7.87996 13.4478 7.82716 13.575 7.82707 13.7077C7.82697 13.8404 7.87959 13.9676 7.97334 14.0615C8.0671 14.1554 8.19431 14.2082 8.32699 14.2083C8.45967 14.2084 8.58696 14.1558 8.68084 14.062L14.3878 8.35403C14.4342 8.30713 14.4712 8.2518 14.4968 8.19103C14.5478 8.069 14.5489 7.93184 14.4998 7.80903Z"></path>
</svg></button><button title="Next (Right arrow key)" type="button" class="mfp-arrow mfp-arrow-right mfp-prevent-close"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
<path d="M14.4998 7.80903C14.4742 7.74825 14.4372 7.69292 14.3908 7.64603L8.68084 1.93803C8.58696 1.84427 8.45967 1.79165 8.32699 1.79175C8.19431 1.79184 8.0671 1.84464 7.97334 1.93853C7.87959 2.03241 7.82697 2.1597 7.82707 2.29238C7.82716 2.42506 7.87996 2.55227 7.97384 2.64603L12.8278 7.50003H1.96484C1.83224 7.50003 1.70506 7.5527 1.61129 7.64647C1.51752 7.74024 1.46484 7.86742 1.46484 8.00003C1.46484 8.13263 1.51752 8.25981 1.61129 8.35358C1.70506 8.44735 1.83224 8.50003 1.96484 8.50003H12.8278L7.97384 13.354C7.87996 13.4478 7.82716 13.575 7.82707 13.7077C7.82697 13.8404 7.87959 13.9676 7.97334 14.0615C8.0671 14.1554 8.19431 14.2082 8.32699 14.2083C8.45967 14.2084 8.58696 14.1558 8.68084 14.062L14.3878 8.35403C14.4342 8.30713 14.4712 8.2518 14.4968 8.19103C14.5478 8.069 14.5489 7.93184 14.4998 7.80903Z"></path>
</svg></button>`
: "";
let html = `<div class="overlay"><button class="zoomImgClose"><svg width="25" height="25" viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg" class="q"><path d="M18.13 6.11l-5.61 5.61-5.6-5.61-.81.8 5.61 5.61-5.61 5.61.8.8 5.61-5.6 5.61 5.6.8-.8-5.6-5.6 5.6-5.62"/></svg></button><div class="overlay-img-wrap"><img class="overlay-image"><div class="lds-ripple"></div></div>${nav}</div>`;
const body = document.querySelector("body");
if (body) {
body.insertAdjacentHTML("beforeend", html);
body.classList.add("u-overflowYHidden");
}
this.loadImage(url);
document
.querySelector(".zoomImgClose")
?.addEventListener("click", () => {
self.overlayRemove();
});
document
.querySelector(".mfp-arrow-right")
?.addEventListener("click", () => {
self.nextImage();
});
document
.querySelector(".mfp-arrow-left")
?.addEventListener("click", () => {
self.prevImage();
});
}

loadImage(o: any) {
let s = new Image();
const loading = document.querySelector(".lds-ripple") as HTMLElement;
if (loading) {
loading.style.display = "inline-block";
}
const i = document.querySelector(".overlay-image") as HTMLPreElement;
const nav = document.querySelector(".image--nav");
nav?.classList.add("u-hide");
i.style.display = "none";
s.onload = () => {
var t = s.width,
e = s.height,
n = window.innerHeight - 140,
a = window.innerWidth - 80;
a < t
? ((e *= a / t), (t = a), n < e && ((t *= n / e), (e = n)))
: n < e &&
((t *= n / e), (e = n), a < t && ((e *= a / t), (t = a)));
i.setAttribute("src", o),
(i.style.width = t + "px"),
(i.style.height = e + "px"),
(i.style.display = "block"),
nav?.classList.remove("u-hide");

document
.querySelector(".overlay-img-wrap")
?.classList.add("is-finieshed");
loading.style.display = "none";
};
s.src = o;
}

overlayRemove() {
this._remove(document.querySelector(".overlay"));
const body = document.querySelector("body");
if (body) {
body.classList.remove("u-overflowYHidden");
}
}

_remove(t: any) {
var e: any = t.parentNode;
e && e.removeChild(t);
}
}

export default imgZoom;
1 change: 1 addition & 0 deletions layouts/partials/footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
window.viewText = '{{ i18n "article.views" }}';
window.dbAPIBase = "{{ .Site.Params.dbAPIBase }}";
window.noComment = '{{ i18n "article.nocomment" }}';
window.zoom = "{{ .Site.Params.zoom }}";
</script>
<script type="text/javascript">
window.timeFormat = {
Expand Down

0 comments on commit d87ce25

Please sign in to comment.