11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

jQueryで背景画像のサイズを取得する

Last updated at Posted at 2016-01-28

パララックスの実装で背景画像の表示サイズを取得する必要が出てたので調査してみた。

ソースコードは以下で公開してます。
https://github.com/itoufo/jquery.get-background-size.js

CSSで具体的な値が設定されてれば単純なんだけど、auto とかcoverが設定されているとだいぶ面倒。 まずはそれぞれの仕様をまとめてみた。

css設定値 説明
auto 自動的に算出される(初期値)
contain 縦横比は保持して、背景領域に収まる最大サイズになるように背景画像を拡大縮小する
cover 縦横比は保持して、背景領域を完全に覆う最小サイズになるように背景画像を拡大縮小する
長さ 背景画像の幅・高さを指定する
パーセンテージ 背景領域に対する背景画像の幅・高さのパーセンテージを指定する

autoの 場合"元画像サイズ"
coverやcontain, %を指定した場合"背景領域のサイズ"
長さ(px等)を指定した場合その値をそれぞれ参照する必要がある

そんなこんなで 出来上がったのが下記のソース。

jquery.get-background-size.js
(function (factory) {
  if (typeof module === "object" && typeof module.exports === "object") {
    module.exports = factory(require("jquery"), window, document);
  }
  else {
    factory(jQuery, window, document);
  }
}(function ($, window, document, undefined) {
  // CSSの各幅表記に対する正規表現
  var urlRegex = /url\(['"]*(.*?)['"]*\)/g;

  /**
   * コンストラクタ
   * @param element
   * @param optionsArg
   * @constructor
   */
  var GetBackgroundSize = function(element, callback){
    this.$element = $(element);
    this.backgroundSize = this.$element.css('background-size').split(' ');
    this.img = new Image();
    this.callback = callback.bind(element);
  };

  /**
   * サイズ最適化
   * @param origin
   * @param current
   * @param target
   * @returns {number}
   */
  GetBackgroundSize.prototype.size_optimization = function(origin, current, target){
    return target * (current/origin);
  };

  /**
   * 要素幅取得
   * @returns {boolean}
   */
  GetBackgroundSize.prototype.getBackgroundWidth = function() {
    var pxRegex = /px/, percentRegex = /%/;

    if (pxRegex.test(this.backgroundSize[0])) {
      this.width = parseInt(this.backgroundSize[0])
    }
    if (percentRegex.test(this.backgroundSize[0])) {
      this.width = this.$element.width() * (parseInt(this.backgroundSize[0]) / 100);
    }
    return (typeof this.width != 'undefined');
  };

  /**
   * 要素高さ取得
   * @returns {boolean}
   */
  GetBackgroundSize.prototype.getBackgroundHeight = function() {
    var pxRegex = /px/, percentRegex = /%/;

    // 背景高さ取得
    if (pxRegex.test(this.backgroundSize[1])) {
      this.height = parseInt(this.backgroundSize[1]);
    }
    if (percentRegex.test(this.backgroundSize[1])) {
      this.height = this.$element.height() * (parseInt(this.backgroundSize[1]) / 100);
    }
    return (typeof this.height != 'undefined');
  };

  /**
   * 生画像の情報を入手
   */
  GetBackgroundSize.prototype.getNaturalImageProperties = function(){
    var _this = this;
    this.img.onload = function () {

      if (typeof _this.width == 'undefined') {
        if (typeof _this.height != 'undefined') {
          _this.width = _this.size_optimization(this.naturalHeight, _this.height, this.naturalWidth);
        }else{
          _this.width = _this.$element.width();
        }
      }

      if (typeof _this.height == 'undefined') {
        if (typeof _this.width != 'undefined') {
          _this.height = _this.size_optimization(this.naturalWidth, _this.width, this.naturalHeight);
        }else {
          _this.height = _this.$element.height();
        }
      }

      if(_this.backgroundSize[0] == "cover") {
        /* 縦横比比較 */
        if(_this.$element.width()/_this.$element.height() > _this.width/_this.height){
          _this.width = _this.$element.width();
          _this.height = _this.size_optimization(this.naturalWidth, _this.width, this.naturalHeight);
        }else{
          _this.height = _this.$element.height();
          _this.width = _this.size_optimization(this.naturalHeight, _this.height, this.naturalWidth);
        }
      }
      _this.callback({width: _this.width, height: _this.height});
    };

    /* Call img.onload to refer natural size. */
    this.img.src = this.$element.css('background-image').replace(urlRegex, '$1');
  };

  /**
   * 初期化処理
   * @returns {{width: *, height: *}}
   */
  GetBackgroundSize.prototype.init = function(){

    // 高さおよび幅が両方与えられていたらそのままReturn
    var rst = [this.getBackgroundHeight(), this.getBackgroundWidth()];

    if(rst[0] && rst[1]) {
      this.callback({width: this.width, height: this.height});
      return;
    }
    return this.getNaturalImageProperties();
  };

  $.fn.getBackgroundSize = function (callback){
    return this.each(function(){
      new GetBackgroundSize(this, callback).init();
    });
  }
}));

呼び出し側
$(function(){
  $('#sample-auto-cover').getBackgroundSize(function(arg){
    // arg.width と arg.heightに背景サイズが入ってくる
    $(this).before('<table class="table">' +
      '<tr><th>width</th><th>height</th></tr>' +
      '<tr><td>' + arg.width + '</td><td>'+ arg.height + '</td></tr>' +
      '</table>'
    );
});
11
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?