2018年5月8日

デザイン

画像に簡単にアニメーションをつけるcurtain.js

目次

  1. はじめに
  2. curtain.jsとは
  3. デモ
  4. 使い方
  5. まとめ

はじめに

本記事では、画像に簡単にアニメーションをつけることができるcurtain.jsをご紹介します。

普通の画像がまるでカーテンのようにふりふりと風になびくアニメーションをつけたり、画像を水面に見立て、ブヨブヨとマウスカーソルに合わせて動いたり…。curtain.jsを使うと簡単に画像に対して様々な目新しいアニメーションをつけることができます。

curtain.jsとは

curtain.jsは小さいvanilla WebGL JavaScriptのライブラリです。3Dのインタラクションやアニメーションを作ることができます。

HTMLの画像を含んだ要素を3DのWebGLテクスチャーplaneに変換し、shadersを使い、アニメーションを加えることができるようにしています。それぞれのplaneの大きさやpositionはCSSで変更することができるので、楽に配置変更サイズ変更をすることができます。

curtain.jsのGithubリポジトリ

Github上にコードが公開されています。

martinlaxenaire/curtainsjs

デモ

curtain.jsでできることは下記デモで見ることができます。

アニメーションをつけることはもちろん、インタラクティブなデモもあるので、ぜひチェックしてみてください。

デモ1
デモ2
デモ3
デモ4
デモ5
デモ5

使い方

まずは、HTMLを設定していきます。

HTML

canvasを入れるdivと画像を入れるdivの2つのdivを作ります。

<body>

    <!-- div that will hold our WebGL canvas -->
    <div id="canvas"></div>

    <!-- div used to create our plane -->
    <div class="plane">

        <!-- image that will be used as texture by our plane -->
        <img src="path/to/my-image.jpg" />
    </div>

</body>

CSS

canvasを内包するdivをドキュメント内に入るように調整し、planeを内包するdivに好きなサイズを設定します。

body {
    /* make the body fit our viewport */
    position: relative;
    width: 100%;
    height: 100vh;
    margin: 0;
    overflow: hidden;
}

#canvas {
    /* make the canvas wrapper fits the document */
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}

.plane {
    /* define the size of your plane */
    width: 80%;
    height: 80vh;
    margin: 10vh auto;
}

.plane img {
    /* hide the img element */
    display: none;
}

JavaScript

WebGLコンテキストをインスタンスとして作り出し、planeを作成し基本的なパラメーターなどを設定します。

window.onload = function() {
    // get our canvas wrapper
    var canvasContainer = document.getElementById("canvas");

    // set up our WebGL context and append the canvas to our wrapper
    var webGLCurtain = new Curtains("canvas");

    // get our plane element
    var planeElement = document.getElementsByClassName("plane")[0];

    // set our initial parameters (basic uniforms)
    var params = {
        vertexShaderID: "plane-vs", // our vertex shader ID
        fragmentShaderID: "plane-fs", // our framgent shader ID
        uniforms: {
            time: {
                name: "uTime", // uniform name that will be passed to our shaders
                type: "1f", // this means our uniform is a float
                value: 0,
            },
        }
    }

    // create our plane mesh
    var plane = webGLCurtain.addPlane(planeElement, params);

    // use the onRender method of our plane fired at each requestAnimationFrame call
    plane.onRender(function() {
        plane.uniforms.time.value++; // update our time uniform value
    });

}

Shaders

bodyタグの中、ライブラリをインクードする直前に下記コードを入れます。
こちらは基本的な頂点シェーダとフラグメントシェーダを設定しています。
Shaderについてあまり詳しくない方は、こちらを参考にするとよいでしょう。

The Book of Shaders(日本語訳)

<!-- vertex shader -->
<script id="plane-vs" type="x-shader/x-vertex">
    #ifdef GL_ES
    precision mediump float;
    #endif

    // those are the mandatory attributes that the lib sets
    attribute vec3 aVertexPosition;
    attribute vec2 aTextureCoord;

    // those are mandatory uniforms that the lib sets and that contain our model view and projection matrix
    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;

    // if you want to pass your vertex and texture coords to the fragment shader
    varying vec3 vVertexPosition;
    varying vec2 vTextureCoord;

    void main() {
        vec3 vertexPosition = aVertexPosition;
        gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);

        // set the varyings
        vTextureCoord = aTextureCoord;
        vVertexPosition = vertexPosition;
    }
</script>

<!-- fragment shader -->
<script id="plane-fs" type="x-shader/x-fragment">
    #ifdef GL_ES
    precision mediump float;
    #endif

    // get our varyings
    varying vec3 vVertexPosition;
    varying vec2 vTextureCoord;

    // the uniform we declared inside our javascript
    uniform float uTime;

    // our texture sampler (default name, to use a different name please refer to the documentation)
    uniform sampler2D uSampler0;

    void main() {
        vec2 textureCoord = vec2(vTextureCoord.x, vTextureCoord.y);

        // displace our pixels along the X axis based on our time uniform
        // textures coords are ranging from 0.0 to 1.0 on both axis
        textureCoord.x += sin(textureCoord.y * 25.0) * cos(textureCoord.x * 25.0) * (cos(uTime / 50.0)) / 25.0;

        gl_FragColor = texture2D(uSampler0, textureCoord);
    }
</script>

以上の設定をしていただく、基本のセットアップが完了です。
このようなものが出来上がるはずです。

基本設定の完成図

パフォーマンスに関して

  • 頂点シェーダの数はパフォーマンスに大きな影響を及ぼすので、1つ以上のplaneを使用する場合は、なるべく頂点の数を減らすと良いです。
  • 画像もなるべくplaneのサイズに合わせて書き出してください
  • ユニフォームの数はなるべく抑える
  • 複数のplaneに複数のテクスチャーを設定する場合は、planeの大きさをCSSの画像の縦横比率に合わせて作ってください。

ドキュメンテーション

curtain.jsのさらなる詳しいドキュメンテーションはこちらをご覧ください。

まとめ

以上、今回は画像に簡単にアニメーションをつけるcurtain.jsをご紹介しました。

簡単に実装自体はできますが、一度も3D WebGLやshadersを使ったことがない方には少しハードルが高いので、こちらの記事を参考にしながら実装してみてください。

The Book of Shaders(日本語訳)
WebGLでGLSL (Shader) を書く流れを(ざっくり)まとめた
WebGL Fundamentals (英語)

0

0

AUTHOR

sasakki デザイナー

アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。

アプリでもっと便利に!気になる記事をチェック!

記事のお気に入り登録やランキングが表示される昨日に対応!毎日の情報収集や調べ物にもっと身近なメディアになりました。

palanでは一緒に働く仲間を募集しています

正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。

話を聞いてみたい

運営メンバー

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にeishis, Inc.を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

sasakki デザイナー

アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。

しまだ

しまだ デザイナー

WebAR/VRのデザインと3DCG制作がメインです。 肩書きは「アニメ案件に関わりたいデザイナー」。

Miu マーケター

ドイツでWEBマーケティングしています。

しんのき エンジニア

主に React Native を使ったアプリ開発と AWS や Firebase を使ったサーバーレスアーキテクチャを担当しています。元々はインフラとかPHPをやっていました。

yamakawa

やまかわたかし デザイナー

フロントエンドデザイナー。デザインからHTML / CSS、JSの実装を担当しています。最近はReact NativeやReact360をよく触っています。

furuya エンジニア

サーバーサイド、フロントエンド、Unityと色々手を出してる雑食系エンジニア。ReactNativeが最近のマイブーム。

Sayaka Osanai デザイナー

Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。

はらた

はらた エンジニア

サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

うえまつゆい エンジニア

サーバーサイドエンジニアからフロントエンドエンジニアになりました。主にReact Nativeでのアプリ開発をしています。

kobori

こぼり ともろう エンジニア

サーバーサイドエンジニア。SIerを経て2019年7月に入社。日々学習しながらRuby on Railsを使った開発を行っています。

sasai

ささい エンジニア

フロントエンドエンジニア WebGLとReactが強みと言えるように頑張ってます。

damien

Damien

WebAR/VRを中心に企画やディレクションやエンジニアもちょっとやっています。森に住んでいます。

デザイナーゲスト

ゲスト デザイナー

CONTACT PAGE TOP