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

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

Похожие вопросы