Расчёт итогового размера с flex-shrink [12/28], не могу понять, в чём суть расчёта.

Да, напишите пожалуйста, хочется понять лучше по этим свойствам.

Всем доброго дня! В примере с flex-shrink все формулы описаны абсолютно правильно, не написано только что с ними делать дальше, и почему одно из значения всегда равно 1 (хотя про нормировку там упомянули).

Возьмем этот пример, в нем три контейнера с базовой шириной 200, 400 и 200px соответственно необходимо “ужать” до 150, 100 и 50px. Составим три уравнения (см.рис1), подставив цифры и решив аналитически получим z=y=3x. Полученная система уравнений имеет бесконечное множество решений (в этом примере три уравнения, решение можно представить графически в виде прямой,т.е. бесконечного количества точек, в пространстве), исключение составляет точка, в которой любое из значений равно нулю, т.к. в этом случае появляется ноль в знаменателе уравнений (деление на ноль). Тут нужно заметить, что и при значении flex-shrink=0 контейнер ведет себя исключительным образом - занимает всю базовую ширину и может выпасть из контейнера-родителя (деление на ноль->бесконечность).

На рисунке 1 представлено численное решение задачи подбора коэффициентов сжатия. В отличие от решения на рисунке 2 первая неизвестная задавалась явно х=1, а искались две оставшиеся. Ответ на первом рисунке: 1,1,3.
Теперь к вопросу о нормировке, почему первый неизвестный коэффициент принимается равным единице? Потому, что так удобнее считать, часто можно подобрать хорошие коэффициенты.
На рисунке 2 можно увидеть ту же систему уравнений, но поиск численных значений теперь идет по трем переменным (решатель использует метод Левенберга-Маркара, приближенные значения неизвестных нужны для начальных параметров алгоритма решения), ответ на втором рисунке: 0.4,1.2,1.2. Заметим, что цифры в ответах на рис.1 и рис.2 пропорциональны, т.е. их можно соотнести друг между другом (конкретно в этом примере: первый и второй коэффициенты в три раза больше первого). Почему решатель выдал такой ответ - просто все неизвестные должны быть максимально близко к заданным приближенным значениям решателя =1(вспомните МНК). Но, как было сказано выше, решений у данной системы уравнений бесконечное множество, так что и этот ответ подходит. Для удобства можно выполнить нормировку - разделить вектор значений на значение первого неизвестного: 0.4/0.4=1, 1.2/0.4=3; 1.2/0.4=3, ответ: 1,3,3. Отсюда и берется первая единица, так удобнее считать и не нужно потом нормировать любое решение, мы получаем одно из множеств решений, но с “целым ориентиром”, равным 1.
На самом деле свойства будут адекватно работать, если ввести любое из множества решений с положительными значениями. Важно соотношение коэффициента сжатия элемента с коэффициентами других элементов, а не его значение.

Для наглядности удобства использования решения с x=1 сделал пример с 4 контейнерами (рис.3). Контейнеры с базовой шириной 100, 200, 300 и 400px соответственно необходимо “ужать” до 50, 75, 100, 75px. Решив численно систему уравнений получим ответ: 0.861, 1.076, 1.148, 1.399. После нормировки получаем ответ: 1, 5/4, 4/3, 13/8. В данном случае мы видим соотношение простых дробей, это стало заметно потому, что у нас появился “целый ориентир” в виде 1. Подобрав НОК дробям получим, что коэффициенты соотносятся как 24, 30, 32, 39. Такое представление результата уменьшит количество цифр в значении коэффициентов, не теряя при этом точности, и избавит код от десятичных дробей. Но задачи бывают разными, и такой фокус прокатит не всегда.

Успехов!
Игра, развивающая навыки по флексам.

С уважением, Alexey.

4 лайка

Прошу прощения за некропост, разбиралась сама и решила запостить свой вариант. Здесь, конечно, уже есть одно решение от уважаемого Kostroma, но, может, кому-то поможет моя альтернативная попытка разобраться :sweat_smile:

TL;DR: считаем для каждого элемента коэффициент k = (базовая ширина - новая ширина) / базовая ширина. Значения flex-shrink будут целыми числами, пропорциональными коэффициентам k (пример расчёта в конце).

Как выводится коэффициент:

Пройдём по механизму расчёта из [12/28]:

[1] ОП = Ширина контейнера - Сумма базовых размеров элементов
[2] СПБР = (Базовый размер1 * flex-shrink1) + (Базовый размер2 * flex-shrink2) + … + (Базовый размерn * flex-shrinkn)

На данном этапе эти величины нас не интересуют. Но обратим внимание на то, что в них не участвуют параметры конкретного элемента, а значит, ОП и СПБР будут одинаковы для всех элементов.

[3] НКС = (базовая_ширина * flex-shrink) / СПБР
[4] итоговая_ширина = базовая_ширина - (НКС * ОП)

Заменим НКС в шаге [4] на его значение из шага [3] и получим:

итоговая_ширина = базовая_ширина - ((базовая_ширина * flex-shrink) / СПБР) * ОП

Отсюда можем выразить значение flex-shrink (ОП для удобства внесём в скобки):

flex-shrink * базовая_ширина * ОП / СПБР = базовая_ширина - итоговая_ширина

flex-shrink = ((базовая_ширина - итоговая_ширина) / базовая_ширина) * (СПБР / ОП)

Но после шага [2] мы выяснили, что СПБР и ОП одинаковы для всех элементов – значит, коэффициент СПБР / ОП тоже будет одинаков для всех элементов. Из этого следует, что значение flex-shrink каждого элемента будет пропорционально коэффициенту k = (базовая_ширина - итоговая_ширина) / базовая_ширина, который мы можем легко посчитать для каждого элемента.

Пример расчёта: задача из п. 12

Проверим полученную формулу на примере. Итак, для элемента 1 базовая ширина равна 100px, а итоговая ширина – 50px. Для элемента 2 базовая ширина равна 300px, а итоговая ширина – 150px.

k1 = (100 - 50) / 100 = 50 / 100 = 1 / 2
k2 = (300 - 150) / 300 = 150 / 300 = 1 / 2

В целом, чтобы найти значения flex-shrink, нам понадобилось бы привести дроби к общему знаменателю и отбросить его, но в данном случае мы сразу видим, что коэффициенты равны, а значит, flex-shrink равны между собой и оба равны 1.

Спойлер: испытание из п. 14

Попробуем ещё один пример. В испытании “Мастер коэффициентов” у нас есть три блока со следующими параметрами: элемент 1 с базовой шириной 200px и итоговой шириной 150px, элемент 2 с базовой шириной 400px и итоговой шириной 100px и элемент 3 с базовой шириной 200px и итоговой шириной 50px. Подставляем значения в формулу:

k1 = (200 - 150) / 200 = 50 / 200 = 1 / 4
k2 = (400 - 100) / 400 = 300 / 400 = 3 / 4
k3 = (200 - 50) / 200 = 150 / 200 = 3 / 4

Отсюда flex-shrink первого элемента равен 1, flex-shrink второго элемента равен 3 и flex-shrink третьего элемента равен 3.

5 лайков

только с Вами и разобрался как высчитать… признателен за некропост)))

1 лайк