みかづきブログ その3

3ヶ月つづけてみました。

複数のスプライト画像を親のdata属性で管理する

複数のスプライト画像を動かす際に、それぞれの要素にクラスを振ったり、data属性を振ることはよくあると思うのですが、JSからのDOMアクセスを減らすべく、

  1. スプライトの親にのみアクセス
  2. 親のdata属性に子の配置をすべて書き込む

という実装方針で実装を試みてみました。

ソース

HTML

<div id="clock" data-time="h00m00s00">
    <div id="hours" class="nums">
        <div id="hours-1" class="num"></div>
        <div id="hours-2" class="num"></div>
    </div>

    <div id="minutes" class="nums">
        <div id="minutes-1" class="num"></div>
        <div id="minutes-2" class="num"></div>
    </div>

    <div id="seconds" class="nums">
        <div id="seconds-1" class="num"></div>
        <div id="seconds-2" class="num"></div>
    </div>
</div>

JavaScript

(function(win, doc) {
    
    "use strict";
    
    var FPS = 1,
        INTERVAL = 1000 / FPS,
        clock = doc.getElementById("clock"),
        now, hh, mm, ss, timeString;
    
    displayNowTime();
    
    function displayNowTime() {
        now = new Date();

        hh  = numberToStringWithDigit(now.getHours(), 2);
        mm  = numberToStringWithDigit(now.getMinutes(), 2);
        ss  = numberToStringWithDigit(now.getSeconds(), 2);
                
        clock.dataset.time = "h" + hh + "m" +  mm + "s" + ss;
        
        setTimeout(displayNowTime, INTERVAL);
    }

    
    function numberToStringWithDigit(num, digit) {
        var ZERO = "0",
            i = 0,
            str, result;
        
        for (; i < digit - 1; i++) {
            str += ZERO;
        }
        
        return (str + num).slice(-digit);
    }
    
})(this, document);

SCSS

@import 'compass/reset';

$height: 61;

.num {
    position: relative;
    width: 45px; height: 610px; 
    background: url(http://jsrun.it/assets/b/m/5/x/bm5xe.png) 0 0 no-repeat;
    overflow: hidden;
}

#clock {
    position: absolute;
    top: 50%; left: 50%;
    margin: -30px 0 0 -135px;
    width: 270px; height: 61px;
    overflow: hidden;
    
    @for $i from 0 through 2 {
        &[data-time*="h#{$i}"] {
            #hours-1 {
                top: $height * $i * -1px;
            }
        }
    }

    @for $i from 0 through 9 {
        &[data-time*="#{$i}m"] {
            #hours-2 {
                top: $height * $i * -1px;
            }
        }
    }

    @for $i from 0 through 9 {
        &[data-time*="m#{$i}"] {
            #minutes-1 {
                top: $height * $i * -1px;
            }
        }
    }
    
    @for $i from 0 through 9 {
        &[data-time*="#{$i}s"] {
            #minutes-2 {
                top: $height * $i * -1px;
            }
        }
    }
    
    @for $i from 0 through 9 {
        &[data-time*="s#{$i}"] {
            #seconds-1 {
                top: $height * $i * -1px;
            }
        }
    }
    
    @for $i from 0 through 9 {
        &[data-time$="#{$i}"] {
            #seconds-2 {
                top: $height * $i * -1px;
            }
        }
    }
}

.nums {
    float: left;
    overflow: hidden;
}

.num {
    float: left;
    overflow: hidden;
}

DEMO


解説

ご覧のとおり時計をつくってみました。

#hours-1、#hours-2、#minutes-1、#minutes-2、#seconds-1、#seconds-2の6個にアクセスするのではなく、#clock の data-time に h00m00s00 という感じで現在時刻を書き込み、CSS側で属性セレクタのマッチをつかってそれぞれの子要素のポジションを決めています。

モダンブラウザでしか動きませんが、なかなか良いコードになったのではないかと思ってます。
今回は以上です。