今一番気になるCSSの美しいエフェクト!インクを水面に落としたように波紋が広がり消えていく -Ripple Click Effect

Googleが先日発表した新しいUX「Material Design」の中で特に注目されているのが、タップやクリックをするとインクを落としたように波紋が広がるエフェクト。
これを実装するテクニックを紹介します。

Material Designについては、前の記事(「波紋」のアニメーションを実装するテクニック)で動画を紹介しています。

デモのアニメーション

この波紋のエフェクトはあちこちのコミュニティで盛んで、その中でもここで紹介するエフェクトはかなり美しく仕上がっています。

デモではリストで配置したナビゲーションの各アイテムをクリックすると、そのクリックした地点を中心に波紋が広がり、フェードで消えていきます。
※上記はエフェクトが分かりやすいよう、各アイテムの高さを広げています。

実際の動作は、下記ページでお楽しみください。

サイトのキャプチャ

Ripple Click Effect from Google Material Desing

波紋のエフェクトのみであればスタイルシートで実装は可能ですが、クリックの地点を中心にエフェクトを適用するためスクリプトを使用しています。

HTML

各アイテムをリスト要素で実装します。

<ul>
	<li><a>Dashboard</a></li>
	<li><a>My Account</a></li>
	<li><a>Direct Messages</a></li>
	<li><a>Chat Rooms</a></li>
	<li><a>Settings</a></li>
	<li><a>Logout</a></li>
</ul>

CSS

リストのスタイル、波紋とフェードのエフェクトはスタイルシートで実装されています。

/*custom fonts - Bitter, Montserrat*/
@import url('http://fonts.googleapis.com/css?family=Montserrat|Bitter');
/*basic reset*/
* {margin: 0; padding: 0;}
body {
	background: url('http://thecodeplayer.com/u/m/b1.png') no-repeat center center fixed;
	background-size: cover;
}

h1 {
	font: normal 32px/32px Bitter; color: white;
	text-align: center; padding: 85px 100px;
}

/*nav styles*/
ul {
	background: white; border-top: 6px solid hsl(180, 40%, 60%);
	width: 200px; margin: 0 auto;
}
ul li {
	list-style-type: none;
	/*relative positioning for list items along with overflow hidden to contain the overflowing ripple*/
	position: relative;
	overflow: hidden;
}
ul li a {
	font: normal 14px/28px Montserrat; color: hsl(180, 40%, 40%);
	display: block; padding: 10px 15px;
	text-decoration: none;
	cursor: pointer; /*since the links are dummy without href values*/
	/*prevent text selection*/
	user-select: none;
	/*static positioned elements appear behind absolutely positioned siblings(.ink in this case) hence we will make the links relatively positioned to bring them above .ink*/
	position: relative;
}

/*.ink styles - the elements which will create the ripple effect. The size and position of these elements will be set by the JS code. Initially these elements will be scaled down to 0% and later animated to large fading circles on user click.*/
.ink {
	display: block; position: absolute;
	background: hsl(180, 40%, 80%);
	border-radius: 100%;
	transform: scale(0);
}
/*animation effect*/
.ink.animate {animation: ripple 0.65s linear;}
@keyframes ripple {
	/*scale the element to 250% to safely cover the entire link and fade it out*/
	100% {opacity: 0; transform: scale(2.5);}
}

JavaScript

jquery.jsを外部ファイルとして、下記のスクリプトを使用します。

//jQuery time
var parent, ink, d, x, y;
$("ul li a").click(function(e){
	parent = $(this).parent();
	//create .ink element if it doesn't exist
	if(parent.find(".ink").length == 0)
		parent.prepend("<span class='ink'></span>");
		
	ink = parent.find(".ink");
	//incase of quick double clicks stop the previous animation
	ink.removeClass("animate");
	
	//set size of .ink
	if(!ink.height() && !ink.width())
	{
		//use parent's width or height whichever is larger for the diameter to make a circle which can cover the entire element.
		d = Math.max(parent.outerWidth(), parent.outerHeight());
		ink.css({height: d, width: d});
	}
	
	//get click coordinates
	//logic = click coordinates relative to page - parent's position relative to page - half of self height/width to make it controllable from the center;
	x = e.pageX - parent.offset().left - ink.width()/2;
	y = e.pageY - parent.offset().top - ink.height()/2;
	
	//set the position and add class .animate
	ink.css({top: y+'px', left: x+'px'}).addClass("animate");
})

top of page

©2017 coliss