本文へジャンプ

Chrome専用コンテンツ「THE COLOR RUN」特設サイトの制作裏側

Posted by MONSTER DIVE

先日、社内イベントの一環として「THE COLOR RUN」とゆうイベントに参加させてもらい、そのレポートを兼ねたスペシャルコンテンツを公開しました。PCのChromeでのみ閲覧できる、という限定的な特設サイトです。詳しくはこちら

こちらのサイト、大分JavaScriptでゴリゴリ書いております。
見てお分かりかと思うのですが、派手です。
このサイトのメインは、やっぱりサイト全体の色が変わること。
では実際にどのように作っているのか、解説していきましょう。

サイト全体の色が変わる

このコンテンツは、色々な所でサイト全体の色が変わります。

  • サムネイルクリックした時
  • 拡大画像のnext / back時
  • Youtubeの再生中

それらをどのように設計したのかを、プログラムベースでざっくりではありますが、書いていきます。

まずサムネイルのクリック時だろうが、拡大画像のnext / backだろうが、Youtubeの再生中だろうが、全部一つの処理(関数)にまとめたいと思いました。
今回は各ページをシーン管理にしています。

ざっくりですが、

  • LoadingScene(ローディング時)
  • ContentsScene(Google Maps & サムネイル一覧)
  • PreviewScene(拡大画像)
  • VideoScene(Youtube)

とゆうシーンのクラスを作成しました。
上記の各シーンにはBaseSceneとゆう親クラスに、共通処理やPrototypeを継承させて、publicな関数を持たせています。(AS3で言うとこのInterfaceをimplementsしてる感じ)
それらシーンを管理させるMainとゆうクラスがあり、今回はそこでサイト全体の色を変更させることをコントロールさせることにしました。

まずMainクラスですが、こいつをシングルトン扱いさせます。
こんな感じで。

Main.coffee

    class @Main
        instance = null
        @getInstance: ->
            if not @instance?
                instance = new @
            instance

こうすることよって、どのクラスからでもMainにアクセスが可能になります。
なので後は、

Main.coffee

        class @Main
            instance = null
            _currentScene = null
            _header = null
            _footer = null
            @getInstance: ->
                if not @instance?
                    instance = new @
                instance
            constructor: ->
                _header = new Header()
                _footer = new Footer()
                return
            ###
            * ヘッダー、フッダー、今現在のシーンの色を変更させる
            * @param colorStr {String} RGBの文字列
            * @return
            ###
            changeColor: (colorStr) =>
                _header.changeColor(colorStr)
                _footer.changeColor(colorStr)
                _currentScene.changeColor(colorStr)
                return

と、prototypeを継承させたmethodを用意すれば、どこのクラスからもこれらが実行が可能になります。

例えば、サムネイルがクリックされた時に拡大画像(PreviewScene)が大きい画像の色情報を解析して、その色をこのMainクラスのchangeColor関数を実行させれば、サイト全体の色が変わります。

PreviewScene.coffee

    class @PreviewScene extends BaseScene
        _this = null
        _image = null
        _bg = null
        _colorRGBStr = ''
        constructor: () ->
            super()
            _this = @
            return
        init: =>
            _bg = document.getElementById 'bg
            loadingLargeImage()
            _this
        #private
        loadingLargeImage = ->
            _image = new Image()
            _image.src = 'hoge.jpg'
            _image.onload = onImageLoadingCompleted()
            return
        onImageLoadingCompleted = ->
            #ここはホントは画像から解析したRGB
            _colorRGBStr = '#ff00ff'

            #ここ重要!ここでMainを叩く
            Main.getInstance.changeColor _colorRGBStr
            return
        # prototypeを継承させておく。親のMainからたたく
        changeColor: (rgbStr) =>
            # _bgに対してCSSのbackground-colorが適用される
            _bg.style.backgroundColor = rgbStr
            return

と、各シーンにprototypeを継承させたpublic関数(changeColor)を設置しておき、それぞれ必要なタイミングで、

    Main.getInstance().changeColor('#000');

と実行すれば、header、footer、各々のシーンで、サイト全体の色がどのクラスからでも変えられる仕様になっています。

おまけ

今回の「THE COLOR RUN」スペシャルコンテンツですが、社内イベントの企画モノとゆうのもあり、自分の好きなことをやらせてもらいました。

  • require.jsへの挑戦
  • underscore.jsの使用 & mixinを自作
  • canvasを使用する
  • workerを使ってみる
  • 映像との連携

これらに挑戦してみましたが、中でもworkerを使ってみるの箇所で、少し面白い使い方をしました。

workerの話をすると、それだけでブログ記事がいくつもできちゃうので割愛しますが、簡単に言うと、メインスレッドじゃないところで処理を実行させる技術です。

最近のWebサイトを見ていると、画像の大量読み込みやvideoの複数読み込みといった処理が多く使用されていますが、今回のサイトでも「サムネイルをクリックした瞬間に拡大画像を読み込む処理」があります。
しかし、その読み込みにはworkerは使用せず、読み込んだ拡大画像をcanvasに描画させ、画像の色情報を解析してRGB値を作成するという処理に、workerを使用してみました。

我ながら面白いチャレンジだったのでは、と思います。
こういった手法を用いれば、少し大きめな画像でも、アニメーション中にそのアニメーションを劣化させること無く、サイト全体に対してその処理を違和感無く動作させることが可能になるはずです。

Recent Entries
MD EVENT REPORT
What's Hot?