README
Scrolling Anchor Libs
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.FC<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 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>
</>
);
}
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 된 것이다.
Options
스크롤링 앵커 라이브러리를 일반적으로 사용할 때는 별도의 옵션은 필요하지 않지만 화면이 동적으로 변화되는 경우에는 옵션을 통해 각 앵커 영역의 offset을 조정할 수 있다.
// 각 값들은 디폴트 설정 값임.
import { IScrollingAnchorEventTarget } from './ScrollingAnchor';
const option: IScrollingAnchorOption = {
offsetAttachTop: 0,
offsetAttachBottom: 0,
onScroll: (nextOffset: number, prevOffset: number, maxOffset: number) => {},
onAttach: (eventTarget: IScrollingAnchorEventTarget) => {},
onDetach: (eventTarget: IScrollingAnchorEventTarget) => {},
};
offsetAttachTop
화면 상단에 앵커가 attach되는 시작 offset을 지정. 예를 들어 offsetAttachTop: 100
으로 지정하게 되면 앵커는 화면 상단 100px 지점부터 attach가 시작된다. 화면이 동적으로 변화되는 경우 컴포넌트 update 라이프사이클에 퍼블릭 메소드인 setPosition
을 사용하여 동적으로 해당 값을 조정할 수 있다.
offsetAttachBottom
화면 하단에 앵커가 attach되는 시작 offset을 지정. offsetAttachTop
옵션과 마찬가지로 앵커가 화면 하단에 attach 되는 경우에 사용 가능하다.
onScroll
화면이 스크롤링 될 때 이벤트를 발생시키며 아래와 같은 파라미터 값을 제공하므로 사용자 콜백 함수를 만들어 처리 할 내용을 라이브러리에 제공해주면 된다.
function onScroll (nextOffset: number, prevOffset: number, maxOffset: number) {}
nextOffset
: 화면 스크롤시 이동한 페이지 offset 값prevOffset
: 마지막으로 이동했던 페이지 offset 값이며, nextOffset 값과 비교하여 스크롤 하여 이동한 거리 및 방향을 알 수 있다.maxOffset
: 화면 상에서 이동 가능한 offset 값을 알 수 있다.
onAttach
각 앵커가 상/하단에 attach 되는 시점에 발생하는 이벤트.
function onAttach (eventTarget: IScrollingAnchorEventTarget) {}
eventTarget 객체:
el
: attach 된 앵커 HTML 요소 객체.direction
: attach 된 앵커의 위치를 의미한다. class="scrolling-anchor"로 지정한 앵커 HTML 엘리먼트의data-direction
값이다 (top
orbottom
)lastIndex
: data-direction 속성 값이 동일한 앵커 중의 몇 번 째 엘리먼트인지를 의미한다 (0부터 시작). 예를 들어 상단에 attach되는 앵커가 2개 일 경우 HTML 엘리먼트 순서대로 index 번호가 매겨져서 index는 각각 0과 1일 된다. 단 하단의 경우에는 역순으로 index 번호가 매겨진다 (마지막 앵커 index가 0).
onDetach
각 앵커가 attach 되는 시점을 벗어나 detach되어 원래 자리로 돌아가는 시점에 발생하는 이벤트.
function onDetach (eventTarget: IScrollingAnchorEventTarget) {}
eventTarget 객체:
el
: detach 된 앵커 HTML 요소 객체.direction
: onAttach의 direction과 동일lastIndex
: onAttach의 index와 동일
Methods
getScrollOffsetY
현재 화면 스크롤 offset을 리턴해주는 static 메소드다.
function getScrollOffsetY (): nubmer {}
(예시)
console.log(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'),
marginTop: 10, // 해당 값만큼 아래 오프셋 위치로 오도록 지정 (default: 0)
delay: 0, // 실제 스크롤을 해당 값만큼 지연 (milliseconds)
});
reset
DOM 랜더링 이후에 UI 변경이 있을 경우, 리스너 등 초기화가 불필요한 부분을 제외하고 각 스크롤링 앵커의 상태 등을 모두 초기화 한다.
function reset (): void {}
destroy
스크롤링 앵커 라이브러리에서 사용한 자원 및 리스너 등을 모두 해제할 때 사용. 컴포넌트의 unmount 혹은 destroy 라이프사이클이 진행되는 시점에 호출해주면 된다.
function destroy (): void {}
Change Log
프로젝트 변경사항은 CHANGELOG.md 파일 참조.
License
프로젝트 라이센스는 LICENSE 파일 참조.