Edited at

Gulp + Bower + skrollr.jsを使ってパララックス実装をしてみたよ

More than 1 year has passed since last update.


はじめに

こんにちは、たいがです。

Life is Tech!で、今年の6月からWebサービスプログラミングコースのメンターとして参加しています。

Life is tech!では、Rubyのフレームワークであるsinatraを使用して開発を行っています。

なので、普段はRubyを触ることが多いのですが、今回はポートフォリオサイトを作成したことについてお話したいと思います!

少し長くなると思いますが、お付き合いいただけると幸いです。


ポートフォリオ作成の経緯


  • 個人作成とは別のところでgulpを使用する必要があったため、自分の理解を深める必要があると感じた


  • Skrollr.jsというJavascript(以下JS)のライブラリに興味を持ち使ってみたいと思った。

ことが挙げられます。そして自分の経験や技術をストックしておく場所がなかったことが今回の経緯です!


今回のポートフォリオの概要


技術スタック


  • JQuery

  • Skrollr.js

  • Gulp

  • Bower

  • npm


概要

ポートフォリオの見た目はこんな感じです

portfolio.jpg

ソースも公開しているので、参考または、アドバイスください。

https://github.com/Shichisan/portfolio


前提知識


Gulpとは?

gulp-logo.jpg

Gulpとは、Node.jsで動くビルドシステムヘルパーです。簡単に言うと、ビルド自動化ツールです。

今までのフロントエンド開発は、SassCoffeeScriptなどを使用する際、その都度コンパイルという作業をしなければならず、この作業はとても非効率でエンジニアにとってストレスになりやすいものでした。また人の手でコンパイルするということは、必ずミスを誘発するものでもあるのです。

しかし、Gulpを使用することでファイルの変更を検知して自動でコンパイルしてくれるためフロントエンドの開発がとても効率的になり、更に必要な作業を定義しておくだけでそれにしたがって自動でビルドをするため人であれば犯す可能性があるミスを無くすことができます!

また


  • タスクという単位で処理を分割することができる。


  • gulpfile.jsというgulpの設定ファイルにビルド時の作業を簡単に記述することができる。

  • 単一のタスクにたんして.pipe()を使用して処理をつなげることができるため、そのタスクが何をするものなのか直感的に理解することができる。

  • プラグインも豊富でカスタマイズ次第で自分のプロジェクトにあったビルドツールになりえること。

ということも利点です。

実際、ポートフォリオ開発では、大活躍でした!


  • 公式サイト


https://gulpjs.com



Bowerとは?

bower-logo.png

Bowerは、フロントエンド用のパッケージ管理ツールです。Sinatraで言うところのGemのような位置づけのものだと勝手に思っています。

npmは、ビルドの際に必要なプラグインやライブラリをインストールすることができたりしますが、bowerは、フロントエンドで使用するライブラリを取得することができます。

今回のポートフォリオでは、jQuerySkrollr.jsbowerでインストールして使用しています。


Skrollr.jsとは?

近いものは早く、遠いもの遅く移動させることで生まれる視差効果(パララックス)をサイトに簡単に実装することができるJSのライブラリです!

どんなことができるかは公式のデモを見て頂くのが一番早いと思います!

具体的には、JSの.scrollTop()取得することができるブラウザのスクロール量をトリガーにして様々なスタイルを適応することができるのでスクロールだけで様々な表現をブラウザ上にもたらすことができるのが特徴です。


実際に作ってみる!


実行環境

この環境では、node,npmを使用するので、インストールされてない人は、予め入れておいてください

これは参考までに

Node.jsとnpmインストールとアップデート


  • バージョン


node v7.4.0

npm 4.0.5



まずは、gulpをインストール


  • ターミナルを使用して、作業用のディレクトリを切ります。

$ mkdir YOUR_DIRECTORY_NAME

YOUR_DIRECTORY_NAMEは好きな名前にしてください。


  • npmでビルドをする際に必要なライブラリたちを定義するためのpackage.jsonを作成します。

$ npm init

色々質問されますが、基本的にenterを押し続けていいと思います。

ちなみにpackage.jsonの中身はこうなっているはずです。


package.json

{

"name": "portfolio",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}



  • gulpnpmを使用してインストールします

gulpコマンドを使えるようにするため、システムにgulpをインストールする

$ npm install -g gulp gulp-cli

プロジェクト内にgulpをインストールする
$ npm install -D gulp # これを実行することにより、package.jsonにgulpのインストール情報が定義される

この時package.jsonはこうなっているはずです。


package.json

{

"name": "portfolio",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"gulp": "^3.9.1"
}
}

インストール前のファイルと比較してみるとdevDependenciesというところに"gulp": "^3.9.1"という行が追加されているのがわかると思います。

なぜこれをするかというと、今は、1つのライブラリだからいいですが、ライブラリがたくさん増えてきたときに他の人のパソコンで私のポートフォリオサイトを開発する場合、一つ一つのライブラリに対して、npm install LIBRARY_NAMEとするのは手間ですよね?

しかしpackage.jsonに定義しておくことでnpm installのみでpackage.jsonにかかれているライブラリたちをインストールしてくれるんです!これをすることによって、他の環境では、npm installを実行するだけでビルドする準備が整うということです!

説明下手ですが、楽ですよね? まあこんな感じです。



  • gulpでタスクを定義するgulpfile.jsを作成する

プロジェクトのRootで

$ touch gulpfile.js

これでgulpを使うための準備が整いました

ここまでがプロジェクトにgulpをインストールする手順です。


ポートフォリオに必要なライブラリたちをpackage.jsonに定義しよう

私のポートフォリオサイトのpackage.jsonは以下の用になっています。


package.json

{

"name": "portfolio",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "YOUR_GIT_ADDRESS.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "YOUR_GIT_ADDRESS/issues"
},
"homepage": "YOUR_GIT_ADDRESS#readme",
"devDependencies": {
"browser-sync": "^2.18.13", # 変更を検知したらブラウザをリロードするためのパッケージ(超便利!!)
"coffee-script": "^1.12.7", # このプロジェクトでcoffeeScriptを使えるようにするためのパッケージ
"gulp": "^3.9.1",
"gulp-bower": "0.0.13", # bowerのパッケージをインストールするためのパッケージ
"gulp-bower-task": "^1.0.0",
"gulp-coffee": "^2.3.4", # gulpでcoffeeファイルをjsファイルにコンパイルするためのパッケージ
"gulp-gh-pages": "^0.5.4", # github-pagesにdeployするためのパッケージ
"gulp-imagemin": "^3.4.0", # 画像を圧縮してサイズを小さくするためのパッケージ
"gulp-sass": "^3.1.0" # gulpでsassファイルをcssファイルにコンパイルするためのパッケージ
}
}

今回は、coffeeScriptにも慣れて置きたかったため、gulpfile.jsgulpfile.coffeeにしています。


bowerの使い方

まずbowerコマンドを使えるようにする必要があるため、ターミナルで以下を実行

$ npm install -g bower

これでbowerコマンドを使えるようになりました!

npmで言うところのpackage.jsonに当たる、bower.jsonを作成します

$ bower init

また質問を沢山されますが、基本Enterで大丈夫です。

そうすると、bower.jsonというファイルができます。


bower.json

{

"name": "portfolio",
"description": "",
"main": "index.js",
"authors": [
"USERNAME <YOUR_EMAIL_ADDRESS>"
],
"license": "ISC",
"homepage": "",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

基本的にbowerを使用して、ライブラリをインストールするときは、

$ bower install LIBRARY_NAME --save

で実行することができます。

LIBRARY_NAMEはインストールしたいライブラリの名前です!

では試しに、jQueryをインストールしてみましょう。

$ bower install jquery -save

これを実行するとbower.jsonが以下の用に変わると思います。


bower.json

{

"name": "portfolio",
"description": "",
"main": "index.js",
"authors": [
"USERNAME YOUR_EMAIL_ADDRESS"
],
"license": "ISC",
"homepage": "",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"jquery": "^3.2.1"
}
}

dependenciesjqueryの行が追加されています!

これも先程のpackage.json同様、このファイルに定義されている依存ライブラリは、他の環境では、bower installのみで一括インストールが可能です。楽ですね。

そして、自分のプロジェクトを見てみると、bower_componentsというディレクトリが新しく作成されていると思います。

ここにbower installしたライブラリたちが入っているわけです。

今回skrollr.jsbowerを使ってインストールできるものがあったので、それを実行します。

$ bower install bower-skrollr --save

これでフロント開発で使用するライブラリたちをインストールすることができました。


補足

私のポートフォリオサイトでは、bower_componentsapp/srcディレクトリ配下にインストールさせたかったため、.bowerrcというファイルを作って、そこにbower installされたときにどのファイルを参照して、読み込むべきライブラリを決めるべきか、インストールしたライブラリたちをどこに格納しておくかを明示的に宣言しています。

{

"directory": "app/src/bower_components",
"json": "bower.json"
}


フロント実装!

ついにやってまいりましたね。ここからがやっとフロント開発です。

最初に仕組みを作っておけば、長期的に恩恵を受けることができるので、ここまでは辛いと思わずやりきっちゃいましょう。

今回私は、ポートフォリオサイトを作成するために以下のディレクトリ構成にしました


directory_construction

root/

app/
src/
bower_components/
css/
fonts/
img/
index.html
.bowerrc
bower.json
gulpfile.coffee
package.json

主にここで言うindex.htmlに見た目の実装をしていきます。

ここからフロント実装ですが、スタイルが定義されているファイルやその他は基本的に変わらないので、今回は、skrollr.jsのお作法だけ、共有したいと思います。

先程も言いましたが、skrollr.jsとは、ブラウザのスクロール量をトリガーに様々なスタイルを適応することができるライブラリになってます。


まずskrollr.jsを動かせるようにする

これはすごく簡単です。

<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>portfolio</title>
/* jqueryもここで読み込んでおく */
<script type="text/javascript" src="src/bower_components/jquery/dist/jquery.min.js"></script>
</head>
<body>
/* ここで、skrollr.jsを読み込み、initする */
<script type="text/javascript" src="src/bower_components/bower-skrollr/skrollr.min.js"></script>
<script type="text/javascript">
var s = skrollr.init();
</script>
</body>
</html>

これだけで動きます。

直接index.htmlをブラウザで開きデベロッパーツールのconsoleを確認し、赤文字が何も出ていなかったら成功です!もし出ていたら、読み込み方が違う、ライブラリが正しくインストールされているかを確認してみてください!


パララックス実装をしてみよう!

今回のポートフォリオサイトでは、スクロールの絶対量のみで実装をしました!

ただこのライブラリはとてもたくさんの指定方法があるのでここではそれも紹介したいと思います。

またこれからブラウザのスクロール量というワードが頻出しますが、よくわからないよって方は、ブラウザのコンソールで以下を実行してみてください!


javascript

$(window).scrollTop();


これで現在のスクロール量がとれます。


指定方法その1 Absolute Mode



  • data-[offset]-anchorが基本となる指定方法です。


ここで言う、offsetとは、スクロール量のことです。

anchorは他に指定することができるオプションのようなものです。


例:

# スクロール量が0のときにトリガーになる

data-0 = data-start = data-0-start

# スクロール量が100のときにトリガーになる
data-100 = data-100-start

# スクロール量が-100のときにトリガーになる(特定の要素から-100したときなどのような使い方ができます。)
data--100-start

# スクロール量が画面最下部から0のときトリガーになる(つまり画面の一番下がトリガーになる)
data-end = data-0-end

# スクロール量が画面最下部から100のときトリガーになる
data-100-end


指定方法その2 Relative Mode


  • スクロール量の指定だけでなく、特定の要素をトリガーに使用することができる指定方法です。


  • data-[offset]-(viewport-anchor)-[element-anchor]が基本的な指定方法になります。



offsetは先ほどと同じで、スクロール量を指定する項目です。

viewport-anchorは指定必須項目で、viewportの指定されている表示領域でどこをトリガーにしたいかを指定することができます。

element-anchorは、top center bottomで指定することができます。


# 要素のトップがviewportのトップにあるとき

data-top = data-0-top = data-top-top = data-0-top-top

# 要素のトップがviewportの100px上にあるとき
data-100-top = data-100-top-top

# 要素の一番したがviewportのトップにあるとき(これは見えないです。)
data-top-bottom = data-0-top-bottom

わかりやすい図が公式のREADMEに記載されていたので、拝借します。

anchor-position-guide-1.jpg


指定方法2−2 Relative Modedata-anchor-targetを指定する

ではもう一つのRelative Modeの指定方法について紹介したいと思います。

これは、data-anchor-targetというものに対象の要素を特定できるもの(HTMLだとidとか)を指定し、その要素をトリガーにすることができる指定方法です!

つまり、特定の要素がブラウザ上に見えたら、スタイルを適応するというようなエフェクトを作ることができるようになります。


index.html

<div data-anchor-target="#element" data-bottom-top="スタイルを定義する">

id="element"の要素が現れたときにスタイルを適応することができる
</div>

<div id="element">この要素がトリガーになる。</div>


このような指定方法を組み合わせて、パララックス実装を楽しんでみてください!

私のポートフォリオでは、skrollr.jsが独自に持っているスタイルが適応されていなかったため、意図した動きになりませんでした。なので、もし私と同じ現象になった人がいたら、公式サイトから、git cloneしてプロジェクトをローカルに引っ張ってきてから、exampleの中にある、fixed-positioning.cssを自分のプロジェクトに持ってきて、htmlファイルにlinkしてみてください!意図した動きになると思います!

今回私のポートフォリオサイトでは、特定の要素が見えてからスタイルを適応するなどの複雑なことはしなかったため、Absolute Modeのみで実装しています。

私のindex.htmlはこんな感じです。


index.html

<!DOCTYPE html>

<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Portfolio</title>
<link rel="stylesheet" href="src/css/style.css">
<link rel="stylesheet" href="src/css/fixed-positioning.css">
<script type="text/javascript" src="src/bower_components/jquery/dist/jquery.min.js"></script>
</head>
<body>
<div id="content1" data-0="top:0%;opacity:1;" data-1000="top:100%;opacity:0.3;" ></div>
<div id="content2" data-3000="opacity:1;" data-3500="opacity:1;" data-4000="opacity: 0;"></div>
<div id="content3" data-7300="top:0%;left:0%;" data-9000="top:0%;left: 100%;"></div>

<div class="introduction-title" data-0="left: 50%;opacity: 1;" data-1000="left: -110%;">
<h1>Portfolio</h1>
<h3>When I noticed my signpost was there</h3>
</div>

<div class="self-introduction" data-1200="opacity: 0; left: 10%;" data-1700="opacity: 1; left: 17%;" data-3000="opacity: 1; left: 17%;" data-3500="opacity: 0; left: 23%;">
<div class="self-image"></div>
<div class="self-description" data-1500="opacity: 0;" data-2000="opacity: 1;" data-2500="opacity: 0;">
<h3>プロフィール</h3>
</div>
</div>

<div class="skills" data-4100="opacity: 0;" data-4500="opacity: 1;" data-7000="opacity: 1;" data-7200="opacity: 0;">
<h2>Skill Sets</h2>
<div class="skill">
<div class="skill-bar" id="progress" data-4500="width:0%;background:rgb(212, 212, 212);" data-6700="width:45%;background:rgb(212, 212, 212);"></div>
<img class="skill-image" src="src/img/logo-html.png" width="10%">
</div>
<div class="skill">
<div class="skill-bar" id="progress" data-4500="width:0%;background:rgb(212, 212, 212);" data-6700="width:45%;background:rgb(212, 212, 212);"></div>
<img class="skill-image logo-css" src="src/img/logo-css3.png" width="10%">
</div>
<div class="skill">
<div class="skill-bar" id="progress" data-4500="width:0%;background:rgb(212, 212, 212);" data-6700="width:30%;background:rgb(212, 212, 212);"></div>
<img class="skill-image" src="src/img/logo-js.png" width="10%">
</div>
<div class="skill">
<div class="skill-bar" id="progress" data-4500="width:0%;background:rgb(212, 212, 212);" data-6700="width:62%;background:rgb(212, 212, 212);"></div>
<img class="skill-image" src="src/img/logo-ruby.png" width="10%">
</div>
<div class="skill">
<div class="skill-bar" id="progress" data-4500="width:0%;background:rgb(212, 212, 212);" data-6700="width:68%;background:rgb(212, 212, 212);"></div>
<img class="skill-image" src="src/img/logo-rails.png" width="10%">
</div>
</div>

<div id="intern_div" data-9000="opacity: 1;" data10500="opacity: 0;">
<h2>Intern Experiences</h2>
</div>

<div id="takes_photos" data10500="opacity: 0;bottom: -80%;" data11000="opacity: 1;bottom: -80%;" data12000="opacity: 1; bottom: 30%;">
<h2>Photos</h2>
<div class="photos">
<div class="photo">
<img src="src/img/content01.JPG" width="100%" height="">
</div>
</div>
</div>

<footer data12000="opacity: 0;" data-12500="opacity: 1;">
<p>2017 © Taiga Ishii</p>
</footer>

<script type="text/javascript" src="src/bower_components/bower-skrollr/skrollr.min.js"></script>
<script type="text/javascript">
var s = skrollr.init();
</script>
</body>
</html>



gulpfile.jsでビルド時に呼ばれるタスクを作ってみよう!

ポートフォリオサイトのための要素が揃ったので、最後に、gulpの力を存分に使いましょう!

先程作成したgulpfile.jsに記述していきたいと思います!(今回は、coffee-scriptをインストールしているのでファイル名をgulpfile.coffeeに変え、記述方法をcoffeeScriptにしてお話したいと思います。)

gulpfile.coffeeの基本的な記述方法は以下です。


gulpfile.coffee

# 必要なライブラリを読み込んで変数に格納

gulp = require 'gulp'
coffee = require 'coffee'

# タスク作成

gulp.task 'タスク名', ['使うライブラリ'], ->
gulp.src プロジェクトのどこにあるファイルが対象なのかを定義する
.pipe(使用するライブラリのメソッド(それらの引数))
.pipe gulp.dest(コンパイルしたものをプロジェクトのどこに格納するかを指定する)
return

# タスクを呼び出すタスクを作成

gulp.task 'default', '呼ぶタスク名', ->
return


ここでやりたいこととしては、

1. 必要なライブラリの呼び出し

2. タスクの作成

3. タスクの呼び出し

この3つです。

では実際にsassファイルをコンパイルしてブラウザシンクをするタスクを作成してみましょう


gulpfile.coffee

srcDir = './app/src'

gulp = require 'gulp'
sass = require 'gulp-sass'
coffee = require 'gulp-coffee'
browserSync = require('browser-sync').create()
gbowerTask = require 'gulp-bower-task'

# bowerのインストールをビルド時に実行するタスク
gulp.task 'compile-bower', ->
gulp.src './bower.json'
.pipe gbowerTask()
.pipe gulp.dest(srcDir + '/bower_components/')

# sassファイルをcssにコンパイルするためのタスク
gulp.task 'sass', ->
gulp.src srcDir + '/css/*.scss'
.pipe(sass(outputStyle: 'expanded'))
.pipe(gulp.dest(srcDir + '/css/'))
return

# sassファイルに変更があったときにブラウザをリロードするタスク
gulp.task 'sass-watch', ['sass'], ->
watcher = gulp.watch(srcDir + '/css/*.scss', [ 'sass' ])
watcher.on 'change', (event) ->
browserSync.reload()
return

# ブラウザとどのファイルを同期するかを指定するタスク
gulp.task 'browser-sync', ->
browserSync.init server:
baseDir: 'app'
index: 'index.html'
return

# ブラウザをリロードするタスク
gulp.task 'bs-reload', ->
browserSync.reload()
return

# タスクを呼び出すタスク
gulp.task 'default', ['sass-watch', 'browser-sync', 'compile-bower'], ->
gulp.watch 'app/index.html', ['bs-reload'] #ここでファイル検知をしてブラウザをリロードする
return


これを記述したあと、ターミナルで以下を実行すると、

$ gulp

このコマンドによりgulpfile.coffee内のgulp.task 'default'で呼び出されているタスク群を実行してくれます。

defaultで指定しているタスクは、gulpのみで、コンパイルしてくれますが、特定のタスクを実行したいみたいなシチュエーションががあると思います。

そういうときは、


gulpfile.coffee

gulp.task 'compile', 'compile-bower'


という書き方でタスクを呼び出すタスクを実装して、

$ gulp compile

というコマンドでタスクを呼び出すことができます!

コンパイル用、ビルド用、監視用など自分の用途に合わせてタスクをカスタマイズできるのも、gulpのいいところですね!


まとめ

gulp bowerに関しては、導入して本当に開発効率があがり、良さを実感することができました!

プラグインの多さも考えると、これからカスタマイズ次第でもっといい開発環境を構築することができそうだなと感じました!

skrollr.jsは、指定の仕方が簡単で、簡単に実装することができました!ただ、スクロールでカクカクしてしまう現象が目立ったので、

今度はScrollMagicを使用して再実装してみたいと思います!

自分の知らないことが新しくしれてとても充実したポートフォリオ実装でした!やっぱり新しい技術を勉強するのは楽しいですね!

今回だけでなく、定期的にインプットとアウトプットは実践していきたいと思います!

次回は、@Hiroki11x さんです!どんな内容を紹介してくれるのかとても楽しみです!明日まで待ちきれないですね!

よろしくお願いします!


参考資料