Как настроить стратегию наложения материала cdk, которая прекрасно работает как на больших, так и на маленьких экранах? - PullRequest
2 голосов
/ 02 ноября 2019

Вопрос

Как настроить стратегию положения наложения материала cdk, которая отлично работает на больших и маленьких экранах?

Цель

МойЦель состоит в том, чтобы создать наложение с помощью Углового наложения CDK , которое следует этим правилам:

  • Никогда не размещайте наложение вне области просмотра
  • Максимальная высота 300 пикселей
  • Положение наложения y с приоритетом сверху, по центру снизу.
  • На экранах с высотой ниже 300 используйте доступную высоту.
  • Другими словами, минимальная высота отсутствует.

Что работает ?

Я выполнил некоторые из вышеуказанных требований, как вы можете видеть здесь, позиционирование отлично работает на устройствах с достаточным вертикальным пространством (вв этом случае 512px):

enter image description here

сломанная часть ?

Однако, как вы можете видеть из следующего рисунка, это не работает на небольших устройствах с недостаточным вертикальным пространством (в этомcase 255px). На самом деле, как вы можете сказать из GIF, в 2 случаях это было очень близко. Положение было правильным, была отключена только высота.

enter image description here

Здесь цель состоит в том, чтобы использовать доступное пространство, как показано красным:

enter image description here

Код ?

У меня есть стек блиц, где вы можете экспериментировать здесь .

компонент

openPopup(element: any) {
    const overlayRef = this.overlay.create({
      hasBackdrop: true,
      positionStrategy: this.overlay.position()
      .flexibleConnectedTo(element)
      .withLockedPosition()
      .withPositions([
        {
          panelClass: 'custom-panel1',
          originX: 'center',
          originY: 'center',
          overlayX: 'start',
          overlayY: 'top',
        },
        {
          panelClass: 'custom-panel2',
          originX: 'center',
          originY: 'center',
          overlayX: 'start',
          overlayY: 'center',
        },
        {
          panelClass: 'custom-panel3',
          originX: 'center',
          originY: 'center',
          overlayX: 'start',
          overlayY: 'bottom',
        },
      ])
      ,
      width: '200px',
      maxHeight: 300,
    });

    const popupComponentPortal = new ComponentPortal(PopupComponent);

    overlayRef.attach(popupComponentPortal);

    overlayRef.backdropClick().subscribe(() => {
      overlayRef.dispose();
    });
  }

глобальные стили

.cdk-overlay-pane {
    max-height: 300px;
}

Примечания

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

Я рекомендую использовать «Открыть в новом окне LIVE»"особенность stackbllitz, при тестировании stackblitz. Ссылка здесь снова .

Я был бы НАСТОЛЬКО благодарен, если бы вы могли помочь решить эту проблему или указать мне правильное направление ??‍♂️

Ответы [ 2 ]

1 голос
/ 04 ноября 2019

Я решил вышеуказанную проблему, осуществив проверку - после открытия диалога. Это делается с помощью наблюдателя изменения размера. Код выглядит следующим образом:

/*
        Read more about the resize observer here: https://developers.google.com/web/updates/2016/10/resizeobserver
        Basicaly, what we do is that we subscribe to size events on the overlay.
        Currently we only get one event, (then we disconnet the resize observer).
        But then we simply calculate if we need to improve the layout.
        */
        const ro = new ResizeObserver(entries => {
            for (const entry of entries) {
                // We get the hight of the element from the the contnetRect, provided by the resize observer
                const height = entry.contentRect.height;

                const { left: x, top: y } = entry.target.getBoundingClientRect();

                const offsetPlusHeight = y + height;

                const pixelsOverflow = offsetPlusHeight - this.viewPortHeight;
                // If y is negative, we are off-screen to the top.
                // If pixelsOverflow is positive, we are off-screen on the bottom
                // In either case, we adopt a new strategy.
                if (y < 0 || pixelsOverflow > 1) {
                    ro.disconnect();
                    overlayRef.updateSize({
                        height: height,
                        maxHeight: config.maxHeight,
                        width: config.width,
                    });
                    // Trust the initial positioning strategy, in terms of the x coordinate

                    // Now determine if we need to throw the overlap, all the way to the top.
                    const delta = this.viewPortHeight - height;
                    const yOffset = delta > 0 ? delta : 0;

                    // Finnaly, we can apply canculate and apply the new position
                    const newPositionStrategy = this.getGlobalPosition(yOffset, x);
                    overlayRef.updatePositionStrategy(newPositionStrategy);
                }
            }
        });

        // Element for which to observe height and width
        ro.observe(overlayRef.overlayElement);

Я думаю, что мне нужна дополнительная проверка, потому что я на самом деле ищу стратегию наложения cdk для элементов с переменной высотой.

Если вы заинтересованы в рабочем решении, у меня есть рабочий стекблиц здесь :

enter image description here

0 голосов
/ 02 ноября 2019

Для высоты вы можете заменить:

maxHeight: 300,

на

height: window.innerHeight < 300 ? window.innerHeight + 'px' : '300px',

Это просто идея. Неплохо напрямую использовать окно в вашей компонентной сети, потому что вы не можете его смутить. Отметьте эту статью , если хотите знать, как это сделать правильно.

...