@MarvinJan

Как оптимизировать динамический truncate середины списка?

Добрый вечер, коллеги!

В общем, есть одна интересная задачка - она решена, но оптимизация оставляет желать лучшего, о чем и хотел с вами посоветоваться.

Суть задачи: есть в ангуляре массив строк
["Java",  "projects",  "dev",  "test",  "controller",  "src",  "main",  "resources",  "application"]


Каждая строка выводится в li > a через *ngFor. Все li - горизонтально, в строку. Так вот, когда элементы начинают залезать на следующую строку нужно усекать весь список по центру и добавлять туда "..." , то есть было:
Java projects dev test controller src main resources application


А на меньшем экране стало:

Java projects ... main resources application

В данный момент реализовано следующим образом:

public truncateRow() {
    if (this.isExcessiveWidth() && this.truncatedItems.length > 3) {
      const centralItemIndex = Math.floor((this.truncatedItems.length - 1) / 2);
      this.truncatedItems.splice(centralItemIndex, 2, "...");
      return setTimeout(() => {
        this.truncateRow();
      });
    }
  }


1. Проверяется необходимость усечения методом isExcessiveWidth (сравнивает высоту ul родителя с первым li, если больше = нужно урезать) и наличие как минимум 3 строк в массиве, чтобы с учетом добавления "..." был минимум в 3 строки всегда.

2. Далее берем центральный элемент массива, вырезаем его и последующий, добавляем на их место троеточие.

3. Повторяем до тех пор пока условия не перестанут выполняться.

setTimeout нужен, чтобы дать новым измерениям ul отрендериться.

Так вот собственно вопрос:

Все это работает, но: процесс "усечения" заметен для человеческого глаза - страдает user experience.

Возможно есть какой то другой подход, без рекурсии, либо с ней, но более оптимизированный?
  • Вопрос задан
  • 89 просмотров
Пригласить эксперта
Ответы на вопрос 2
Xuxicheta
@Xuxicheta Куратор тега Angular
инженер
Вместо явного дочернего li создаешь невидимый с opacity: 0; position: absolute, чтобы вывести его из потока и визуально скрыть. В отличии от display: none элемент будет отренденер и будут доступны его геометрические размеры.
Получаешь его длину, получаешь длину родителя, усекаешь массив пока li не станет короче родителя.
И только потом показываешь основной li с усеченным массивом.
Можно использовать тот же li, только класс поменять ему.
Ответ написан
@forspamonly2
если у вас там нет сложных текстов (со всякими rtl фрагментами и прочими влияющими на компоновку извращениями), то можно попробовать посчитать размеры руками используя measureText от canvas
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы