1.17.0 • Published 8 months ago

@mornya/scrolling-anchor-libs v1.17.0

Weekly downloads
91
License
ISC
Repository
github
Last release
8 months ago

Scrolling Anchor Libs

npm node types downloads license

The Scrolling Anchor UI module.

This project has been created by Vessel CLI. For a simple and quick reference about it, click here.

About

스크롤링 앵커로 지정된 각각의 HTML 요소(클라이언트들)을 화면 스크롤 위치에 따라 페이지 상단 및 하단 영역에 attach 혹은 detach 하도록 구현해주는 UI 라이브러리.

Installation

해당 모듈을 사용할 프로젝트에서는 아래와 같이 설치한다.

$ npm install --save @mornya/scrolling-anchor-libs
or
$ yarn add @mornya/scrolling-anchor-libs

Usage

SPA 형태 혹은 SSR 환경의 앱에서 사용이 가능하며, React.js / Vue.js 등의 라이프사이클과는 별개로 동작하므로 컴포넌트 mount 시점에 라이브러리를 초기화 하고 unmount 시점에 라이브러리를 해제 해주면 된다.

Required default style

라이브러리 내 SCSS 파일(@mornya/scrolling-anchor-libs/dist/scrolling-anchor.scss)이 반드시 적용되어야 하므로 해당 SCSS 파일을 import 해주거나, 참고하여 커스터마이징 후 적용해준다. 아래 스타일은 scrolling-anchor.scss 파일에 있는 내용으로, 기본적으로 적용되어야 제대로 동작한다.

$scrolling-anchor-zindex: 99;

.scrolling-anchor {
  & > * {
    display: inherit;
  }
  &[data-direction="top"] > .sa-attached,
  &[data-direction="bottom"] > .sa-attached {
    display: block;
    position: fixed;
    z-index: $scrolling-anchor-zindex;
  }
}

Vue.js example

<template>
  ...
  <div class="scrolling-anchor" data-direction="top"> <!-- "top" is default -->
    <nav>Top Navigation</nav>
  </div>
  ...
  <div
    class="scrolling-anchor"
    data-attach-delay="200"
    data-detach-delay="400"
  >
    <div>
      Top direction bar<br/>
      The styles will be applied after 200ms when attached<br/>
      also detached styles will be applied after 400ms
    </div>
  </div>
  ...
  <div class="scrolling-anchor" data-direction="bottom">
    <nav>Bottom Navigation</nav>
  </div>
  ...
</template>

<script>
import { ScrollingAnchor } from '@mornya/scrolling-anchor-libs';

export default {
  data () {
    return {
      saNav: null,
    };
  },
  updated () {
    if (!this.saNav) {
      this.saNav = new ScrollingAnchor();
    }
  },
  beforeDestroy () {
    this.saNav?.destroy();
  },
};
</script>

<style lang="scss">
  @import "~@mornya/scrolling-anchor-libs/dist/scrolling-anchor.scss";
</style>

React.js example

import React, { useRef, useEffect } from 'react';
import { ScrollingAnchor } from '@mornya/scrolling-anchor-libs';
import '@mornya/scrolling-anchor-libs/dist/scrolling-anchor.scss';

type Props = {};

const Navigation: React.VFC<Props> = (_props) => {
  const saNav = useRef<ScrollingAnchor | null>(null);

  useEffect(() => {
    if (!saNav.current) {
      saNav.current = new ScrollingAnchor('.scrolling-anchor', {
        onAttach (eventTarget) {
          console.log('Navigation attached:', eventTarget.el);
        },
        onDetach (eventTarget) {
          console.log('Navigation detached:', eventTarget.el);
        },
      });
    }
    return () => {
      // unmounted
      saNav.current?.destroy();
    };
  }, []); // mounted

  return (
    <>
      {/* ... */}
      <div className="scrolling-anchor" data-direction="top"> <!-- "top" is default -->
        <nav>Top Navigation</nav>
      </div>

      {/* ... */}
      <div
        className="scrolling-anchor"
        data-attach-delay="200"
        data-detach-delay="400"
      >
        <div>
          Top direction bar<br/>
          The styles will be applied after 200ms when attached<br/>
          also detached styles will be applied after 400ms
        </div>
      </div>

      {/* ... */}
      <div className="scrolling-anchor" data-direction="bottom">
        <nav>Bottom Navigation</nav>
      </div>
    </>
  );
}

Attributes

data-attach-delay

해당 HTML 속성 값(숫자, > 0ms)이 지정된 ScrollingAnchor 영역은 상단 혹은 하단 화면영역에 attach 되려는 순간 .sa-child-will-attach 클래스가 추가되며, 지정한 값 만큼 시간이 지난 후 제거되면서 .sa-child-attached 클래스가 추가 된다. 동시에 실제 attach가 일어나는 .scrolling-anchor 클래스 하위 노드에는 .sa-will-attach 클래스가 추가되고 삭제되면서 .sa-attached 클래스가 추가된다.

트렌지션 등의 효과가 적용되는 시간만큼 해당 HTML 속성 값을 지정해주면 된다.

data-detach-delay

data-attach-delay 와는 반대로 detach 상황에 적용된다. .scrolling-anchor 클래스로 지정된 요소에는 .sa-child-will-detach 클래스가 추가되었다가 지정된 시간이 지난 후 삭제되며, 하위 노드에서는 .sa-will-detach 클래스가 추가되었다가 마찬가지로 삭제된다.

.sa-detached 같은 클래스는 생성되지 않으며, .sa-attached 클래스가 존재하면 attach 된 것이고 없으면 detach 된 것이다.

data-prepared

스크롤링 앵커가 스크롤 시작시 바로 부착될 경우, 화면상으로 튀어 보이는 것을 방지하기 위해 미리 부착된 것 처럼 보이게 처리 한다.

data-waypointed

스크롤링 앵커가 초기화되는 시점에 첫 스크롤링 앵커가 attach 될지 여부를 선언한다. 예를 들어 Y-offset이 0인 앵커의 경우 data-waypoint="true" 설정시 초기화 시점에 attach 되게 된다.

Options

스크롤링 앵커 라이브러리를 일반적으로 사용할 때는 별도의 옵션은 필요하지 않지만 화면이 동적으로 변화되는 경우에는 옵션을 통해 각 앵커 영역의 offset을 조정할 수 있다.

// 각 값들은 디폴트 설정 값임.
import { IScrollingAnchorOption } from './ScrollingAnchor';

const option: IScrollingAnchorOption = {
  isFixedSize: true,
  debouncedResize: 200,
  offsetAttachTop: 0,
  offsetAttachBottom: 0,
  onAttach: (eventTarget: IScrollingAnchorEventTarget) => {},
  onDetach: (eventTarget: IScrollingAnchorEventTarget) => {},
  onScroll: (nextOffset: number, prevOffset: number, maxOffset: number) => {},
};

isFixedSize

상/하단 앵커가 attach될 때, 계산된 width, height 값으로 앵커의 너비/높이를 고정할지의 여부. false로 지정시에는 앵커들에 대해 미리 너비/높이가 지정되어 있어야 자연스럽게 보인다.

debouncedResize

resize 이벤트가 발생할 때 디바운스 시간(milliseconds)을 조정. 0이하의 값은 디바운스 없이 처리 됨.

offsetAttachTop

화면 상단에 앵커가 attach되는 시작 offset을 지정. 예를 들어 offsetAttachTop: 100 으로 지정하게 되면 앵커는 화면 상단 100px 지점부터 attach가 시작된다. 화면이 동적으로 변화되는 경우 컴포넌트 update 라이프사이클에 퍼블릭 메소드인 setPosition을 사용하여 동적으로 해당 값을 조정할 수 있다.

offsetAttachBottom

화면 하단에 앵커가 attach되는 시작 offset을 지정. offsetAttachTop 옵션과 마찬가지로 앵커가 화면 하단에 attach 되는 경우에 사용 가능하다.

onAttach

각 앵커가 상/하단에 attach 되는 시점에 발생하는 이벤트.

function onAttach (eventTarget: IScrollingAnchorEventTarget) {}

eventTarget 객체:

  • el: attach 된 해당 앵커 HTML 요소 객체.
  • height: attach 된 해당 앵커의 높이.
  • offsetTop: 전체 attach 된 앵커 높이의 합.
  • direction: attach 된 앵커의 위치를 의미한다. class="scrolling-anchor"로 지정한 앵커 HTML 엘리먼트의 data-direction 값이다 (top or bottom)
  • lastIndex: data-direction 속성 값이 동일한 앵커 중의 몇 번 째 엘리먼트인지를 의미한다 (0부터 시작). 예를 들어 상단에 attach되는 앵커가 2개 일 경우 HTML 엘리먼트 순서대로 index 번호가 매겨져서 index는 각각 0과 1일 된다. 단 하단의 경우에는 역순으로 index 번호가 매겨진다 (마지막 앵커 index가 0). attach 된 앵커가 없을 경우 -1.

onDetach

각 앵커가 attach 되는 시점을 벗어나 detach되어 원래 자리로 돌아가는 시점에 발생하는 이벤트.

function onDetach (eventTarget: IScrollingAnchorEventTarget) {}

eventTarget 객체:

  • el: detach 된 해당 앵커 HTML 요소 객체.
  • height: detach 된 해당 앵커의 높이.
  • offsetTop: onAttach의 offsetTop과 동일.
  • direction: onAttach의 direction과 동일
  • lastIndex: onAttach의 index와 동일

onScroll

화면이 스크롤링 될 때 이벤트를 발생시키며 아래와 같은 파라미터 값을 제공하므로 사용자 콜백 함수를 만들어 처리 할 내용을 라이브러리에 제공해주면 된다.

function onScroll (nextOffset: number, prevOffset: number, maxOffset: number) {}
  • nextOffset: 화면 스크롤시 이동한 페이지 offset 값
  • prevOffset: 마지막으로 이동했던 페이지 offset 값이며, nextOffset 값과 비교하여 스크롤 하여 이동한 거리 및 방향을 알 수 있다.
  • maxOffset: 화면 상에서 이동 가능한 최대 offset 값을 알 수 있다.

Methods

initialize()

new ScrollingAnchor()로 선언된 객체를 다시 초기화 한다.

destroy 메소드가 실행되어 리스너와 스크롤링 앵커 객체를 모두 해제한 후 재설정 하므로 해당 메소드를 미리 실행할 필요 없다.

function initialize (): void {}

destroy

사용한 자원 및 리스너 등을 모두 해제할 때 사용. 컴포넌트의 unmount 혹은 destroy 라이프사이클이 진행되는 시점에 호출해주면 된다.

function destroy (): void {}

getScrollOffsetX / getScrollOffsetY

현재 화면 스크롤 offset을 리턴해주는 static 메소드.

function getScrollOffsetX (): nubmer {}
function getScrollOffsetY (): nubmer {}

(예시)

console.log(
  ScrollingAnchor.getScrollOffsetX(),
  ', ',
  ScrollingAnchor.getScrollOffsetY(),
);

setPosition

동적으로 상/하단의 attach 시작 offset을 지정할 수 있다.

function setPosition (option: IScrollingAnchorPosition): void {}

option은 초기 ScrollingAnchor 생성시 사용한 옵션과 동일한 내용이지만 offsetAttachTop, offsetAttachBottom 두 값만 사용되어진다. 이 값을 하나 이상 넘겨주면 된다 (넘기지 않아도 무관).

scrollTo

지정한 HTML엘리먼트의 위치가 상단에 오도록 화면을 스크롤 한다.

function scrollTo (scrollOption: IScrollToOption): Promise<IScrollToResult | null> {}

(예시)

scrollTo({
  el: document.querySelector('#target-element'), // null 일 경우 오류 발생
  marginTop: 10, // 해당 값만큼 아래 오프셋 위치로 오도록 지정 (default: 0)
  delay: 0, // 실제 스크롤을 해당 값만큼 지연 (milliseconds)
  isAnimate: true, // Smooth-scroll 여부
  resolveAfter: 250, // 스크롤 후 최종위치 콜백이 리턴되기까지 지연될 시간 (milliseconds)
});

reset

DOM 랜더링 이후에 UI 변경이 있을 경우, 리스너 등 초기화가 불필요한 부분을 제외하고 각 스크롤링 앵커의 상태 등을 모두 초기화 한다. ⚠️ 주의: 실행시 각 스크롤 앵커 영역 위치 재조정으로 스크롤 앵커 영역이 화면에서 깜빡일 수 있다.

function reset (): void {}

Change Log

프로젝트 변경사항은 CHANGELOG.md 파일 참조.

License

프로젝트 라이센스는 LICENSE 파일 참조.

1.15.0

10 months ago

1.17.0

8 months ago

1.16.0

8 months ago

1.14.0

12 months ago

1.13.0

1 year ago

1.11.2

1 year ago

1.12.0

1 year ago

1.11.1

2 years ago

1.11.0

2 years ago

1.10.2

2 years ago

1.10.1

2 years ago

1.10.0

2 years ago

1.9.5

2 years ago

1.9.1

2 years ago

1.9.0

2 years ago

1.8.6

2 years ago

1.9.4

2 years ago

1.9.3

2 years ago

1.9.2

2 years ago

1.8.5

3 years ago

1.8.4

3 years ago

1.8.2

3 years ago

1.8.3

3 years ago

1.8.1

3 years ago

1.8.0

3 years ago

1.7.0

3 years ago

1.6.0

3 years ago

1.5.0

3 years ago

1.4.1

3 years ago

1.4.0

3 years ago

1.3.2

3 years ago

1.3.1

3 years ago

1.3.0

4 years ago

1.2.0

4 years ago

1.1.0

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago