Dikey olarak kaydırırken yatay kaydırmaya izin verme (veya tersi)


17

Birlikte, bir liste var overflow-xve overflow-yset için auto. Buna ek olarak, momentum kaydırma ayarladım, bu yüzden dokunmatik kaydırma mobilde güzel çalışıyor webkit-overflow-scrolling: true.

Ancak sorun, dikey kaydırırken yatay kaydırmanın nasıl devre dışı bırakılacağını anlayamıyorum. Sol üst veya sağ üst tarafa doğru kaydırmak tablonun çapraz olarak kaymasına neden olacağından, gerçekten kötü bir kullanıcı deneyimine yol açar. Kullanıcı dikey olarak kaydırırken, kullanıcı dikey olarak kaydırmayı durdurana kadar yatay olarak herhangi bir kaydırma istemiyorum.

Aşağıdakileri denedim:

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;
  }
}

Ama ne seti overflow-xya overflow-yhiç hiddenonun kaydırıldığını zaman, aksaklık ve üstüne geri atlar kaydırma. Ayrıca webkit-overflow-scrolling: true, bunun neden olduğunu fark ettim, kaldırdığımda, davranış duruyor gibi görünüyor, ama kesinlikle mobil cihazlarda momentum kaydırma için buna ihtiyacım var.

Dikey kaydırırken yatay kaydırmayı nasıl devre dışı bırakabilirim?


Kaydırma sorununu nasıl çözeceğimizi bilmiyorum. Belki bir adım geri gidip iki eksenden birinin kaymasını engellemeye çalışın? Konu Dışı: Tablolar gerçekten küçük ekranlar için tasarlanmamıştır.
Joep Kockelkorn

Kodunuzda eksik bir kıvrık ayraç var. Parçacık olarak eklerseniz, konsolda bir hata mesajı görürsünüz.
Razvan Zamfir

sadece aptalca bir fikir. neden kaydırmak için iki kaydırıcı veya özel kaydırıcı kullanmıyorsunuz?
Thomas Ludewig

Yanıtlar:


4

Bunu dene

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;
  }
}

Kaydırma için bir div kullanmak yerine neden iki tane kullanmıyorsunuz? Biri X ve diğeri Y için


1
İyi fikir! buna bir şans vereceğim.
Josh O'Connor

1
Lol, bunun dahiyane bir fikir olduğunu söylemeliyim.
frodo2975

15

Büyük veri tabloları göstermediğiniz sürece, tasarımınızın mobil cihazlarda çok eksenli kaydırmaya ihtiyaç duyması genellikle kötü bir uygulamadır. Olduğu söyleniyor, neden önlemek istiyorsun? Bir kullanıcı çapraz olarak kaydırmak isterse, bu bana dünyanın sonu gibi görünmüyor. OSX'teki Chrome gibi bazı tarayıcılar, varsayılan olarak açıkladığınızı zaten yapar.

Tek eksenli kaydırmaya sahip olmanız gerekiyorsa, kaydırma konumunu touchstartve touchmoveolayları takip etmek için olası bir çözüm olabilir . Sürükleme eşiğinizi tarayıcınınkinden daha düşük bir değere ayarlarsanız, algılanan aksaklıklardan kaçınarak css öğelerinizi kaydırma işlemine başlamadan önce yapabilirsiniz. Ayrıca, hala aksak olsa bile, dokunma başlangıcı ve dokunuşun geçerli konumuna sahip olursunuz. Bunlardan, bölgenizin başlangıç ​​kaydırma konumunu kaydederseniz, bölmeyi elinizle doğru yere kaydırarak gerektiğinde üste atlamayı engelleyebilirsiniz. Olası bir algoritma şöyle görünebilir:

// 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.

İkinci fikir: kaydırma işleyicinizde, css sınıflarını değiştirmek yerine, div'in kaydırma konumunu doğrudan kilitlenmesini istediğiniz eksen için ayarlayın. IE, yatay olarak kaydırıyorsanız, scrollTop öğesini her zaman başlangıç ​​değerine ayarlayın. Bu ayrıca kaydırmayı iptal edebilir, emin değil. Çalışıp çalışmadığını görmek için denemeniz gerekir.


Bunu denedim ama süper gergin ve performans korkunç oldu.
Josh O'Connor

3

Bunu çözmeye çalışmanın birçok yolu vardır. Burada bazı iyi fikirler sunulmaktadır.

Bununla birlikte, diğerlerinin belirttiği gibi, çok boyutlu kaydırmaya güvenmek (veya kaçınmaya çalışmak) kötü bir UX kokusudur - UX'in bir sorun olduğunu gösterir. Bunun meşru bir geliştirme meselesi olduğunu düşünmüyorum. Geri adım atmak ve neyi başarmaya çalıştığınızı yeniden değerlendirmek daha iyi olur. Sorunlardan biri, kullanıcı arayüzünü daha kullanışlı hale getirmek için kullanıcıları kafa karıştırmanız olabilir. Burada açıklanan kullanılabilirlik muhtemelen karışıklığa neden olacaktır.

Neden yatay kaydırma yapamıyorum?

Neden dikey kaydırmayı bıraktığımda, yalnızca yatay kaydırılabilir?

Bunlar sorulabilecek bazı sorulardır (duyulamaz).

Dikey veri listesinin ek bilgilerinin yalnızca kullanıcı satırı seçtiğinde göz atılabilir olmasına izin vermeye çalışıyorsanız, varsayılan olarak yalnızca dikey olarak kaydırılabilir düz bir listeye sahip olmak ve yalnızca dikey olarak geçiş yapmak çok daha iyi olur "satır" seçildiğinde / etkinleştirildiğinde bilgi. Ayrıntıları daraltmak sizi düz dikey listeye geri götürür.

Böyle bir saçak teknik zorluğu çözmek için çemberlerden atlamak zorundaysanız, kullanıcı deneyiminin başlamak için iyi tasarlanmadığının iyi bir göstergesi.


3

Üç kap kullanmanız gerekiyor.
İlk kapta dikey kaydırma ve yatay izin verme işlevlerini etkinleştiriyorum.
İkincisi, tam tersi, yatay kaydırma ve dikey izin verme etkinleştirin. Emin kullanmak olun overflow-x: hidden;ve overflow-y: hidden;aksi çocuk konteynerler mevcut kabın ötesine gidebilir.
Ayrıca kullanmanız gerekir min-width: 100%; min-height: 100%;.
Üçüncü kap için kullanmamız gerekir display: inline-block;ve daha sonra dahili içerik bu kapsayıcıyı esnetir ve karşılık gelen kaydırma çubukları iki ana blokta görünür.

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;
}

Burada iPhone'daki Safari'de test edebilirsiniz .

İyi şanslar!! 😉


: kaldırdı eller:: kaldırdı eller:
cup_of

0

Bu eğlenceli gibi görünüyor;)

Makul olup olmadığını tartışmayacağım.

RxJS ile denedim:

  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();
  }

Her 4 tampon touchemoveetkinliği ve daha sonra dört etkinlik (koordinatları ile yapılan son derece karmaşık hesaplama yapmak map(calculateDirection)çıkışları) RIGHT, LEFT, UPya da DOWNve devre dışı dikey veya horicontal kaydırma deneyin göre. Android telefonumda krom çalışıyor;)

Geliştirilebilecek, yeniden yazılabilecek küçük bir oyun alanı yarattım ...

Şerefe Chris

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.