H5W3
当前位置:H5W3 > JavaScript > 正文

【JS】如何使用CSS和JS创建“前后”图像比较功能

如何使用CSS和JS创建“前后”图像比较功能

杜尼卜
发布于 1 月 24 日

https://coding.zhangbing.site/view.html?url=./list/slider-before-after-image.html

使用html range input创建前后图像比较效果的分步教程。使用CSS和JavaScript,JS部分代码非常少,主要是HTML、CSS,和实现思路。

介绍

如果你有两张图像进行比较,则“前后”图像滑块是一个有效而又简单的UI元素。

该“slider”元素使你的用户可以控制两个图像在屏幕上的显示方式,并自由浏览两个不同的图像。你可能认为它需要一些库来创建这样的效果,但实际上,它是一个非常直接和容易编码的UI。有了CSS和JS的基础知识,每个人都可以创建它。

在本教程中,我将详细解释这个UI背后的概念,如何实现它,以及进一步增强的建议。

结果演示

逐步指南

步骤1.了解概念

这个“图像slider”的概念非常简单,你只需要两个组件,图像容器和一个slider。

图片容器只是一个普通的div,两张相同大小的图片相互重叠。一个作为“背景”,另一个作为“前景”。

【JS】如何使用CSS和JS创建“前后”图像比较功能

我们将使用绝对定位使前景图像直接置于背景图像之上。背景图的宽度总是100%,而前景图的宽度会根据用户的输入而改变,使背景图的一部分出现。

第二个组件是“slider”。为了使事情简单化,我们可以使用html range输入元素。它允许用户在你定义的最小值和最大值之间通过拖动来选择一个值。使用javascript中的事件监听器可以很容易地获取输入值。

<input type="range" min="1" max="100" value="50" class="slider" id="myRange">

【JS】如何使用CSS和JS创建“前后”图像比较功能

我们将使滑块具有100%的容器宽度和高度,并将其放置在图像容器的顶部。当用户拖动滑块时,我们同时更新前景的宽度,创建一种用户拖动图像的错觉。

【JS】如何使用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%;
}

【JS】如何使用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,.3);
outline: none;
margin: 0;
transition: all .2s;
}
.slider:hover {
background: rgba(242,242,241,.1);
}
.slider::-webkit-slider-thumb{
-webkit-appearance: none;
appearance: none;
width: 6px;
height: 600px;
background: white;
cursor: pointer;
}

我在滑块上应用了一个略微可见的灰色背景,在悬停时,使颜色更加透明。当用户将鼠标悬停在图像上时,创建“焦点”效果。对于滑块,它只是一个白色背景div,具有容器的整个高度。

我们现在有了一个工作的滑块,让我们把它和前景图片的宽度联系起来。

步骤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 + "%"
})

太酷了!功能正常。作为使用 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);
}

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,我们让圆圈拇指和滑块一起移动。

这样,我们的“前后”图像滑块就完成了,你现在可以选择你最喜欢的图片并进行实验。

源码

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

总结

如前所述,这个UI元素的概念非常简单,你不需要安装另一个库来达到这种效果。话虽如此说,这是一个非常基本的实现,正如你所看到的,我使用了许多固定像素大小。如果你想要一个更“高级”的设计,我建议花点时间研究一下不同窗口大小下的设计变化。

在此示例中,我使用了黑白图片和彩色图片的比较。但是,我看到了许多其他具有时间变化特征的示例(例如100年前和现在的同一座城市)。对于这类设计,实现是类似的。

另外,由于我们使用的是背景图片属性(不受容器大小的影响),因此你还可以使用动画gif轻松创建静态到动态的滑块。

如果你喜欢本教程或有其他想法,请发表评论!


原文:https://blog.zhangbing.site/2021/01/04/how-to-create-a-before-after-image-slider-with-css-and-js/

javascripthtml前端css3
阅读 22发布于 1 月 24 日
本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议

前端全栈开发者
专栏首发于公众号《前端全栈开发者》,订阅关注第一时间阅读好文
avatar

杜尼卜
前端工程师

<strong>做工程师不做码农、全栈开发工程师、持续学习者</strong>

10.1k 声望
1k 粉丝

0 条评论
得票时间

avatar

杜尼卜
前端工程师

<strong>做工程师不做码农、全栈开发工程师、持续学习者</strong>

10.1k 声望
1k 粉丝

宣传栏

https://coding.zhangbing.site/view.html?url=./list/slider-before-after-image.html

使用html range input创建前后图像比较效果的分步教程。使用CSS和JavaScript,JS部分代码非常少,主要是HTML、CSS,和实现思路。

介绍

如果你有两张图像进行比较,则“前后”图像滑块是一个有效而又简单的UI元素。

该“slider”元素使你的用户可以控制两个图像在屏幕上的显示方式,并自由浏览两个不同的图像。你可能认为它需要一些库来创建这样的效果,但实际上,它是一个非常直接和容易编码的UI。有了CSS和JS的基础知识,每个人都可以创建它。

在本教程中,我将详细解释这个UI背后的概念,如何实现它,以及进一步增强的建议。

结果演示

逐步指南

步骤1.了解概念

这个“图像slider”的概念非常简单,你只需要两个组件,图像容器和一个slider。

图片容器只是一个普通的div,两张相同大小的图片相互重叠。一个作为“背景”,另一个作为“前景”。

【JS】如何使用CSS和JS创建“前后”图像比较功能

我们将使用绝对定位使前景图像直接置于背景图像之上。背景图的宽度总是100%,而前景图的宽度会根据用户的输入而改变,使背景图的一部分出现。

第二个组件是“slider”。为了使事情简单化,我们可以使用html range输入元素。它允许用户在你定义的最小值和最大值之间通过拖动来选择一个值。使用javascript中的事件监听器可以很容易地获取输入值。

<input type="range" min="1" max="100" value="50" class="slider" id="myRange">

【JS】如何使用CSS和JS创建“前后”图像比较功能

我们将使滑块具有100%的容器宽度和高度,并将其放置在图像容器的顶部。当用户拖动滑块时,我们同时更新前景的宽度,创建一种用户拖动图像的错觉。

【JS】如何使用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%;
}

【JS】如何使用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,.3);
outline: none;
margin: 0;
transition: all .2s;
}
.slider:hover {
background: rgba(242,242,241,.1);
}
.slider::-webkit-slider-thumb{
-webkit-appearance: none;
appearance: none;
width: 6px;
height: 600px;
background: white;
cursor: pointer;
}

我在滑块上应用了一个略微可见的灰色背景,在悬停时,使颜色更加透明。当用户将鼠标悬停在图像上时,创建“焦点”效果。对于滑块,它只是一个白色背景div,具有容器的整个高度。

我们现在有了一个工作的滑块,让我们把它和前景图片的宽度联系起来。

步骤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 + "%"
})

太酷了!功能正常。作为使用 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);
}

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,我们让圆圈拇指和滑块一起移动。

这样,我们的“前后”图像滑块就完成了,你现在可以选择你最喜欢的图片并进行实验。

源码

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

总结

如前所述,这个UI元素的概念非常简单,你不需要安装另一个库来达到这种效果。话虽如此说,这是一个非常基本的实现,正如你所看到的,我使用了许多固定像素大小。如果你想要一个更“高级”的设计,我建议花点时间研究一下不同窗口大小下的设计变化。

在此示例中,我使用了黑白图片和彩色图片的比较。但是,我看到了许多其他具有时间变化特征的示例(例如100年前和现在的同一座城市)。对于这类设计,实现是类似的。

另外,由于我们使用的是背景图片属性(不受容器大小的影响),因此你还可以使用动画gif轻松创建静态到动态的滑块。

如果你喜欢本教程或有其他想法,请发表评论!


原文:https://blog.zhangbing.site/2021/01/04/how-to-create-a-before-after-image-slider-with-css-and-js/

本文地址:H5W3 » 【JS】如何使用CSS和JS创建“前后”图像比较功能

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址