fix(photoswipe): keyboard arrow animation via CSS keyframes
Previous approach (CSS transition + reflow trick) is unreliable in Firefox. New approach: PhotoSwipe emits 'change' synchronously before painting; we add a direction-aware CSS keyframe animation to the incoming slide element, with animation-fill-mode:both so there is no flash before the animation starts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
This commit is contained in:
@@ -111,15 +111,31 @@ const lightbox = new PhotoSwipeLightbox({
|
||||
pswpModule: () => import('https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe.esm.min.js')
|
||||
});
|
||||
lightbox.on('afterOpen', function () {
|
||||
var container = lightbox.pswp.element.querySelector('.pswp__container');
|
||||
var pswp = lightbox.pswp;
|
||||
var keyDir = 0;
|
||||
var clearTimer = null;
|
||||
function onKey(e) {
|
||||
if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;
|
||||
container.style.transition = 'transform 0.35s cubic-bezier(0.4, 0, 0.22, 1)';
|
||||
container.getBoundingClientRect();
|
||||
setTimeout(function () { container.style.transition = ''; }, 400);
|
||||
if (e.key === 'ArrowRight') keyDir = 1;
|
||||
else if (e.key === 'ArrowLeft') keyDir = -1;
|
||||
else keyDir = 0;
|
||||
}
|
||||
document.addEventListener('keydown', onKey, true);
|
||||
lightbox.pswp.on('close', function () { document.removeEventListener('keydown', onKey, true); });
|
||||
pswp.on('change', function () {
|
||||
if (!keyDir) return;
|
||||
var dir = keyDir;
|
||||
keyDir = 0;
|
||||
var el = pswp.currSlide && pswp.currSlide.el;
|
||||
if (!el) return;
|
||||
el.classList.remove('pswp-key-from-left', 'pswp-key-from-right');
|
||||
el.offsetWidth;
|
||||
el.classList.add(dir > 0 ? 'pswp-key-from-right' : 'pswp-key-from-left');
|
||||
clearTimeout(clearTimer);
|
||||
clearTimer = setTimeout(function () { el.classList.remove('pswp-key-from-left', 'pswp-key-from-right'); }, 400);
|
||||
});
|
||||
pswp.on('close', function () {
|
||||
document.removeEventListener('keydown', onKey, true);
|
||||
clearTimeout(clearTimer);
|
||||
});
|
||||
});
|
||||
lightbox.init();
|
||||
|
||||
|
||||
@@ -146,15 +146,31 @@ const lightbox = new PhotoSwipeLightbox({
|
||||
pswpModule: () => import('https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe.esm.min.js')
|
||||
});
|
||||
lightbox.on('afterOpen', function () {
|
||||
var container = lightbox.pswp.element.querySelector('.pswp__container');
|
||||
var pswp = lightbox.pswp;
|
||||
var keyDir = 0;
|
||||
var clearTimer = null;
|
||||
function onKey(e) {
|
||||
if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;
|
||||
container.style.transition = 'transform 0.35s cubic-bezier(0.4, 0, 0.22, 1)';
|
||||
container.getBoundingClientRect();
|
||||
setTimeout(function () { container.style.transition = ''; }, 400);
|
||||
if (e.key === 'ArrowRight') keyDir = 1;
|
||||
else if (e.key === 'ArrowLeft') keyDir = -1;
|
||||
else keyDir = 0;
|
||||
}
|
||||
document.addEventListener('keydown', onKey, true);
|
||||
lightbox.pswp.on('close', function () { document.removeEventListener('keydown', onKey, true); });
|
||||
pswp.on('change', function () {
|
||||
if (!keyDir) return;
|
||||
var dir = keyDir;
|
||||
keyDir = 0;
|
||||
var el = pswp.currSlide && pswp.currSlide.el;
|
||||
if (!el) return;
|
||||
el.classList.remove('pswp-key-from-left', 'pswp-key-from-right');
|
||||
el.offsetWidth;
|
||||
el.classList.add(dir > 0 ? 'pswp-key-from-right' : 'pswp-key-from-left');
|
||||
clearTimeout(clearTimer);
|
||||
clearTimer = setTimeout(function () { el.classList.remove('pswp-key-from-left', 'pswp-key-from-right'); }, 400);
|
||||
});
|
||||
pswp.on('close', function () {
|
||||
document.removeEventListener('keydown', onKey, true);
|
||||
clearTimeout(clearTimer);
|
||||
});
|
||||
});
|
||||
lightbox.init();
|
||||
|
||||
|
||||
@@ -515,15 +515,31 @@ const lightbox = new PhotoSwipeLightbox({
|
||||
pswpModule: () => import('https://cdn.jsdelivr.net/npm/photoswipe@5/dist/photoswipe.esm.min.js')
|
||||
});
|
||||
lightbox.on('afterOpen', function () {
|
||||
var container = lightbox.pswp.element.querySelector('.pswp__container');
|
||||
var pswp = lightbox.pswp;
|
||||
var keyDir = 0;
|
||||
var clearTimer = null;
|
||||
function onKey(e) {
|
||||
if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;
|
||||
container.style.transition = 'transform 0.35s cubic-bezier(0.4, 0, 0.22, 1)';
|
||||
container.getBoundingClientRect(); // force reflow so browser commits current position as "from"
|
||||
setTimeout(function () { container.style.transition = ''; }, 400);
|
||||
if (e.key === 'ArrowRight') keyDir = 1;
|
||||
else if (e.key === 'ArrowLeft') keyDir = -1;
|
||||
else keyDir = 0;
|
||||
}
|
||||
document.addEventListener('keydown', onKey, true);
|
||||
lightbox.pswp.on('close', function () { document.removeEventListener('keydown', onKey, true); });
|
||||
pswp.on('change', function () {
|
||||
if (!keyDir) return;
|
||||
var dir = keyDir;
|
||||
keyDir = 0;
|
||||
var el = pswp.currSlide && pswp.currSlide.el;
|
||||
if (!el) return;
|
||||
el.classList.remove('pswp-key-from-left', 'pswp-key-from-right');
|
||||
el.offsetWidth; // restart animation if navigating rapidly
|
||||
el.classList.add(dir > 0 ? 'pswp-key-from-right' : 'pswp-key-from-left');
|
||||
clearTimeout(clearTimer);
|
||||
clearTimer = setTimeout(function () { el.classList.remove('pswp-key-from-left', 'pswp-key-from-right'); }, 400);
|
||||
});
|
||||
pswp.on('close', function () {
|
||||
document.removeEventListener('keydown', onKey, true);
|
||||
clearTimeout(clearTimer);
|
||||
});
|
||||
});
|
||||
lightbox.init();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user