[Из песочницы] Как мы звезды рейтинга дробили
Вместо предисловия
Привет всем хабражителям! Взбрело мне как-то, холодным зимним вечером внести на сайт вместо целых звезд рейтинга — их частичную заливку для дробных чисел (4.5, 3.85 и тд.). Так ведь и глазу милее и информативнее — какое заведение лучше, а какое хуже. Вот и сели мы с командой думать и гадать.
Как мы путь свой искали
Но тут возникли нюансы. Самая распространенная практика — использовать наложение изображения одно поверх другого. С самого-самого начала мы думали сделать все с помощью изображения-маски, но увы, дизайн не подразумевал, что звездочки могут быть рядом, а контролировать ширину блока заливки и размер звезды не очень удобно.
Тут у Кинопоиска все 10 звезд — одна картинка, где они еще и приклеены друг к другу. Так им очень легко закрасить оранжевым на столько, на сколько душа желает.
.starbar .outer {
background: url(/images/starz.gif) no-repeat;
width: 219px;
height: 30px;
position: absolute;
}
.starbar_w {
display: block;
width: 167.09px;
background: url(/images/starz.gif) 0 -62px no-repeat;
height: 30px;
position: absolute;
}
Всегда есть где разгуляться!
Всё же, нам хотелось универсальный и масштабируемый вариант, полностью подчиняющийся BEM методологии. К тому же в проекте нет ни одного спрайта и все иконки реализованы с помощью собственного набора иконок, бережно собранного в шрифт. Но, думаю, об этом мы поговорим в других статья ;)
В целом, мы пришли к эксперименту:, а почему бы не наложить нашу шрифтовую иконочку поверх другой? Вот мы и сделали:
Каждую звездочку сделали отдельным объектом, состоящей из .stars__out в качестве контейнера и .stars__in в качестве заливки.
А вот и CSS:
.cfi.cfi--star { /* ... */ } /* наш аналог Font Awesome, который рисует звезду */
.stars__out {
position: relative;
margin-right: 5px; /* сделаем отступ между зведами */
color: grey;
z-index: 1;
}
.stars__in {
/* разместим ка мы нашу заливку как дочернюю основной иконки и кинем поверх */
position: absolute;
z-index: 2;
color: orange; /* дадим солнечного цвета */
font-size: inherit; /* и шрифту размер родителя */
/* блоку дадим точки отчета по нулям относительно родителя */
display: block;
top: 0; left: 0; bottom: 0;
/* ну и ограничим область видимости, а также ширину установим в 0 по умолчанию */
overflow: hidden;
width: 0;
}
Все. Дальше, когда нам нужно залить на 100% (полная звездочка), мы просто даем ей CSS свойство width: 100%.
А вот для не полных звездочек, мы использовали еще одну хитрость. Мы ставим в ширину не x * 100%, а значение по специально рассчитанной формуле.
Все дело в психологии. Нам свойственно визуально воспринимать процент заполнения в объеме, а не в ширине, а по сколько звезда слева и справа имеет весьма малую площадь, что усложняет восприятие, мы придумали заполнять звезду по ширине нелинейно:
Для нелинейной модели мы взяли синусоиду. Она как раз отлично описывает плавное начало и окончание роста, и быстрый рост в средине.
Развернули ее, получив arksin, ужали его в рамки {0; 1} по обоим осям и получили не плохую и простую формулу для расчета «психологической заполненности» звезды.
Код на JavaScript:
var y = Math.asin( 2 * x - 1 ) / Math.PI + 0.5;
Как оказалось, такой принцип хорошо работает в старых браузерах, и даже ничего не ползет на IE9. И довольны были все — и дизайнеры, и заказчики, и даже мое Эго, что и побудило меня статью накатать.
Искренне надеюсь, что кому нибудь это понадобиться :)
Комментарии (2)
29 декабря 2016 в 14:28 (комментарий был изменён)
–2↑
↓
Такая визуализация не информативна для пользователя без цифр.
Нельзя навскидку сказать это 60%, 70%, 80% или на какой из двух картинок больше процентов?
Простое разбиение на 10 частей позволяет сразу ответить на оба вопроса, закрашивая каждый сектор добавляем 10%29 декабря 2016 в 15:21
0↑
↓
Вот за нелинейную заливку прям спасибо вам!