Motion blur while scrolling.
This commit is contained in:
@@ -46,6 +46,26 @@ const viewportHeight = ref(600)
|
|||||||
const rowHeight = ref(64)
|
const rowHeight = ref(64)
|
||||||
const rowProbe = ref(null)
|
const rowProbe = ref(null)
|
||||||
let rowProbeObserver = null
|
let rowProbeObserver = null
|
||||||
|
|
||||||
|
// Scrolling blur effect
|
||||||
|
const blurAmount = ref(0) // pixels
|
||||||
|
let _lastBlurPos = 0
|
||||||
|
let _blurFrame = null
|
||||||
|
|
||||||
|
function _updateMotionBlur() {
|
||||||
|
const pos = scrollTop.value || 0
|
||||||
|
if (_lastBlurPos) {
|
||||||
|
blurAmount.value = 0.5 * Math.abs(pos - _lastBlurPos)
|
||||||
|
}
|
||||||
|
_lastBlurPos = pos
|
||||||
|
_blurFrame = requestAnimationFrame(_updateMotionBlur)
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewportBlurStyle = computed(() => {
|
||||||
|
return blurAmount.value > 0
|
||||||
|
? { filter: 'url(#cal-vert-blur)', willChange: 'filter' }
|
||||||
|
: { filter: 'none' }
|
||||||
|
})
|
||||||
const baseDate = computed(() => new Date(1970, 0, 4 + calendarStore.config.first_day))
|
const baseDate = computed(() => new Date(1970, 0, 4 + calendarStore.config.first_day))
|
||||||
const selection = ref({ startDate: null, dayCount: 0 })
|
const selection = ref({ startDate: null, dayCount: 0 })
|
||||||
const isDragging = ref(false)
|
const isDragging = ref(false)
|
||||||
@@ -387,6 +407,10 @@ onMounted(() => {
|
|||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
clearInterval(timer)
|
clearInterval(timer)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Start motion blur loop
|
||||||
|
_lastBlurPos = scrollTop.value || 0
|
||||||
|
_blurFrame = requestAnimationFrame(_updateMotionBlur)
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
@@ -403,6 +427,7 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.removeEventListener('pointerlockchange', handlePointerLockChange)
|
document.removeEventListener('pointerlockchange', handlePointerLockChange)
|
||||||
|
if (_blurFrame) cancelAnimationFrame(_blurFrame)
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleDayMouseDown = (d) => {
|
const handleDayMouseDown = (d) => {
|
||||||
@@ -506,6 +531,15 @@ window.addEventListener('resize', () => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="calendar-view-root" :dir="rtl && 'rtl'">
|
<div class="calendar-view-root" :dir="rtl && 'rtl'">
|
||||||
<div ref="rowProbe" class="row-height-probe" aria-hidden="true"></div>
|
<div ref="rowProbe" class="row-height-probe" aria-hidden="true"></div>
|
||||||
|
<!-- Inline SVG filter for vertical motion blur -->
|
||||||
|
<svg width="0" height="0" aria-hidden="true" focusable="false" class="motion-blur-defs">
|
||||||
|
<defs>
|
||||||
|
<!-- stdDeviation: x y; keep a tiny epsilon on X so some browsers don't drop the filter entirely -->
|
||||||
|
<filter id="cal-vert-blur" color-interpolation-filters="sRGB" x="-10%" width="120%" y="-10%" height="120%">
|
||||||
|
<feGaussianBlur :stdDeviation="`${0.001} ${blurAmount.toFixed(2)}`" edgeMode="duplicate" />
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
<HeaderControls
|
<HeaderControls
|
||||||
:reference-date="centerVisibleDateStr"
|
:reference-date="centerVisibleDateStr"
|
||||||
@@ -520,7 +554,7 @@ window.addEventListener('resize', () => {
|
|||||||
@year-change="handleHeaderYearChange"
|
@year-change="handleHeaderYearChange"
|
||||||
/>
|
/>
|
||||||
<div class="calendar-container">
|
<div class="calendar-container">
|
||||||
<div class="calendar-viewport" ref="viewport">
|
<div class="calendar-viewport" ref="viewport" :style="viewportBlurStyle">
|
||||||
<div class="calendar-content" :style="{ height: contentHeight + 'px' }">
|
<div class="calendar-content" :style="{ height: contentHeight + 'px' }">
|
||||||
<div
|
<div
|
||||||
class="weeks-wrapper"
|
class="weeks-wrapper"
|
||||||
|
|||||||
Reference in New Issue
Block a user