Skip to content

Commit e15eb63

Browse files
Horizontal swipe between collection elements
1 parent 23904ba commit e15eb63

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

  • src/player/types/ContentView

src/player/types/ContentView/type.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,108 @@ FrameTrail.defineType(
937937
}
938938
});
939939

940+
// Horizontal swipe to navigate between collection elements.
941+
// Uses touchstart/touchmove because <video controls> swallows
942+
// pointer events at the browser level (even capture phase on
943+
// ancestors never fires). Touch events DO still propagate.
944+
// Vertical scroll is preserved by only acting when the gesture
945+
// is predominantly horizontal.
946+
(function() {
947+
var startX = 0, startY = 0, swiping = false, decided = false;
948+
var THRESHOLD = 40; // min px to trigger a swipe
949+
var ANGLE_LIMIT = 30; // max degrees from horizontal
950+
951+
detailsContainerElement.addEventListener('touchstart', function(e) {
952+
if (e.touches.length !== 1) return;
953+
startX = e.touches[0].clientX;
954+
startY = e.touches[0].clientY;
955+
swiping = true;
956+
decided = false;
957+
}, true);
958+
959+
detailsContainerElement.addEventListener('touchmove', function(e) {
960+
if (!swiping || decided) return;
961+
var touch = e.touches[0];
962+
var dx = touch.clientX - startX;
963+
var dy = touch.clientY - startY;
964+
var dist = Math.sqrt(dx * dx + dy * dy);
965+
if (dist < THRESHOLD) return;
966+
967+
decided = true;
968+
var angle = Math.abs(Math.atan2(dy, dx) * 180 / Math.PI);
969+
if (angle > ANGLE_LIMIT && angle < (180 - ANGLE_LIMIT)) {
970+
swiping = false;
971+
return;
972+
}
973+
974+
swiping = false;
975+
e.preventDefault();
976+
977+
var activeElement = self.contentViewContainer.querySelector('.collectionElement.open');
978+
if (!activeElement) return;
979+
980+
if (dx < 0) {
981+
var next = activeElement.nextElementSibling;
982+
while (next && !next.classList.contains('collectionElement')) { next = next.nextElementSibling; }
983+
if (next) next.click();
984+
} else {
985+
var prev = activeElement.previousElementSibling;
986+
while (prev && !prev.classList.contains('collectionElement')) { prev = prev.previousElementSibling; }
987+
if (prev) prev.click();
988+
}
989+
}, true);
990+
991+
detailsContainerElement.addEventListener('touchend', function() { swiping = false; decided = false; }, true);
992+
detailsContainerElement.addEventListener('touchcancel', function() { swiping = false; decided = false; }, true);
993+
994+
// Also support mouse-based swipe (desktop, non-touch)
995+
detailsContainerElement.addEventListener('pointerdown', function(e) {
996+
if (e.pointerType === 'touch') return; // handled by touch events above
997+
if (e.button !== 0) return;
998+
startX = e.clientX;
999+
startY = e.clientY;
1000+
swiping = true;
1001+
decided = false;
1002+
}, true);
1003+
1004+
detailsContainerElement.addEventListener('pointermove', function(e) {
1005+
if (e.pointerType === 'touch') return;
1006+
if (!swiping || decided) return;
1007+
var dx = e.clientX - startX;
1008+
var dy = e.clientY - startY;
1009+
var dist = Math.sqrt(dx * dx + dy * dy);
1010+
if (dist < THRESHOLD) return;
1011+
1012+
decided = true;
1013+
var angle = Math.abs(Math.atan2(dy, dx) * 180 / Math.PI);
1014+
if (angle > ANGLE_LIMIT && angle < (180 - ANGLE_LIMIT)) {
1015+
swiping = false;
1016+
return;
1017+
}
1018+
1019+
swiping = false;
1020+
var activeElement = self.contentViewContainer.querySelector('.collectionElement.open');
1021+
if (!activeElement) return;
1022+
1023+
if (dx < 0) {
1024+
var next = activeElement.nextElementSibling;
1025+
while (next && !next.classList.contains('collectionElement')) { next = next.nextElementSibling; }
1026+
if (next) next.click();
1027+
} else {
1028+
var prev = activeElement.previousElementSibling;
1029+
while (prev && !prev.classList.contains('collectionElement')) { prev = prev.previousElementSibling; }
1030+
if (prev) prev.click();
1031+
}
1032+
}, true);
1033+
1034+
detailsContainerElement.addEventListener('pointerup', function(e) {
1035+
if (e.pointerType !== 'touch') { swiping = false; decided = false; }
1036+
}, true);
1037+
detailsContainerElement.addEventListener('pointercancel', function(e) {
1038+
if (e.pointerType !== 'touch') { swiping = false; decided = false; }
1039+
}, true);
1040+
})();
1041+
9401042
return detailsContainerElement;
9411043

9421044
},

0 commit comments

Comments
 (0)