Пресъздаване на Ripple Effect част от Google Design
Bulgarian (Български) translation by Mihail Petrov (you can also view the original English article)



Основна тема на разговорите последно време е новият подход на Google към дизайна. Но вместо да говорим за теорията зад концепцията Material Design, ще се съсредоточим върху някой интересни техники които компанията е имплементирала в дизайна на началната страница на технологията, която ни представиха.



Когато потребителите натиснат някой от блоковете пред тях, се наблюдава изпълване на пространството посредством векторен кръг. Google нарича този ефект touch ripple, а ние ще се опитаме да го пресъздадем с помощта на JQuery, HTML и CSS.
Скелет на приложението
Преди да започнем работа ни е необходимо да създадем прост скелет, под формата на мрежа без помощта на никакви външни библиотеки.
1 |
<div class="row"> |
2 |
<div class="col col-1-3 blue"></div> |
3 |
<div class="col col-1-3 orange"></div> |
4 |
<div class="col col-1-3 green"></div> |
5 |
</div>
|
6 |
<div class="row"> |
7 |
<div class="col col-1-2 gray"></div> |
8 |
<div class="col col-1-2 blue"></div> |
9 |
</div>
|
10 |
<div class="row"> |
11 |
<div class="col col-1-4 orange"></div> |
12 |
<div class="col col-1-2 green"></div> |
13 |
<div class="col col-1-4 blue"></div> |
14 |
</div>
|
В имената на класовете, с тире са отразени дробните размери на колоните на мрежата ( 1-3 => 1/3 ).
Основни стилове
Следващата стъпка е да напишем кода за класовете на колоните. За целта ще ползваме LESS, който ни дава възможност да влагаме стиловете един в друг, както и да използваме оператора &
. Няма да навлизаме в подробности касаещи LESS, но въпреки това че обясним значението на оператора &
. Преди това вижте кода за класовете на колоните.
1 |
.col { |
2 |
position: relative; |
3 |
display: block; |
4 |
float: left; |
5 |
margin: 1.25%; |
6 |
background-color: #444; |
7 |
color: #fff; |
8 |
padding: 100px; |
9 |
box-sizing: border-box; |
10 |
&.orange { |
11 |
background-color: #EF8130; |
12 |
}
|
13 |
&.blue { |
14 |
background-color: #00ADE2; |
15 |
}
|
16 |
&.gray { |
17 |
background-color: #444; |
18 |
}
|
19 |
&.green { |
20 |
background-color: #76CE51; |
21 |
}
|
22 |
&-1- { |
23 |
&2 { |
24 |
width: 47.5%; |
25 |
}
|
26 |
&3 { |
27 |
width: 30.8333%; |
28 |
}
|
29 |
&4 { |
30 |
width: 22.5%; |
31 |
}
|
32 |
}
|
33 |
}
|
Оператора &
, долепя името на родителският елемент към името на вложеният елемент. Следващият пример илюстрира действието на оператора.
1 |
.col { |
2 |
&-1 { |
3 |
&-3 { |
4 |
color: #fff; |
5 |
}
|
6 |
}
|
7 |
}
|
Ще бъде компилиран до следният код:
1 |
.col-1-3 { color: #fff; } |
Както и този код
1 |
&.col { |
2 |
&.orange { |
3 |
background-color: #EF8130; |
4 |
}
|
5 |
}
|
Ще доведе до следният резултат
1 |
.col.orange { |
2 |
background-color: #EF8130; |
3 |
}
|
Ако искате да научите повече за технологията LESS, можете да почерпите повече информация от следните уроци.
Как работи векторната графика (SVG)
Нека сега обясним по какъв начин ще създадем ефекта със запълване на блока при натискане на бутона на мишката. Въпроса е да разберем как да създадем векторен кръг в рамките на натиснатият блок.



Когато потребителя натисне блока, е необходимо да изчислим разстоянието от курсора до краищата на блока, в който се намираме. След това ще ползваме намерените координати за да изчертаем кръг. Векторният елемент ще бъде позициониран с абсолютни координати в рамките на блока, докато той самият ще бъде позициониран релативно спрямо елемента. За целта ще ползваме SVG елемента #
Първата ни работа е да създадем стилови правила за векторните елементи.
1 |
svg { |
2 |
position: absolute; |
3 |
top: 0; |
4 |
left: 0; |
5 |
width: 100%; |
6 |
height: 100%; |
7 |
}
|
8 |
circle { |
9 |
fill: rgba(255,255,255,0.1); |
10 |
}
|
За запълване на кръга, използваме алфа канала(прозрачност), даден ни от свойството RGBa, като дефинираме стойност на прозрачност в рамките на 10%.
JavaScript кода
Ще дефинираме слушател за събитието, щракване с мишката върху елемент с клас .col
. След това ще вземем релативната позиция на елемент спрямо документа.
Улавяне позицията на мишката
Позицията на мишката е относителна спрямо блока. За да вземем координатите на горният ляв ъгъл използваме метода $(this).offset()
.
1 |
$(".col").on("click", function(e){ |
2 |
var x = e.pageX; |
3 |
var y = e.pageY; |
4 |
var clickY = y - $(this).offset().top; |
5 |
var clickX = x - $(this).offset().left; |
6 |
var box = this; |
7 |
// ...
|
8 |
});
|
Забележка: В рамките на примерите ползваме библиотеката jQuery.
Конвертираме стойностите на променливите clickX
и clickY
, в целочислени стойности, като така избягваме несъответствия при визуализирането на ефекта в различни браузъри.
1 |
var setX = parseInt(clickX); |
2 |
var setY = parseInt(clickY); |
Премахване на съществуващите векторни елементи.
Налага се да премахнем всички съществуващи SVG елементи които съществуват в рамките на блока върху който щракаме. Ако смятате да добавяте векторно съдържание в рамките на блока, е добре да ползвате метод като jQuery's.not()
, в комбинация с някакъв клас, като по този начин гарантирате, че няма да премахнете точно този специфичен елемент.
1 |
$(this).find("svg").remove(); |
Добавяне на новият векторен елемент
Следва да добавим векторният елемент, като подадем текстово съдържание на функцията:
1 |
$(this).append('<svg><circle cx="'+setX+'" cy="'+setY+'" r="'+0+'"></circle></svg>'); |
Полетата setX
и setY
, определят центъра на векторният кръг, точно там където активираме щракването с мишката.
Анимация
Остава да анимираме, радиуса на кръга с помощта на jQuery функцията animate
. На всяка стъпка се налага да извикаме метод, които ще се погрижи за промяна на радиуса на елемента.
1 |
var c = $(box).find("circle"); |
2 |
c.animate( |
3 |
{
|
4 |
"r" : $(box).outerWidth() |
5 |
},
|
6 |
{
|
7 |
easing: "easeOutQuad", |
8 |
duration: 400, |
9 |
step : function(val){ |
10 |
c.attr("r", val); |
11 |
}
|
12 |
}
|
13 |
);
|
Не забравяйте че елемента box
, беше дефиниран по рано. В рамките на този код, използваме изинга(""easeOutQuad"") на jQuery .
Завършеният код
Завършеният вид на кода изглежда така:
1 |
$(".col").on("click", function(e){ |
2 |
var x = e.pageX; |
3 |
var y = e.pageY; |
4 |
var clickY = y - $(this).offset().top; |
5 |
var clickX = x - $(this).offset().left; |
6 |
var box = this; |
7 |
|
8 |
var setX = parseInt(clickX); |
9 |
var setY = parseInt(clickY); |
10 |
$(this).find("svg").remove(); |
11 |
$(this).append('<svg><circle cx="'+setX+'" cy="'+setY+'" r="'+0+'"></circle></svg>'); |
12 |
|
13 |
|
14 |
var c = $(box).find("circle"); |
15 |
c.animate( |
16 |
{
|
17 |
"r" : $(box).outerWidth() |
18 |
},
|
19 |
{
|
20 |
easing: "easeOutQuad", |
21 |
duration: 400, |
22 |
step : function(val){ |
23 |
c.attr("r", val); |
24 |
}
|
25 |
}
|
26 |
);
|
27 |
});
|
Заключение
Ефекта, който ви показах може да намери множество приложения различни от демонстрираното. Например можете да идентифицирате позицията, върху която е щракнал потребителя в рамките на произволно изображение, което от своя страна може да създаде ефект на изскачащ прозорец за коментари. Приложенията са наистина много, помислете какви бихте предложили вие.
Няколко примера
- Polymer paper elements paper-ripple
- Ripples Effect Button - on CodePen
- Google Material Design - on CodePen
- Material Design Buttons - on CodePen