Как сделать количество видимых слайдов отзывчивым в CSS в чистой реагирующей карусели - PullRequest
0 голосов
/ 06 марта 2020

Как / как мы можем сделать количество видимых слайдов отзывчивыми в CSS? / Не нужно использовать JS для изменения visibleSlides на основе точек останова.

Например; Каждый слайд имеет min-width: 100px; min-height: 100px; ie. изображение, которое мы хотим видеть в деталях, поэтому оно не должно быть меньше 100 пикселей.

Мы установили visibleSlides на 8 (для настольных компьютеров). На мобильном мы хотим показать только 2 слайда. Поскольку мы не хотим, чтобы отдельные слайды имели высоту и ширину менее 100 пикселей, а также не перекрывали слайды.

Я знаю, что мы могли бы использовать реакцию, чтобы проверить ширину экрана и установить visibleSlides, однако это нелегко чтобы все приложения имели к нему доступ, особенно на стороне сервера, как показано ниже. js.

См. эту песочницу https://codesandbox.io/s/pure-react-carousel-responsive-visible-slides-k8cui

(Создано из https://codesandbox.io/s/withered-wood-4bx36?fontsize=14&hidenavigation=1&theme=dark)

Ответы [ 2 ]

0 голосов
/ 08 апреля 2020

У меня была такая проблема для моего приложения, и я не смог найти способ сделать это с CSS. Тем не менее, я реализовал это, используя ResizeObserver и react-hooks.
PS Я использую next js, и это не большая проблема для реализации его на стороне сервера.
Вот мое решение, надеюсь, оно может помочь.
Шаг 1. Создайте обработчик для прослушивания событий изменения размера из приложения.

import { useEffect, useState, RefObject } from 'react';
import ResizeObserver from 'resize-observer-polyfill';

interface DOMRectReadOnly {
  readonly bottom: number;
  readonly height: number;
  readonly left: number;
  readonly right: number;
  readonly top: number;
  readonly width: number;
  readonly x: number;
  readonly y: number;
}

interface useResizeObserverProperties {
  ref?: RefObject<Element> | null;

  element?: Element | null | undefined;

  callback?: (entry: ResizeObserverEntry) => void;
}

const IS_BROWSER = typeof window !== 'undefined';

/**
 * Watch for the resizing of a React component or Element.
 *
 * @param hookProperties - Configuration optinos for the hook.
 *
 * @returns The `DOMRect` for the observed element.
 */
export const useResizeObserver = ({
  ref,
  element,
  callback,
}: useResizeObserverProperties) => {
  const [sizes, setSizes] = useState<DOMRectReadOnly>({
    bottom: 0,
    height: 0,
    left: 0,
    right: 0,
    top: 0,
    width: 0,
    x: 0,
    y: 0,
  });

  const handleResize = (entries: ResizeObserverEntry[]) => {
    const [entry] = entries;

    if (callback) callback(entry);

    setSizes(entry.contentRect);
  };

  const [resizeObs] = useState(() =>
    IS_BROWSER ? new ResizeObserver(handleResize) : undefined,
  );

  useEffect(() => {
    if (!resizeObs) return;
    let domNode;

    if (ref) {
      domNode = ref.current;
    } else if (element) {
      domNode = element;
    }

    if (domNode) {
      resizeObs.observe(domNode);
    }

    return () => resizeObs.disconnect();
  }, [ref, resizeObs, element]);

  return sizes;
};

Шаг 2. В ваших component.tsx


import React, { useState, useRef } from 'react';
import { CarouselProvider, Slider, Slide } from 'pure-react-carousel';
import { useResizeObserver } from 'from previously created file';

const YourComponent = () => {
  const [visibleSlides, setVisibleSlides] = useState(1);
  const ref = useRef<HTMLDivElement>(null);

  // Current width of element
  const { width } = useResizeObserver({ ref });

  switch (true) {
    case width > 768 && width < 1280:
      setVisibleSlides(2);
      break;
    /**
     * Switch your cases here
     */
  }

  return (
    <div ref={ref}>
      <CarouselProvider
        naturalSlideWidth={100}
        naturalSlideHeight={125}
        totalSlides={3}
        visibleSlides={visibleSlides}
      >
        <Slider>
          <Slide index={0}>Slide 1</Slide>
          <Slide index={1}>Slide 2</Slide>
          <Slide index={2}>Slide 3</Slide>
        </Slider>
      </CarouselProvider>
    </div>
  );
};

export default YourComponent;

Кстати, я рекомендую вам throttle setVisibleSlides вызовов, чтобы избежать слишком большого количества повторных рендеров при изменении размера окна. из dev-tools.

0 голосов
/ 28 марта 2020

не ответ, но я пытаюсь сделать то же самое. Как насчет использования перехватчиков React useState для целого числа visibleSlides и создания прослушивателя окна, который прослушивает точки останова и изменяет состояние по мере необходимости ...

...