すたらSample

【CSS, jQuery】clipで切り出した画像のアニメーション

2011/02/01

下のような4つの部位がある1枚の画像に対して、CSSのclipプロパティを使って
必要な部分を切り出し、その画像をアニメーションさせます。

手順

  1. CSSのみで表示
  2. jQueryのみで表示
  3. 汎用化
  4. アニメーションさせる
  5. アニメーションさせたまま動かす

#img1 {
  position: absolute; /*必須*/
  top: 0;
  left: 0;
  clip: rect(0px, 48px, 32px, 0px);
}

jQueryで画像を生成し、CSSを指定します。
1枚分の高さの32pxだけtopを減算することで、2番の画像を適正な位置に表示することができます。

jQuery(document).ready(function($){
  $('<img>')
    .attr({
      'id':'img2',
      'src':'img.png'
    })
    .css({
      'position':'absolute',
      'top':'-32px',
      'clip':'rect(32px, 48px, 64px, 0px)'
    })
    .appendTo('#area2');
});

アニメーションの準備として、表示画像の指定や座標を変数で自由に設定できるようにし、
その一連の処理を関数にします。

グローバル変数を設定します。

//表示する画像のサイズ
var H = 32; //高さ
var W = 48; //幅
//アニメーションの順番と画像切り出しの指定
var obj_anim = {
  src:'img.png',
  set:[
    {top:0 * H, right:1 * W, bottom:1 * H, left:0 * W},
    {top:1 * H, right:1 * W, bottom:2 * H, left:0 * W},
    {top:2 * H, right:1 * W, bottom:3 * H, left:0 * W},
    {top:3 * H, right:1 * W, bottom:4 * H, left:0 * W}
  ]
};

画像切り出し、生成の汎用関数を作成します

function setAnim(x, y, id, index){
  var set = obj_anim.set[0]; //長いので短縮!

  var img = $('')
    .attr({
      'id':'img'+id,
      'src':obj_anim.src
    })
    .css({
      'position':'absolute',
      'top' : y - set['top']  + 'px',
      'left': x - set['left'] + 'px',
      'clip':'rect('+
        set['top']   +'px,'+ set['right'] +'px,'+
        set['bottom']+'px,'+ set['left']  +'px' +
      ')'
    })
    .appendTo('#area'+id);
}

作成した関数を呼び出します

jQuery(document).ready(function($){
  setAnim(0, 0, 3, 0);
});

上で作成した関数も利用して、アニメーションさせます。

現在のアニメーションの順番を保存するグローバル変数です。

var INDEX4 = 0;

表示する画像を変更して、アニメーションを実現する関数です

function updateAnim4(id){
  INDEX4++;
  if(INDEX4 >= obj_anim.set.length) INDEX4 = 0;

  var set = obj_anim.set[INDEX4]; //長いので短縮!
  $('#img'+id)
    .css({
      'top' : - set['top']  + 'px',
      'left': - set['left'] + 'px',
      'clip':'rect('+
        set['top']   +'px,'+ set['right'] +'px,'+
        set['bottom']+'px,'+ set['left']  +'px' +
      ')'
    });
}

まずは画像を生成・設置し、その後定期的に画像を変更していきます。

jQuery(document).ready(function($){
  setAnim(0, 0, 4, 0); //生成・設置
  setInterval(function(){
    updateAnim4(4); //画像を変更
  }, 1000);
});

親divの枠内で動きまわるようにします。

var INDEX5 = 0; //現在表示している画像の番号
var limit_w; //親の境界 - 画像の幅
var limit_h; //親の境界 - 画像の高さ
var vx = 2; //X方向へ進む距離
var vy = -1; //Y方向へ進む距離

取得したCSSのtop,leftの値から数値のみを取り出す関数を作っておきます

function getInt(text){
  if(text == undefined) return 0;
  var matches = text.match(/(-?[0-9]+)(px)?/);
  if(!matches){
    return 0;
  }else{
    return parseInt(matches[1], 10);
  }
}

表示する位置が変わっても正しくアニメーションされるように関数を書き換えます

function updateAnim5(id){
  //一つ前の画像切り出し情報を記憶
  var PREV = INDEX5;
  if(PREV < 0) var PREV = obj_anim.set.length - 1;
  var prev = obj_anim.set[PREV];

  //現在の画像切り出し情報を記憶
  INDEX5++;
  if(INDEX5 >= obj_anim.set.length) INDEX5 = 0;
  var curr = obj_anim.set[INDEX5]; //長いので短縮!

  //一つ前の画像座標を記憶
  var prev_top  = getInt($('#img'+id).css('top'));
  var prev_left = getInt($('#img'+id).css('left'));

  $('#img'+id)
    .css({
      'top' : prev_top  - curr['top']  + prev['top']  + 'px',
      'left': prev_left - curr['left'] - prev['left'] + 'px',
      'clip':'rect('+
        curr['top']   +'px,'+ curr['right'] +'px,'+
        curr['bottom']+'px,'+ curr['left']  +'px' +
      ')'
    });
}

画像の位置を動かす関数を作ります

function moveImg(id){

  //現在の画像座標を記憶
  var curr_top  = getInt($('#img'+id).css('top'));
  var curr_left = getInt($('#img'+id).css('left'));

  //現在の画像切り出し情報を取得
  var rect = obj_anim.set[INDEX5];

  $('#img'+id)
    .css({
      'top' : curr_top  + vy + 'px',
      'left': curr_left + vx + 'px',
      'clip':'rect('+
        rect['top']   +'px,'+ rect['right'] +'px,'+
        rect['bottom']+'px,'+ rect['left']  +'px' +
      ')'
    });
}

ロード後に親divの領域を取得し、アニメーションと移動を開始します。

jQuery(document).ready(function($){

  limit_w = parseInt($('#area5').width(),10) - W;
  limit_h = parseInt($('#area5').height(),10) - H;

  setAnim(0, 0, 5, 0);
  setInterval(function(){
    updateAnim5(5);
  }, 1000);
  setInterval(function(){
    moveImg(5);
  },50);
});