rm /blog

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

【CSS】【jQuery】ストレイテナー公式サイトのシュビッて素早く動く黒い物体の正体を追跡してみた

2018年4月現在の、ストレイテナーの公式ホームページにおける、
リンク部分にマウスオーバーしたときに黒い物体が素早くシュビッ(?)って動くやつの正体を追跡してみた。
(「黒い物体が素早くシュビッて動く」ってゴキ○リみたいだな…まあいいか)

 

20180426_blog_image01.jpg


 

 


ソース開いてjsとcss見れば誰でもなんとなくわかってしまうが、実態としてはjQueryCSSで実現している。
左側に位置している縦のメニューの個々はリストタグ(li)で構成されているが、
このliタグはメニューとしてそれぞれを適正な場所に位置付ける役割のみであり、「シュビッて素早く動く黒い物体」を実現する役割は担っていない。
「シュビッて素早く動く黒い物体」は実はliタグの中に仕込まれたspanタグで、cssのtransitionによって変形操作を実施している。
spanタグには「初期状態」と「シュビッと動く」ときの2種類のclassがあり、最初の表示段階では前者のみがclassに設定されている。
liタグ内のaタグにマウスオーバーしたイベントをjQueryで拾って、spanタグに「シュビッと動く」classを追加して、用が済んだらclassを削除、
という流れで「シュビッて素早く動く黒い物体」を実現しているのである。

  1. spanタグには初期段階で「animate_bar」というクラスが設定されていて(これが上記の「初期状態」)
    要点だけかいつまむと、背景黒(background-color:#000;)でliタグ全体(width:100%;)を埋め尽くすようになっている。
    ただ初期段階でこれが見えるとかっこ悪いので、transform: translateX(-100%);というCSSにより、画面外に追い出されている。
    この「初期段階での非表示」には多分いろいろ実現方法があり、opacity:0で透明にするとかでも実現可能。
    (テナーの公式サイトはtranslateXで画面外に追い出すやり方を採用していた、というだけだと思う)
  2. 「aタグにマウスオーバーする」は、jQueryのonでイベントの発生契機を捉えている。
    テナーの公式サイトの実装ではmouseovertouchstartを設定していた。
    この処理内で、「aタグの隣にいるanimate_barというクラス」に「menu-action」というクラスを追加している。(=$("a").prev(".animate_bar").addClass("menu-action"))
  3. マウスオーバー時に動的追加されるクラス「menu-action」では、transform: translateX(100%);により、横幅目いっぱいに要素を変形させる。
    その際、transition: cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.3s;の指定により、変形速度をコントロールしている。
    cubic-bezierはベジエ関数で、引数の詳細はどこまで詰められたものかはわからないが、↑の数値はテナー公式サイトの実装通り。
    これを0.3秒で行え、という指示になっている。
  4. 「animate_bar」というクラスに対しては、「transitionの完了」をイベントとして捉え、
    マウスオーバー時に動的追加されているクラス「menu-action」を削除する処理もjQueryで実装されている。
    このときの「transitionの完了」は旧バージョンのブラウザなども考慮してかなり多くのイベント名が列挙されていた。


簡単に言えばこんなところか。
つくってみたテストHTMLはこんな↓感じ。

<html>
	<head>
		<meta charset="UTF-8">
		<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
		<script>
		$(function(){
			var menuActionClassName = "menu-action";
			var transitionEndEvent = 'webkitTransitionEnd MozTransitionEnd mozTransitionEnd msTransitionEnd oTransitionEnd transitionEnd transitionend';
			↑4.で指定しているtransition完了のイベント名
			
			$("a").on('mouseover touchstart' , function(){         ←2.の部分
				$(this).prev(".animate-bar").addClass(menuActionClassName);
			});
	
			$(".animate-bar").on(transitionEndEvent,function(){   ←4.の部分
				$(this).removeClass(menuActionClassName);
			});
		});
		</script>
		<style type="text/css">
		li {
			display: list-item;
			position:relative;
			margin-right:20px;
			overflow:hidden;
		}
		.animate-bar {   ←1.の部分
			display: block;
			position: absolute;
			top: 0;
			bottom:0;
			width:100%;
			height:16px;
			margin: auto;
			background-color: #000;
			transform: translateX(-100%);
		}
		.animate-bar.menu-action {   ←3.の部分
			transform: translateX(100%);
			transition: cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.3s;
			/*transition: cubic-bezier(0.25, 0.46, 0.45, 0.94) 1.5s;*/
		}
		</style>
		<title>straightener animation bar test</title>
		
	</head>
	<body>
		<ul>
			<li>
				<span class="animate-bar"></span>
				<a>NEW</a>
			</li>
			<li>
				<span class="animate-bar"></span>
				<a>LIVE</a>
			</li>
			<li>
				<span class="animate-bar"></span>
				<a>ABOUT</a>
			</li>
		</ul>
	</body>
</html>


これは「シュビッて素早く動く黒い物体」を実現するのに必要な部分だけを抜粋しているので、テナー公式サイトの実装とは細部が異なる。
(テナー公式サイトのほうがもっと”凝って”いる)
なお、一部コメントにしてあるのは、実験と検証目的で追加したものなので、無視して構わんですたい。

作ってみて思ったけど、この動作は、
「同じ幅の要素」に対して適用されるから綺麗に映るのであって、
ガタガタの幅の(=それぞれが異なる幅を持つ)要素に対して適用してもそこまでいい見栄えにならない

というのが実態のようだった。
まあ感じ方は人それぞれなんだろうけど…
その点、テナー公式サイトでは、左側に縦にズラっと並んだ要素がそれぞれ均一の幅で構成されていて、
マウスを動かすと、つられて一緒に流れるようにスライドしていく「黒い物体」は、非常に滑らかな動きとして映る。
この辺はデザインセンスなんでしょうなあ。

ストレイテナーの公式サイトは、恐らくWEBデザイナーさんが手がけられているのだろうから、
そうした専門の方が作り上げたフロントエンド側のモダンな表現手法の要点を、
一部分だけでも解き明かせたのはいい勉強になったかなと思う。
学習しようと思えば、身近にこういう題材がゴロゴロ転がっているのは非常に良いことですな。