How to set an exact background position based on element's position?

时间:2017-06-15 09:52:21

标签: javascript jquery html css css3

What I am trying to achieve: using the same image, set an elements background-position with jQuery, so they overlaps closest parents background-image. I somehow figured, that $element.property().left needs to be multiplied by something close to 2 (still don't really understand why it's so), but I cannot see any math pattern in it.

If anybody could tell me what exactly comes into an equation, it'd be great help. I imagine there is padding and margin of an element and all the elements up the DOM tree involved, but after lot of combinations I still cannot get there.

It might seem that the best way to get desired effect is just to set background: transparent;, but it is not the case; I need it for further usage of filter CSS property on the element's background image.

There are inline styles in HTML added for testing; also, I created jsfiddle.

$.fn.filteredImg= function() {
    
    var $this = $(this)

    $this.each(function(index, card) {
        var $card   = $(card);
        var img     = $card.data("img");
        var $parent = $card.parentsUntil("[data-img='" + img + "']").last().parent();
        var $effect = $card.children(".filtered-effect");
        var pos     = $card.position();
        $parent.css({ 
            backgroundImage: "url(" + img + ")",
            backgroundRepeat: "no-repeat"
        });
        $effect.css({
            backgroundImage: "url(" + img + ")",
            backgroundPosition: -2 * Math.ceil(pos.left) + "px " + -Math.round(pos.top) + "px"
        });
    })
    

}   

$(".card-filtered-img").filteredImg();
.card-filtered-img {
  width: 80%;
  min-height: 500px;
  margin-left: 77px;
  margin-top: 17px;
  position: relative; 
}
  .card-filtered-img > * {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0; 
  }
  .card-filtered-img .filtered-effect {
    z-index: 99; 
  }
  .card-filtered-img .card-content {
    background: rgba(34, 34, 34, 0.35);
    z-index: 100; 
  }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-img="http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg">
<div class="container" style="margin-top:30px">
      <div class="row" style="padding:30px">
          <div class="col">
              <div class="card-filtered-img" data-img="http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg">
                  <div class="filtered-effect"></div>
                  <div class="card-content"></div>
              </div>

              <div class="card-filtered-img" data-img="http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg">
                  <div class="filtered-effect"></div>
                  <div class="card-content"></div>
              </div>
          </div>
      </div>
  </div>

2 个答案:

答案 0 :(得分:1)

Here is the solution base on offset instead of position (and I simplified the code):

$.fn.filteredImg= function() {
    
    var $this = $(this);

    $this.each(function(index, card) {
        var $card   = $(card);
        var $effect = $card.children(".filtered-effect");
        var $parent = $(card).parents(".parent").first();
        var img     = $parent.data("img");
        var cardPos = $card.offset();
        $parent.css({ 
            backgroundImage: "url(" + img + ")",
            backgroundRepeat: "no-repeat"
        });
        $effect.css({
            backgroundImage: "url(" + img + ")",
            backgroundPosition: -cardPos.left + "px " + -cardPos.top + "px"
        });
    })
    

}   

$(".card-filtered-img").filteredImg();
.card-filtered-img {
  width: 80%;
  min-height: 500px;
  margin-left: 77px;
  margin-top: 17px;
  position: relative; 
}
  .card-filtered-img > * {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0; 
  }
  .card-filtered-img .filtered-effect {
    z-index: 99; 
  }
  .card-filtered-img .card-content {
    background: rgba(34, 34, 34, 0.35);
    z-index: 100; 
  }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent" data-img="http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg">
  <div class="container">
    <div class="row">
        <div class="col-md-12">
            <div class="card-filtered-img">
              <div class="filtered-effect"></div>
              <div class="card-content"></div>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <div class="card-filtered-img">
              <div class="filtered-effect"></div>
              <div class="card-content"></div>
            </div>
        </div>
    </div>
</div>

答案 1 :(得分:0)

从/如果您使用完整视口,您可以使用视口单元来定位和调整内部的大小并将所有脚本放在一起。

当您调整大小时,这也可以扩展,并且可以提升性能,因为您不需要脚本来监视调整大小和重绘。

注意,对于此演示,我在没有bootstrap的情况下运行此操作,因为我不想为其媒体查询等添加补偿。

Updated fiddle

html, body {
  margin: 0;
  overflow-x: hidden;
}
.outer {
  height: 1080px;
  width: 100vw;
}
.card-acrylic {
  top: 20px;
  width: 80vw;
  margin-left: 10vw;
  min-height: 500px;
  position: relative;
  background-position: left -10vw top -20px;
}
.card-acrylic + .card-acrylic {
  top: 40px;
  background-position: left -10vw top -540px;
}

.card-acrylic > * {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.card-acrylic .acrylic-effect {
  z-index: 99;
}

.card-acrylic .card-content {
  background: rgba(34, 34, 34, 0.35);
  z-index: 100;
}
<div class="outer" style="background-image: url(http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg)">

  <div class="card-acrylic" style="background-image: url(http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg)">
    <div class="acrylic-effect"></div>
    <div class="card-content"></div>
  </div>

  <div class="card-acrylic" style="background-image: url(http://www.planwallpaper.com/static/images/colorful-wallpaper2.jpg)">
    <div class="acrylic-effect"></div>
    <div class="card-content"></div>
  </div>
</div>