带滑动背景的滑块

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 $200 免费信用额度!

iOS 版 Yahoo! 天气应用 的众多超级棒的设计功能中,城市屏幕之间的过渡是其中之一。 背景图像不仅会在屏幕从一个屏幕移动到另一个屏幕时移动,背景图像本身也会滑动。 它似乎隐藏了一些“旧”屏幕并揭示了“新”屏幕,这些屏幕越靠近完整视图就越明显。

让我们尝试在网络上实现它。

HTML 代码

像任何滑块一样,有三个主要组件

  • 包含所有内容的容器
  • 一个滑动容器,其宽度与所有幻灯片并排的宽度相同
  • 每个单独的侧边容器

我们不会过多地关注幻灯片内的内容。 我只会添加温度以显示每个幻灯片确实可以在顶部容纳内容。

<div class="slider" id="slider">
  <div class="holder">
    <div class="slide" id="slide-0"><span class="temp">74°</span></div>
    <div class="slide" id="slide-1"><span class="temp">64°</span></div>
    <div class="slide" id="slide-2"><span class="temp">82°</span></div>
  </div>
</div>

容器可能是一个 <section>,幻灯片可能是一个 <article>。 这真的取决于情况。 我会让你根据自己的需求做出语义选择。

布局方案如下

CSS 代码

“滑块”(视觉容器)和幻灯片需要具有明确相同的尺寸。 我们将在此处使用像素,但您可以使用任何方法来实现它。

.slider {
  width: 300px;
  height: 500px;
  overflow-x: scroll;
}
.slide {
  float: left;
  width: 300px;
  height: 500px;
}

将这些幻灯片浮动到左侧不会使它们排列成一行,因为幻灯片的父元素宽度不足以让它们这样做。 这就是我们需要占位符元素的原因之一。 它将是 300% 宽(幻灯片数量 × 100%),这将完全适合三个幻灯片。

.holder {
  width: 300%;
}

我们的每个幻灯片都有一个唯一的 ID。 这样做很有用,因为如果我们选择,我们可以创建链接到这些 ID 的锚链接,并且滑块将“跳转”到这些幻灯片。 我们将添加 JavaScript 来执行一些实际的“滑动”,但即使没有它,我们的滑块也能正常工作。 ID 使此成为可能,因此让我们在此处使用它们来插入一些漂亮的背景图像。

#slide-0 {
  background-image: url(http://farm8.staticflickr.com/7347/8731666710_34d07e709e_z.jpg);
}
#slide-1 {
  background-image: url(http://farm8.staticflickr.com/7384/8730654121_05bca33388_z.jpg);
}
#slide-2 {
  background-image: url(http://farm8.staticflickr.com/7382/8732044638_9337082fc6_z.jpg);
}

有了所有这些,我们的布局就会成形

CSS 代码(黑色渐变)

作为一个细节,根据背后的照片,以白色设置的温度可能会看不清。 为了确保它可见,我们可以使照片在底部逐渐淡化为黑色。 伪元素会很好地完成这项工作。

.slide:before {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 40%;
  background: linear-gradient(transparent, black);
}

此处需要图片说明

JavaScript 代码(背景滑动)

我们将在此处使用 jQuery,因为我们热爱生活。 我们的目标是根据滚动调整幻灯片的背景位置。 我们可以在 CSS 中以百分比形式设置背景位置,但这本身并不能实现我们想要的酷炫隐藏/显示更多效果。 根据滚动的量(我们可以在 JavaScript 中测量),我们将调整背景位置。 单独来说,这看起来像这样

$("#slider").on("scroll", function() {
  $(".slides").css({
    "background-position": $(this).scrollLeft()/6-100+ "px 0"
  });  
});

其中的“6”和“-100”是魔法数字。 不是 容易出现脆弱性的 CSS 魔法数字,而是传统的魔法数字。 只是一些恰好使效果起作用的数字。 或许很糟糕,但这并不是什么大不了的事情。 设计方面的事情有时就是这样。 也许最好在代码中添加一个注释来解释这一点。 这些特定的数字基于我使用的图像及其大小以及看起来不错的内容。

此处的效果是我们想要的背景移动

请注意,当幻灯片几乎消失时,黄色有轨电车的可见度降低了。

JavaScript 代码(赋予结构)

这段小小的 JavaScript 代码看起来很孤独,因为它没有背后的结构。 滑块是查看结构化 JavaScript 的简单方法的一个很好的借口。

我们可以将所有与滑块相关的内容都设为一个对象。

var slider = {

};

然后,我们将相关元素组合到一个区域中,将我们的事件绑定在一起,并编写执行非常特定任务的小函数。

var slider = {
  
  el: {
    slider: $("#slider"),
    allSlides: $(".slide")
  },
 
  init: function() {
    // manual scrolling
    this.el.slider.on("scroll", function(event) {
      slider.moveSlidePosition(event);
    });
  },
  
  moveSlidePosition: function(event) {
    // Magic Numbers
    this.el.allSlides.css({
      "background-position": $(event.target).scrollLeft()/6-100+ "px 0"
    });  
  }
  
};

slider.init();

HTML 代码(添加导航)

添加滑动功能会非常(非常)酷(提示)。 但现在,让我们添加一些可点击的链接来更改幻灯片,而不是依赖滚动条。 在现实生活中,您甚至可以删除滚动条(直接对容器使用 overflow: hidden;)。 我们需要的是链接到各个幻灯片 ID 的锚链接。

<nav class="slider-nav">
  <a href="#slide-0" class="active">Slide 0</a> 
  <a href="#slide-1">Slide 1</a> 
  <a href="#slide-2">Slide 2</a> 
</nav>

随意设置样式。 对于 演示,我将它们设置为带隐藏文本的小灰色圆圈。

JavaScript 代码(添加导航)

我们的结构现在更有用。 我们只需添加我们正在处理的其他几个元素,添加一个我们正在监听的新事件(单击导航),并编写一个处理该事件的小函数。

我们知道从链接本身的 ID 可以知道单击导航链接时滚动位置的动画移动距离。 该链接可能是 href=”#slide-1″,我们可以轻松地从中获取“1”。 然后我们需要滚动到的位置是(1 × 幻灯片宽度),在本例中为 300。 我们将在 JavaScript 中存储该 300 值。

var slider = {
  
  el: {
    slider: $("#slider"),
    allSlides: $(".slide"),
    sliderNav: $(".slider-nav"),
    allNavButtons: $(".slider-nav > a")
  },
  
  timing: 800,
  slideWidth: 300, // could measure this
  
  init: function() {
    // You can either manually scroll...
    this.el.slider.on("scroll", function(event) {
      slider.moveSlidePosition(event);
    });
    // ... or click a thing
    this.el.sliderNav.on("click", "a", function(event) {
      slider.handleNavClick(event, this);
    });
  },
  
  moveSlidePosition: function(event) {
    // Magic Numbers
    this.el.allSlides.css({
      "background-position": $(event.target).scrollLeft()/6-100+ "px 0"
    });  
  },
  
  handleNavClick: function(event, el) {
    // Don't change URL to a hash, remove if you want that
    event.preventDefault();

    // Get "1" from "#slide-1", for example
    var position = $(el).attr("href").split("-").pop();
    
    this.el.slider.animate({
      scrollLeft: position * this.slideWidth
    }, this.timing);
    
    this.changeActiveNav(el);
  },
  
  changeActiveNav: function(el) {
    // Remove active from all links
    this.el.allNavButtons.removeClass("active");
    // Add back to the one that was pressed
    $(el).addClass("active");
  }
  
};

slider.init();

我们在导航链接上有一个“active”类,仅用于在 CSS 中用于视觉上指示哪个幻灯片处于活动状态。 我们通过从所有链接中删除“active”,然后将其添加到被单击的链接中来处理它。

演示!

Check out this Pen!