[javascript] 세로로 스크롤 할 때 가로 스크롤을 허용하지 마십시오 (또는 그 반대)
overflow-x
및로 overflow-y
설정된 목록 이 auto
있습니다. 또한 운동량 스크롤을 설정 했으므로 터치 스크롤이 모바일에서 잘 작동합니다 webkit-overflow-scrolling: true
.
그러나 문제는 세로 스크롤 할 때 가로 스크롤을 비활성화하는 방법을 알 수 없다는 것입니다. 왼쪽 상단 또는 오른쪽 상단으로 스 와이프하면 테이블이 대각선으로 스크롤되므로 사용자 환경이 실제로 좋지 않습니다. 사용자가 세로 스크롤 할 때 사용자가 세로 스크롤을 중지 할 때까지 가로 스크롤을 원하지 않습니다.
나는 다음을 시도했다.
JS :
offsetX: number;
offsetY: number;
isScrollingHorizontally = false;
isScrollingVertically = false;
//Detect the scrolling events
ngOnInit() {
this.scrollListener = this.renderer.listen(
this.taskRows.nativeElement,
'scroll',
evt => {
this.didScroll();
}
);
fromEvent(this.taskRows.nativeElement, 'scroll')
.pipe(
debounceTime(100),
takeUntil(this.destroy$)
)
.subscribe(() => {
this.endScroll();
});
}
didScroll() {
if ((this.taskRows.nativeElement.scrollLeft != this.offsetX) && (!this.isScrollingHorizontally)){
console.log("Scrolling horizontally")
this.isScrollingHorizontally = true;
this.isScrollingVertically = false;
this.changeDetectorRef.markForCheck();
}else if ((this.taskRows.nativeElement.scrollTop != this.offsetY) && (!this.isScrollingVertically)) {
console.log("Scrolling Vertically")
this.isScrollingHorizontally = false;
this.isScrollingVertically = true;
this.changeDetectorRef.markForCheck();
}
}
endScroll() {
console.log("Ended scroll")
this.isScrollingVertically = false;
this.isScrollingHorizontally = false;
this.changeDetectorRef.markForCheck();
}
HTML :
<div
class="cu-dashboard-table__scroll"
[class.cu-dashboard-table__scroll_disable-x]="isScrollingVertically"
[class.cu-dashboard-table__scroll_disable-y]="isScrollingHorizontally"
>
CSS :
&__scroll {
display: flex;
width: 100%;
height: 100%;
overflow-y: auto;
overflow-x: auto;
will-change: transform;
-webkit-overflow-scrolling: touch;
&_disable-x {
overflow-x: hidden;
}
&_disable-y {
overflow-y: hidden;
}
}
그러나 매번 I 세트 overflow-x
나 overflow-y
에 hidden
의 스크롤 된 경우 글리치 상단으로 다시 이동합니다 스크롤. 또한 webkit-overflow-scrolling: true
이것이 발생하는 이유입니다.이를 제거하면 동작이 중지되는 것처럼 보이지만 모바일 장치에서 운동량 스크롤을 위해서는 이것이 필요합니다.
세로로 스크롤 할 때 가로 스크롤을 비활성화하려면 어떻게합니까?
답변
이 시도
HTML
<div
class="cu-dashboard-table__scroll-vertical"
>
<div
class="cu-dashboard-table__scroll-horizontal"
>
<!-- Scroll content here -->
</div>
</div>
CSS
&__scroll {
&-horizontal {
overflow-x: auto;
width: 100%;
-webkit-overflow-scrolling: touch;
}
&-vertical {
overflow-y: auto;
height: 100%;
-webkit-overflow-scrolling: touch;
}
}
스크롤에 하나의 div를 사용하는 대신 왜 두 개의 div를 사용하지 않습니까? X와 Y에 각각 하나씩
답변
큰 데이터 테이블을 표시하지 않는 한 모바일에서 다축 스크롤이 필요한 디자인은 일반적으로 좋지 않습니다. 그것은 왜 당신이 그것을 방지하고 싶습니까? 사용자가 대각선으로 스크롤하기를 원한다면 그것은 세상의 종말처럼 보이지 않습니다. OSX의 Chrome과 같은 일부 브라우저는 이미 기본적으로 설명하고 있습니다.
단일 축 스크롤이 필요한 경우 가능한 해결 방법은 스크롤 위치 touchstart
와 touchmove
이벤트를 직접 추적하는 것입니다 . 드래그 임계 값을 브라우저보다 낮게 설정하면 스크롤을 시작하기 전에 CSS 작업을 수행하여 감지 된 글리치를 피할 수 있습니다. 또한 여전히 고장이 나더라도 터치 시작 및 터치의 현재 위치가 있습니다. 여기에서 div의 시작 스크롤 위치를 기록하면 div를 올바른 위치로 수동으로 스크롤하여 필요한 경우 상단으로 점프하는 것을 막을 수 있습니다. 가능한 알고리즘은 다음과 같습니다.
// Touchstart handler
if (scrollState === ScrollState.Default) {
// Record position and id of touch
touchStart = touch.location
touchStartId = touch.id.
scrollState = ScrollState.Touching
// If you have to manually scroll the div, first store its starting scroll position:
containerTop = $('.myContainer').scrollTop();
containerLeft = $('.myContainer').scrollLeft();
}
// Touchmove handler - If the user has dragged beyond a distance threshold,
// do the css classes swap.
if (touch.id === touchStartId && distance(touchStart, touch.location > threshold) {
scrollState = ScrollState.Scrolling;
swapCssClasses();
// If you have to manually scroll the div to prevent jump:
$('.myContainer').scrollTop(containerTop + (touch.location.y - touchStart.y));
// Do the same for horizontal scroll.
}
// Then, listen for debounced scroll events, like you're already doing,
// to reset your state back to default.
두 번째 아이디어 : 스크롤 핸들러에서 CSS 클래스를 변경하는 대신 잠 그려는 축에 대해 div의 스크롤 위치를 직접 설정하십시오. IE, 가로로 스크롤하는 경우 항상 scrollTop을 시작 값으로 설정하십시오. 스크롤을 취소해도 확실하지 않을 수 있습니다. 작동하는지 확인해야합니다.
답변
이 문제를 해결하는 방법에는 여러 가지가 있습니다. 몇 가지 좋은 아이디어가 여기에 제공됩니다.
그러나 다른 사람들이 언급했듯이 다차원 스크롤에 의존하거나 피하려고 시도하는 것은 UX의 나쁜 냄새입니다. UX가 문제임을 나타냅니다. 나는 이것이 합법적 인 개발 문제라고 생각하지 않습니다. 한 걸음 물러서서 달성하려는 것을 재평가하는 것이 좋습니다. 문제 중 하나는 UI를보다 유용하게 사용하기 위해 사용자를 혼란스럽게 할 수 있다는 것입니다. 여기에 설명 된 유용성은 혼동을 일으킬 수 있습니다.
가로로 스크롤 할 수없는 이유는 무엇입니까?
세로 스크롤을 중지하면 가로 스크롤 만 가능한 이유는 무엇입니까?
다음은 질문이있을 수 있습니다 (들리지 않음).
사용자가 행을 선택한 경우에만 세로 데이터 목록의 추가 정보를 찾아 볼 수있게하려면 기본적으로 세로로만 스크롤 가능하고 세로로만 전환하는 단순 목록을 갖는 것이 훨씬 좋습니다. “행”이 선택 / 활성화되었을 때의 정보. 세부 사항을 축소하면 평평한 수직 목록으로 돌아갑니다.
이러한 기술적 문제를 해결하기 위해 농구대를 뛰어 넘어야하는 경우, 사용자 경험이 처음부터 잘 설계되지 않았 음을 나타내는 것이 좋습니다.
답변
세 개의 용기를 사용해야합니다.
첫 번째 컨테이너에서 세로 스크롤을 사용하고 가로를 허용하지 않습니다.
두 번째, 그 반대로도 가로 스크롤을 사용하고 세로를 허용하지 않습니다. 반드시 사용되어야 overflow-x: hidden;
하고 overflow-y: hidden;
, 그렇지 않으면 하위 컨테이너가 현재 컨테이너 넘어 갈 수 있습니다.
또한 사용해야 min-width: 100%; min-height: 100%;
합니다.
세 번째 컨테이너의 display: inline-block;
경우 내부 컨테이너를 사용 하여 내부 컨테이너를 확장하면 해당 스크롤 막대가 두 개의 상위 블록에 나타납니다.
HTML
<div class="scroll-y">
<div class="scroll-x">
<div class="content-container">
<!-- scrollable content here -->
</div>
</div>
</div>
CSS
.scroll-y {
position: absolute;
overflow-x: hidden;
overflow-y: auto;
width: 100%;
height: 100%;
min-width: 100%;
min-height: 100%;
}
.scroll-x {
overflow-y: hidden;
overflow-x: auto;
width: auto;
min-width: 100%;
min-height: 100%;
}
.content-container {
min-width: 100%;
min-height: 100%;
display: inline-block;
}
iPhone의 Safari에서 여기 에서 테스트 할 수 있습니다 .
행운을 빕니다!! 😉
답변
이 재미처럼 보인다;)
그것이 합리적인지에 대해서는 논쟁하지 않을 것입니다.
RxJS로 시도했습니다.
ngAfterViewInit() {
const table = document.getElementById("table");
const touchstart$ = fromEvent(table, "touchstart");
const touchmove$ = fromEvent(table, "touchmove");
const touchend$ = fromEvent(table, "touchend");
touchstart$
.pipe(
switchMapTo(
touchmove$.pipe(
// tap(console.log),
map((e: TouchEvent) => ({
x: e.touches[0].clientX,
y: e.touches[0].clientY
})),
bufferCount(4),
map(calculateDirection),
tap(direction => this.setScrollingStyles(direction)),
takeUntil(touchend$)
)
)
)
.subscribe();
}
우리는 모든 4 버퍼 touchemove
이벤트를 다음 네 개의 이벤트 (의 좌표 몇 가지 매우 정교한 계산하게 map(calculateDirection)
출력은) RIGHT
, LEFT
, UP
또는 DOWN
내가 비활성화 수직 또는 horicontal 스크롤하려고 것을 기반으로합니다. 크롬에서 내 안드로이드 전화에서 그것은 일종의 작품;)
나는 작은 놀이터를 만들었 습니다.
건배 Chris