Resize Debounce
resizeDebounce와 maxResizeDebounce 옵션으로 리사이즈 호출 빈도를 제어합니다.
컨테이너 오른쪽 하단을 드래그하면서 두 캐러셀의 resize 호출 빈도를 비교해 보세요.
- JavaScript
- React
- Vue@3
import Flicking from "@egjs/flicking"; import "@egjs/flicking/dist/flicking.css"; import "./styles.css"; function formatTime() { return new Date().toLocaleTimeString("ko-KR", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit", fractionalSecondDigits: 3 }); } // debounce: 0 (default) const flickA = new Flicking("#flick-a", { resizeDebounce: 0, maxResizeDebounce: 100 }); // debounce: 300ms / maxDebounce: 800ms const flickB = new Flicking("#flick-b", { resizeDebounce: 300, maxResizeDebounce: 800 }); const logElA = document.getElementById("log-a"); const logElB = document.getElementById("log-b"); const countElA = document.getElementById("count-a"); const countElB = document.getElementById("count-b"); const logsA = []; const logsB = []; function addLog(logs, logEl, countEl) { logs.unshift(`[${formatTime()}] resize()`); if (logs.length > 30) logs.pop(); logEl.innerHTML = logs.map(l => `<div>${l}</div>`).join(""); countEl.textContent = `${logs.length}x`; } flickA.on("afterResize", () => addLog(logsA, logElA, countElA)); flickB.on("afterResize", () => addLog(logsB, logElB, countElB)); // Change container width via slider const slider = document.getElementById("width-slider"); const valueLabel = document.getElementById("width-value"); const wrapA = document.getElementById("wrap-a"); const wrapB = document.getElementById("wrap-b"); slider.addEventListener("input", () => { const w = `${slider.value}%`; wrapA.style.width = w; wrapB.style.width = w; valueLabel.textContent = `${slider.value}%`; });
import Flicking from "@egjs/react-flicking"; import { useCallback, useRef, useState } from "react"; import "@egjs/react-flicking/dist/flicking.css"; import "./styles.css"; function formatTime() { return new Date().toLocaleTimeString("ko-KR", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit", fractionalSecondDigits: 3 }); } function FlickingDemo({ label, config, width }) { const [logs, setLogs] = useState([]); const onAfterResize = useCallback(() => { setLogs(prev => [`[${formatTime()}] resize()`, ...prev].slice(0, 30)); }, []); return ( <div className="demo-section"> <div className="demo-label">{label}</div> <div style={{ width }}> <Flicking resizeDebounce={config.resizeDebounce} maxResizeDebounce={config.maxResizeDebounce} onAfterResize={onAfterResize} > <div className="flicking-panel panel-1">1</div> <div className="flicking-panel panel-2">2</div> <div className="flicking-panel panel-3">3</div> <div className="flicking-panel panel-4">4</div> <div className="flicking-panel panel-5">5</div> </Flicking> </div> <div className="log-header"> <span>Resize log</span> <span className="count-badge">{logs.length}x</span> </div> <div className="log-area"> {logs.length === 0 ? "Move the slider to see resize logs..." : logs.map((log, i) => <div key={i}>{log}</div>)} </div> </div> ); } export default function App() { const [width, setWidth] = useState(100); return ( <div> <div className="demo-hint"> Change the width using the slider and compare the resize call frequency between the two carousels. </div> <div className="slider-row"> <span>Container width</span> <input type="range" min={30} max={100} value={width} onChange={e => setWidth(Number(e.target.value))} /> <span className="value-label">{width}%</span> </div> <FlickingDemo label="resizeDebounce: 0 (default)" config={{ resizeDebounce: 0, maxResizeDebounce: 100 }} width={`${width}%`} /> <FlickingDemo label="resizeDebounce: 300ms / maxResizeDebounce: 800ms" config={{ resizeDebounce: 300, maxResizeDebounce: 800 }} width={`${width}%`} /> </div> ); }
<template> <div> <div class="demo-hint"> Change the width using the slider and compare the resize call frequency between the two carousels. </div> <div class="slider-row"> <span>Container width</span> <input type="range" :min="30" :max="100" v-model.number="width" /> <span class="value-label">{{ width }}%</span> </div> <!-- debounce: 0 --> <div class="demo-section"> <div class="demo-label">resizeDebounce: 0 (default)</div> <div :style="{ width: width + '%' }"> <Flicking :options="{ resizeDebounce: 0, maxResizeDebounce: 100 }" @afterResize="addLogA" > <div class="flicking-panel panel-1">1</div> <div class="flicking-panel panel-2">2</div> <div class="flicking-panel panel-3">3</div> <div class="flicking-panel panel-4">4</div> <div class="flicking-panel panel-5">5</div> </Flicking> </div> <div class="log-header"> <span>Resize log</span> <span class="count-badge">{{ logsA.length }}x</span> </div> <div class="log-area"> <template v-if="logsA.length === 0"> Move the slider to see resize logs... </template> <div v-for="(log, i) in logsA" :key="i">{{ log }}</div> </div> </div> <!-- debounce: 300ms --> <div class="demo-section"> <div class="demo-label">resizeDebounce: 300ms / maxResizeDebounce: 800ms</div> <div :style="{ width: width + '%' }"> <Flicking :options="{ resizeDebounce: 300, maxResizeDebounce: 800 }" @afterResize="addLogB" > <div class="flicking-panel panel-1">1</div> <div class="flicking-panel panel-2">2</div> <div class="flicking-panel panel-3">3</div> <div class="flicking-panel panel-4">4</div> <div class="flicking-panel panel-5">5</div> </Flicking> </div> <div class="log-header"> <span>Resize log</span> <span class="count-badge">{{ logsB.length }}x</span> </div> <div class="log-area"> <template v-if="logsB.length === 0"> Move the slider to see resize logs... </template> <div v-for="(log, i) in logsB" :key="i">{{ log }}</div> </div> </div> </div> </template> <script setup> import Flicking from "@egjs/vue3-flicking"; import { ref } from "vue"; import "@egjs/vue3-flicking/dist/flicking.css"; function formatTime() { return new Date().toLocaleTimeString("ko-KR", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit", fractionalSecondDigits: 3 }); } const width = ref(100); const logsA = ref([]); const logsB = ref([]); const addLogA = () => { logsA.value = [`[${formatTime()}] resize()`, ...logsA.value].slice(0, 30); }; const addLogB = () => { logsB.value = [`[${formatTime()}] resize()`, ...logsB.value].slice(0, 30); }; </script> <style> .flicking-viewport.vertical { display: block; width: 100%; } .flicking-panel { width: 200px; height: 150px; margin-right: 10px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: bold; color: white; } .panel-1 { background: #3e8ed0; } .panel-2 { background: #00d1b2; } .panel-3 { background: #f14668; } .panel-4 { background: #ffe08a; color: #333; } .panel-5 { background: #48c78e; } .demo-container { margin-bottom: 24px; } .demo-label { font-weight: bold; margin-bottom: 8px; color: #666; } .button { padding: 8px 16px; margin: 4px; border: 2px solid #3498db; background: transparent; color: #3498db; border-radius: 4px; cursor: pointer; font-size: 14px; } .button:hover { background: #3498db; color: white; } .controls { display: flex; justify-content: center; margin-top: 16px; gap: 8px; } .slider-row { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; } .slider-row input[type="range"] { flex: 1; } .slider-row .value-label { font-size: 13px; color: #666; min-width: 50px; text-align: right; } .demo-section { margin-bottom: 16px; } .demo-section .demo-label { font-weight: bold; margin-bottom: 6px; font-size: 14px; } .demo-hint { font-size: 13px; color: #888; margin-bottom: 12px; } .log-area { margin-top: 6px; padding: 8px 12px; background: #f5f5f5; border-radius: 4px; font-size: 12px; font-family: monospace; color: #333; max-height: 100px; overflow-y: auto; } .log-header { display: flex; justify-content: space-between; align-items: center; } .log-header span { font-size: 13px; color: #888; } .count-badge { font-size: 13px; font-weight: bold; color: #3498db; } </style>
요약
주요 옵션
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
resizeDebounce | number | 0 | resize 호출 디바운스 지연 (ms) |
maxResizeDebounce | number | 100 | 디바운스 최대 지연 보장 (ms) |
동작 비교
| 설정 | 동작 | 적합한 상황 |
|---|---|---|
resizeDebounce: 0 | 크기 변경 즉시 resize 호출 | 일반적인 사용 (기본값) |
resizeDebounce: 300 | 300ms 동안 변경이 없으면 호출 | 빈번한 크기 변경 시 성능 최적화 |
resizeDebounce: 300 + maxResizeDebounce: 800 | 300ms 디바운스 + 최대 800ms마다 보장 | 연속 변경 중에도 주기적 업데이트 필요 |
상세 설명
resizeDebounce
resizeDebounce는 resize 호출을 지정된 시간만큼 지연시킵니다. 지연 중 크기가 다시 변경되면 타이머가 리셋됩니다.
maxResizeDebounce
maxResizeDebounce는 디바운스 지연의 최대치를 보장합니다. resizeDebounce가 설정되어 있고 연속적인 크기 변경이 일어나더라도, 최소한 maxResizeDebounce 밀리초마다 한 번은 resize가 실행됩니다.
사용 시나리오
언제 사용하나요?
- 채팅/라이브 피드:
resizeDebounce로 빈번한 resize 콜 절감 - 드래그 가능한 레이아웃:
resizeDebounce+maxResizeDebounce로 중간 업데이트 보장 - 일반적인 반응형: 기본값(
resizeDebounce: 0)으로 즉시 반응
주의사항
주의
resizeDebounce값이 너무 크면 사용자가 크기 변경 후 패널이 늦게 재배치되어 보일 수 있습니다maxResizeDebounce는resizeDebounce가 0보다 클 때만 의미가 있습니다
관련 링크
관련 옵션
resizeDebounce: 리사이즈 디바운스maxResizeDebounce: 최대 디바운스
관련 데모
- Auto Resize: 리사이즈 감지 방식 설정
- Optimize Size Update: 불필요한 축 변경 무시