Gallery와 이미지 Swipe기능

이미지를 클릭하면 확대되면서 swipe가 되는 viewer를 사용하고 싶은데 만들기 전에 이미 있는지 한번 검색을 해봤고 나름 괜찮은 라이브러리가 있어 소개하려고 합니다.

라이브러리 github repo에 잘 설명되어있지만 적용한 방법과 조금 custom한 부분이 있기 때문에 추가 설명하도록 하겠습니다.


Gallery기능

{{- $.Page.Scratch.Add "figurecount" 1 }}
<div class="gallery caption-position-{{ with .Get "caption-position" | default "center" }}{{.}}{{end}} caption-effect-{{ with .Get "caption-effect" | default "fade" }}{{.}}{{end}} hover-effect-{{ with .Get "hover-effect" | default "zoom" }}{{.}}{{end}} {{ if ne (.Get "hover-transition") "none" }}hover-transition{{end}}" itemscope itemtype="http://schema.org/ImageGallery">
	  {{ .Inner }}
</div>

shotcodes에 gallery.html을 추가해주고 위와 같이 코드를 작성해주었습니다. 라이브러리에는 dir옵션으로 특정 경로밑에있는 파일모두 자동으로 삽입하게끔 되어있었는데 나는 이미지를 지정해주는 게 더 나을것같아 코드를 삭제하고 위와같이만 남겨주었고 caption과 effect의 default값을 변경해주었습니다.

caption과 effect의 종류도 설명 홈페이지에 나와있습니다.


figure

{{- $src := .Get "src" }}
<div class="box{{ with .Get "caption-position" }} fancy-figure caption-position-{{.}}{{end}}{{ with .Get "caption-effect" }} caption-effect-{{.}}{{end}}" {{ with .Get "width" }}style="max-width:{{.}}"{{end}}>
  <figure {{ with .Get "class" }}class="{{.}}"{{ end }} itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img">
      <img itemprop="thumbnail" src="{{ $src }}" {{ with .Get "alt" | default (.Get "caption") }}alt="{{.}}"{{ end }}/><!-- <img> hidden if in .gallery -->
    </div>
    {{ with .Get "link" | default (.Get "src") }}<a href="{{.}}" itemprop="contentUrl"></a>{{ end }}
    {{- if or (or (.Get "title") (.Get "caption")) (.Get "attr")}}
      <figcaption>
        {{- with .Get "title" }}<h4>{{.}}</h4>{{ end }}
        {{- if or (.Get "caption") (.Get "attr")}}
          <p>
            {{- .Get "caption" -}}
            {{- with .Get "attrlink"}}<a href="{{.}}">{{ .Get "attr" }}</a>{{ else }}{{ .Get "attr"}}{{ end -}}
          </p>
        {{- end }}
      </figcaption>
    {{- end }}
  </figure>
</div>

갤러리 내부에 들어가는 figure로 이를 이용해 gallery 내부에 img를 넣어줄 수 있습니다.


헤더에 css추가해주기

css코드
/*
Grid Layout Styles
*/
.gallery {
  overflow: hidden;
  margin: 10px;
  max-width: 768px;
}
.gallery .box {
  float: left;
  position: relative;
  /* Default: 1 tile wide */
  width: 100%;
  padding-bottom: 100%;
}
@media only screen and (min-width: 365px) {
  /* Tablet view: 2 tiles */
  .gallery .box {
    width: 50%;
    padding-bottom: 50%;
  }
}
@media only screen and (min-width: 480px) {
  /* Small desktop / ipad view: 3 tiles */
  .gallery .box {
    width: 33.3%;
    padding-bottom: 33.3%; /*  */
  }
}
@media only screen and (min-width: 9999px) {
  /* Medium desktop: 4 tiles */
  .box {
    width: 25%;
    padding-bottom: 25%;
  }
}

/*
Transition styles
*/
.gallery.hover-transition figure,
.gallery.hover-effect-zoom .img,
.gallery:not(.caption-effect-appear) figcaption,
.fancy-figure:not(.caption-effect-appear) figcaption {
  -webkit-transition: all 0.3s ease-in-out;
  -moz-transition: all 0.3s ease-in-out;
  -o-transition: all 0.3s ease-in-out;
  transition: all 0.3s ease-in-out;
}
/*
figure styles
*/
figure {
  position: relative; /* purely to allow absolution positioning of figcaption */
  overflow: hidden;
}
.gallery figure {
  margin: 0px;
  position: absolute;
  left: 5px;
  right: 5px;
  top: 5px;
  bottom: 5px;
}
.gallery.hover-effect-grow figure:hover {
  transform: scale(1.05);
}
.gallery.hover-effect-shrink figure:hover {
  transform: scale(0.95);
}
.gallery.hover-effect-slidedown figure:hover {
  transform: translateY(5px);
}
.gallery.hover-effect-slideup figure:hover {
  transform: translateY(-5px);
}

/*
img / a styles
*/
.box {
  margin: 0 auto;
}
.box img {
  box-shadow: 0 10px 30px rgb(0 0 0 / 10%);
  border: 2px solid #e6e6e6 !important;
}

.gallery .img {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}
.gallery.hover-effect-zoom figure:hover .img {
  transform: scale(1.05);
}
.gallery img {
  display: none; /* only show the img if not inside a gallery */
  width: 100%;
  height: 100%;
  object-fit: cover;
}
figure a {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}

/*
figcaption styles
*/
.gallery figcaption,
.fancy-figure figcaption {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: #000;
  color: #fff;
  text-align: center;
  font-size: 75%; /* change this if you want bigger text */
  background: rgba(0, 0, 0, 0.5);
  opacity: 1;
  cursor: pointer;
}
.gallery.caption-position-none figcaption,
.fancy-figure.caption-position-none figcaption {
  display: none;
}
.gallery.caption-position-center figcaption,
.fancy-figure.caption-position-center figcaption {
  top: 0;
  padding: 40% 5px;
}
.gallery.caption-position-bottom figcaption,
.fancy-figure.caption-position-bottom figcaption {
  padding: 5px;
}
.gallery.caption-effect-fade figure:not(:hover) figcaption,
.gallery.caption-effect-appear figure:not(:hover) figcaption,
.fancy-figure.caption-effect-fade figure:not(:hover) figcaption,
.fancy-figure.caption-effect-appear figure:not(:hover) figcaption {
  background: rgba(0, 0, 0, 0);
  opacity: 0;
}
.gallery.caption-effect-slide.caption-position-bottom figure:not(:hover) figcaption,
.fancy-figure.caption-effect-slide.caption-position-bottom figure:not(:hover) figcaption {
  margin-bottom: -100%;
}
.gallery.caption-effect-slide.caption-position-center figure:not(:hover) figcaption,
.fancy-figure.caption-effect-slide.caption-position-center figure:not(:hover) figcaption {
  top: 100%;
}
figcaption p {
  margin: auto; /* override style in theme */
}

위의 css는 기존의 css파일에서 조금 내입맛에 바꾼상태입니다. (border와 shadow를 좀 주고 background-img를 없애고 object-fit을 cover로 바꾸는 등 조금 손을 봤습니다.)

<link rel="stylesheet" href="/css/hugo-easy-gallery.css" />

/layouts/partials/html-header.html에 위의 코드를 추가해주면 됩니다.


사용방법

example

일반 shortcode사용하듯이 gallery를 사용하고 내부에 figure를 선언하고 srccaption으로 옵션을 줄 수 있습니다.

이렇게만 수행해도 이미지를 클릭시 확대가 되고 gallery도 정상적으로 수행되는 것을 볼 수 있는데 확대만 되지 닫기버튼도 존재하지않고 우리가 하려고하는 swipe도 안되기 때문에 swipe도 추가해주어야 합니다.



Swipe추가

라이브러리는 shortcode형태로 제공을 하는데 swipe는 페이지내에서 한번만 선언해주면되고 shortcode보다 더 간편하게 사용하기 위해서 페이지 상단에서 옵션으로 설정할 수 있게 했습니다.

<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
  <!-- Background of PhotoSwipe.
     It's a separate element, as animating opacity is faster than rgba(). -->
  <div class="pswp__bg"></div>
  <!-- Slides wrapper with overflow:hidden. -->
  <div class="pswp__scroll-wrap">
    <!-- Container that holds slides.
      PhotoSwipe keeps only 3 of them in DOM to save memory.
      Don't modify these 3 pswp__item elements, data is added later on. -->
    <div class="pswp__container">
      <div class="pswp__item"></div>
      <div class="pswp__item"></div>
      <div class="pswp__item"></div>
    </div>
    <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
    <div class="pswp__ui pswp__ui--hidden">
      <div class="pswp__top-bar">
        <!--  Controls are self-explanatory. Order can be changed. -->
        <div class="pswp__counter"></div>
        <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
        <button class="pswp__button pswp__button--share" title="Share"></button>
        <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
        <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
        <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
        <!-- element will get class pswp__preloader--active when preloader is running -->
        <div class="pswp__preloader">
          <div class="pswp__preloader__icn">
            <div class="pswp__preloader__cut">
              <div class="pswp__preloader__donut"></div>
            </div>
          </div>
        </div>
      </div>
      <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
        <div class="pswp__share-tooltip"></div>
      </div>
      <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button>
      <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button>
      <div class="pswp__caption">
        <div class="pswp__caption__center"></div>
      </div>
    </div>
  </div>
</div>

/layouts/partials/swipe.html을 생성해서 위와같이 작성해주고 아까 css추가해준 haader.html에 아래와같이 js도 추가해주면됩니다.

{{ if (in .Params.active "swipe")}}
    <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
    <script src="/js/load-photoswipe.js"></script>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/photoswipe.min.css" integrity="sha256-sCl5PUOGMLfFYctzDW3MtRib0ctyUvI9Qsmq2wXOeBY=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/default-skin/default-skin.min.css" integrity="sha256-BFeI1V+Vh1Rk37wswuOYn5lsTcaU96hGaI7OUVCLjPc=" crossorigin="anonymous" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/photoswipe.min.js" integrity="sha256-UplRCs9v4KXVJvVY+p+RSo5Q4ilAUXh7kpjyIP5odyc=" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/photoswipe-ui-default.min.js" integrity="sha256-PWHOlUzc96pMc8ThwRIXPn8yH4NOLu42RQ0b9SpnpFk=" crossorigin="anonymous"></script>
{{ end }}


---
title: 'Gallery와 이미지 Swipe기능'
date: 2021-04-15T20:31:12+09:00
Description: 'Hugo에 Gallery와 이미지 Swipe기능 추가해보기'
weight:
active:
  - swipe
---

최종적으로 swipe를 사용할 page에 옵션으로 action: swipe를 주면 해당 페이지는 figure에 대해 swipe가 설정이 됩니다.



번외) gallery를 사용안하고 그냥 img에 swipe기능 추가하기

img를 태그를 생성할때 위에서 설정한 className을 갖고있어야 swipe기능이 활성화 되기 때문에 figure shortcodes르 그대로 이용하려고 했으나 figure에는 caption에 해당하는 <a>태그가 존재했고 gallery내부에 선언이 안되어있다면 별도의 공간을 차지하는 문제가 발생해서 swipe-image라는 별도의 shortcode를 만들어서 사용할 수 있도록 했습니다.

{{- $src := .Get "src" }}
<div class="box{{ with .Get "caption-position" }} fancy-figure caption-position-{{.}}{{end}}{{ with .Get "caption-effect" }} caption-effect-{{.}}{{end}}" {{ with .Get "width" }}style="max-width:{{.}}"{{end}}>
  <figure {{ with .Get "class" }}class="{{.}}"{{ end }} itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img">
      <img itemprop="thumbnail" src="{{ $src }}" {{ with .Get "alt" | default (.Get "caption") }}alt="{{.}}"{{ end }}/><!-- <img> hidden if in .gallery -->
    </div>
    {{ with .Get "link" | default (.Get "src") }}<a href="{{.}}" itemprop="contentUrl"></a>{{ end }}

  </figure>
</div>

기존의 figure에서 <a>태그를 만드는 코드만 뺀것이기 때문에 사용법은 figure와 동일하고 figure대신 swipe-image로 사용을 하면 됩니다.

그러면 잘 gallery내부에 있지 않아도 swipe가 적용된 것을 볼 수 있습니다.


이번에는 직접 만든 것이 아니라 외부 라이브러리를 소개했는데 도움이 되었기를 바라고 이를 이용해서 저처럼 입맛에 맞게 커스텀해서 사용하면 될 것 같습니다.





Reference

https://github.com/liwenyip/hugo-easy-gallery