天天看點

執行個體:用CSS和JS建立“前後”圖像對比效果

執行個體:用CSS和JS建立“前後”圖像對比效果

使用 html range input建立前後圖像比較效果的分步教程。使用 CSS 和 JavaScript,JS 部分代碼非常少,主要是 HTML、CSS,和實作思路。

介紹

如果你有兩張圖像進行比較,則“前後”圖像滑塊是一個有效而又簡單的 UI 元素。

執行個體:用CSS和JS建立“前後”圖像對比效果

該“slider”元素使你的使用者可以控制兩個圖像在螢幕上的顯示方式,并自由浏覽兩個不同的圖像。你可能認為它需要一些庫來建立這樣的效果,但實際上,它是一個非常直接和容易編碼的 UI。有了 CSS 和 JS 的基礎知識,每個人都可以建立它。

在本教程中,我将詳細解釋這個 UI 背後的概念,如何實作它,以及進一步增強的建議。

結果示範

執行個體:用CSS和JS建立“前後”圖像對比效果

Codepen demo: https://codepen.io/josephwong2004/pen/NWRGxdR

逐漸指南

步驟 1.了解概念​

這個“圖像 slider”的概念非常簡單,你隻需要兩個元件,圖像容器和一個 slider。

圖檔容器隻是一個普通的 div,兩張相同大小的圖檔互相重疊。一個作為“背景”,另一個作為“前景”。

執行個體:用CSS和JS建立“前後”圖像對比效果

我們将使用絕對定位使前景圖像直接置于背景圖像之上。背景圖的寬度總是 100%,而前景圖的寬度會根據使用者的輸入而改變,使背景圖的一部分出現。

第二個元件是“slider”。為了使事情簡單化,我們可以使用 html range輸入元素。它允許使用者在你定義的最小值和最大值之間通過拖動來選擇一個值。使用 javascript 中的事件監聽器可以很容易地擷取輸入值。

<input
  type="range"
  min="1"
  max="100"
  value="50"
  class="slider"
  id="myRange"
/>      
執行個體:用CSS和JS建立“前後”圖像對比效果

使用預設 slider 輸入的一個缺點是,樣式是有限的。你不能在設計上太過瘋狂,如果你正在尋找一個更可定制的 slider,你可能需要自己建構它。然而,這不是本教程的重點。

我們将使滑塊具有 100%的容器寬度和高度,并将其放置在圖像容器的頂部。當使用者拖動滑塊時,我們同時更新前景的寬度,建立一種使用者拖動圖像的錯覺。

執行個體:用CSS和JS建立“前後”圖像對比效果

當滑塊值更新時,我們将更改前景的寬度

步驟 2.建立圖像容器​

首先建立容器,這是一個内部有兩個 div 的簡單結構。由于我們不希望圖像根據包含它們的 div 寬度進行縮放,是以我們将對圖像應用 background-image 而不是 <img> 标簽。我們需要使用的一種重要樣式是 background-size 屬性,并確定圖像始終保持相同大小。

HTML:

<div class="container">
  <div class="img background-img"></div>
  <div class="img foreground-img"></div>
</div>      

CSS:

.container {
  position: relative;
  width: 900px;
  height: 600px;
  border: 2px solid white;
}
.img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-size: 900px 100%;
}
.background-img {
  background-image: url("https://i.loli.net/2020/12/28/1dGpFx3zJ9Pjcme.jpg");
}
.foreground-img {
  background-image: url("https://i.loli.net/2020/12/28/xIZmjtBR5VWoqiz.jpg");
  width: 50%;
}      

為了使本教程更容易些,我對所有内容都使用了固定大小。如果你不想使用 SCSS,隻需将樣式設定為扁平而不是嵌套。

執行個體:用CSS和JS建立“前後”圖像對比效果

我使用了同一圖像的兩個版本(有色和無色),是以它們完全對齊。

現在我們有了容器,讓我們添加滑塊。

步驟 3.建立滑塊​

我們的滑塊需要覆寫整個圖像,并用細白條“劃分”圖像的前後部分。可以通過設定滑塊和滑塊(你拖動的部分)的樣式來完成。我們需要使滑塊和拇指的預設外觀不可見,然後在其上應用我們自己的樣式。

HTML(在圖檔下方):

<div class="container">
  ...
  <input
    type="range"
    min="1"
    max="100"
    value="50"
    class="slider"
    name="slider"
    id="slider"
  />
</div>      
.container {
  position: relative;
  width: 900px;
  height: 600px;
  border: 2px solid white;
}
.img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-size: 900px 100%;
}
.background-img {
  background-image: url("https://i.loli.net/2020/12/28/1dGpFx3zJ9Pjcme.jpg");
}
.foreground-img {
  background-image: url("https://i.loli.net/2020/12/28/xIZmjtBR5VWoqiz.jpg");
  width: 50%;
}


.slider {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 100%;
  background: rgba(242, 242, 241, 0.3);
  outline: none;
  margin: 0;
  transition: all 0.2s;
}
.slider:hover {
  background: rgba(242, 242, 241, 0.1);
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 6px;
  height: 600px;
  background: white;
  cursor: pointer;
}      

我在滑塊上應用了一個略微可見的灰色背景,在懸停時,使顔色更加透明。當使用者将滑鼠懸停在圖像上時,建立“焦點”效果。對于滑塊,它隻是一個白色背景 div,具有容器的整個高度。

執行個體:用CSS和JS建立“前後”圖像對比效果

我們現在有了一個工作的滑塊,讓我們把它和前景圖檔的寬度聯系起來。

步驟 4.将事件偵聽器添加到滑塊​

最後一步是将滑塊上的值連結到前景圖像的寬度,這很容易實作(因為我們使用本地 html range input 作為滑塊)。應用事件偵聽器時,可以在 event.target.value 中獲得 1–100 的值。

然後,我們隻需要選擇前景元素,并在滑塊更新時更改它的寬度即可。

JS

const slider = document.getElementById("slider");
slider.addEventListener("input", function(e) {
  document.querySelector(".foreground-img").style.width =
    e.target.value + "%";
});      

如果它沒有按預期工作,請嘗試檢視你是否正确擷取了 slider 的值,然後再次檢查 CSS 的 background-size 屬性。​

執行個體:用CSS和JS建立“前後”圖像對比效果

太酷了!功能正常。作為使用 range 輸入的額外好處是我們甚至可以在容器内單擊,使滑塊移動到被單擊的位置。

我們可以(可能應該)添加到 UI 的另一件事是在滑塊上做一個“拖動我”圓圈圖示,以訓示這是可拖動的元件。

步驟 5(可選)在滑塊上添加圓圈拇指​

原生的 range 輸入有它的優勢(容易實作,容易取值等),但在樣式上我們可以做的不多。由于我們用白色分隔線代替了預設的 “圓圈”拇指,是以我們需要用某種方式把圓圈加回來。

一種快速(但不實用)的方法是添加另一個元素,它與滑塊完全無關,但位于滑塊的中心,并通過 javascript“跟随”滑塊的移動。這正是我們要做的。

HTML:

<div class="container">
  ...
  <div class="slider-button"></div>
</div>      

CSS:

.slider-button {
  pointer-events: none;
  position: absolute;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background-color: white;
  left: calc(50% - 18px);
  top: calc(50% - 18px);
  display: flex;
  justify-content: center;
  align-items: center;
}
.slider-button::after {
  content: "";
  padding: 3px;
  display: inline-block;
  border: solid #5d5d5d;
  border-width: 0 2px 2px 0;
  transform: rotate(-45deg);
}
.slider-button::before {
  content: "";
  padding: 3px;
  display: inline-block;
  border: solid #5d5d5d;
  border-width: 0 2px 2px 0;
  transform: rotate(135deg);
}      

after 和 before 元素在圓圈按鈕内添加兩個“箭頭”

JS:

const slider = document.getElementById("slider");
let sliderPos;
slider.addEventListener("input", function(e) {
  sliderPos = e.target.value;
  document.querySelector(
    ".foreground-img"
  ).style.width = `${sliderPos}%`;
  document.querySelector(
    ".slider-button"
  ).style.left = `calc(${sliderPos}% - 18px)`;
});      

我們還需要做的一件事是讓圓圈成為不可選擇的,這樣滑鼠事件總是會轉到滑塊。通過一些精心的定位和 JS,我們讓圓圈拇指和滑塊一起移動。

執行個體:用CSS和JS建立“前後”圖像對比效果

這樣,我們的“前後”圖像滑塊就完成了,你現在可以選擇你最喜歡的圖檔并進行實驗。

源碼​

效果和全部代碼:https://coding.zhangbing.site

總結

如前所述,這個 UI 元素的概念非常簡單,你不需要安裝另一個庫來達到這種效果。話雖如此說,這是一個非常基本的實作,正如你所看到的,我使用了許多固定像素大小。如果你想要一個更“進階”的設計,我建議花點時間研究一下不同視窗大小下的設計變化。

在此示例中,我使用了黑白圖檔和彩色圖檔的比較。但是,我看到了許多其他具有時間變化特征的示例(例如 100 年前和現在的同一座城市)。對于這類設計,實作是類似的。

另外,由于我們使用的是背景圖檔屬性(不受容器大小的影響),是以你還可以使用動畫 gif 輕松建立靜态到動态的滑塊。

如果你喜歡本教程或有其他想法,請留言評論!