CSSスプライトで背景画像を指定したブロックを擬似的に拡大縮小可能にするjQueryプラグイン

CSSスプライトは、画像リソースとコードのメンテナンスの手間が大幅に軽減できます。
しかし、例えばmax-widthなどを指定して、ビューポートの拡大縮小と一緒に拡大縮小しようとすると、ボックスは拡大縮小できても背景画像がそれにともないません。

CSSで上書きしようにも、CSSにはそういう定義はなく、実現することはできません。

そこで、jQueryを使ってそれを擬似的にできるようにしてみました。
背景画像として定義されている画像を、IMG要素として配置し、top と left で表示したい部分を表示。
ウィンドウのリサイズに従って、ボックスのwidthと height、top と left、画像のtopとleft、max-widthを再計算します。

追記:インライン要素の場合の不具合を修正しました。(2013.7.11)

(function($){
$.fn.swapSpriteImage = function(option) {
 var o = $.extend({
  'decimal' : 'ceil'
 }, o);
 this.each(function(){
  var e = $(this).css({
    'display'  : 'block',
    'overflow' : 'hidden',
   })
   , p = $(e.parent().get(0))
   , src = e.css('background-image').replace(/url\x28(?:[\x22\x27])?(.*?)(?:[\x22\x27])?\x29$/,'$1')
   , x = $.browser.msie ? e.css('background-position-x') : e.css('background-position').split(' ')[0]
   , y = $.browser.msie ? e.css('background-position-y') : e.css('background-position').split(' ')[1]
   , w = parseFloat( e.width() )
   , h = parseFloat( e.height() )
   , r = parseFloat(w) / parseFloat(h)
   , img = $("<img src="+src+" />").css( {
      'display'	 : 'block',
      'position' : 'relative',
      'top'		 : y,
      'left'	 : x
     } )
   , pw = parseFloat(p.width())
  ;
  if (!src) return e;
  
  if (o['max-width']) { pw = o['max-width'] }
  else {
   e.parents().each(function(){
    mw = $(this).css('max-width');
    if ( mw !== 'none' &amp;&amp; mw !== undefined) {
     pw = parseFloat( mw );
     return false;
    }
   })
  }
  ;
  e.css({
   'background'	 : 'none',
   'max-width'	 : ( ( w / pw ) * 100 ) + '%',
   'text-indent' : 0,
   'white-spzce' : 'wrap'
  }).html(img);
  img.bind('load', function(){ console.log([img.width(),w]);
   img.css({
    'width': Math[o['decimal']]( parseFloat(img.width()) / w * 100 ) + '%'
   });
   $(window).resize(function(){
    var yi = parseFloat(y)
     , xi = parseFloat(x)
     , pow = parseFloat( e.width() / w )
    ;
    img.css({
     'top'	 : yi * pow,
     'left'	 : xi * pow
    });
    e.css({ 'height' : Math[o['decimal']](h * pow) })
   });
   $(window).trigger('resize');
  });
 });
 return this;
}
})(jQuery)

使い方は、

$("#sprite-box").swapSpriteImage()

対象の要素のDOM上の上位どこかに max-width を指定したコンテナを作っておくか、オプション(下記参照)でmax-widthの値を指定してください。

オプション

$("#sprite-box").swapSpriteImage({
 "max-width" : 640px,
  // ≒ ビューポートの幅。初期値:親要素に max-width を指定した要素がある場合、その値。ない場合は親要素の表示幅。
 "decimal" : "ceil"
  // 小数点以下の処理方法。Mathのメソッド。初期値:ceil
})

Leave a Reply