借助 input range 实现图片对比功能

欢迎关注我的公众号:前端侦探

之前在项目中做了一个图片对比的工具,演示如下

Kapture 2023-07-15 at 15.41.20

有一些有趣的小细节,一起看看如何实现的吧

一、布局

布局比较简单,两张图片上下重叠在一起就行了

<div class="wrap">

	<img class="img" src="img1" >

	<img class="img" src="img2">
</div>

这里可以只给第一个图片设置绝对定位,有几个好处

  1. 第1张图片层级自动就高了
  2. 第1张图片仍在原处,也无需设置 left、top
  3. 第1张图片不占空间,父级高度就由第2张图片决定了
.img:first-of-type{
	position: absolute
}


示意如下
image-20230715154607830

更多有关绝对定位的小技巧可以参考之前这篇文章:你可能不知道的绝对定位

二、滑动图片

这里有个滑动的操作,如果直接使用 JS 来实现的话可能是这样(实际还有更多细节)

wrap.onmousedown = () => {}
document.onmousemove = () => {}
document.onmouseup = () => {}

其实在这里大可不必这么麻烦,完全可以借助原生标签的能力。提到”滑动”,是不是可以想到 input range 呢?

<input type="range">

image-20230715154918223

显然这个效果与实际相差甚远,不过完全可以用CSS定制一下,主要是去除背景色

[type=range]{
  margin: 0;
  -webkit-appearance: none;
  position: absolute;
  height: 100%;
  max-width: 100%;
  background: none;
  overflow: hidden;
  z-index: 2;
}
::-webkit-slider-runnable-track {
  background-color: transparent; /*去除背景*/
  height: 100%;
  cursor: ew-resize;
}
::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 4px;
  height: 100%;
  background-color: #18a0fb;
}

这样就变成了一个背景透明,只剩下滑块的滑动条了,并且整个范围都是可以滑动的

image-20230715155023892

然后把滑动条覆盖在图片之上就行了

<div class="wrap">

	<img class="img" src="img1" >

	<input type="range">
	<img class="img" src="img2">
</div>

三、裁切图片

现在需要在滑动过程中,动态裁剪上面的图片,可以通过 inputoninput 事件监听当前的进度,这里可以通过 CSS 变量记录在父级

input.oninput = () => {
	this.parentNode.style.setProperty('--pos', this.value / 100);
}


有了这个 CSS 变量,很多种方式都可以实现裁剪效果了,想了想至少有以下几种方式

1. 直接改变width

如果是普通的 div 标签,可以直接通过 overflow: hidden来裁剪内容,这里是图片,没有单独的父级,只能直接改变图片的宽高

.img:first-child{



	width: calc( var(--pos, .5) * 100% );

	height: 100%
}

但是这样很明显会有一个问题,图片被拉伸变形了

Kapture 2023-07-15 at 15.53.18.gif

怎么解决呢?其实通过图片的 object-* 属性就可以完美解决了

image.png

object-fit – CSS:层叠样式表 | MDN (mozilla.org)

object-position – CSS:层叠样式表 | MDN (mozilla.org)

这里用cover可以满足我们的需求

.img:first-child{



	width: calc( var(--pos, .5) * 100% );

	height: 100%;
	object-fit: cover;
 	object-position: left;
}

这样就正常了

Kapture 2023-07-15 at 15.41.20

2. clip-path裁剪

可以直接利用 clip-path 中的 inset 函数裁剪一个矩形。inset的四个参数分别表示距离的距离,示意如下

image-20230715160701060

用代码实现就是

.img:first-child{



	clip-path: inset( 0 calc( 100% - var(--pos, .5) * 100% ) 0 0 )
}


这种实现简单快速,也很好理解

Kapture 2023-07-15 at 15.41.20

3. mask遮罩

还可以通过 mask遮罩 实现,具体做法就是绘制一个矩形,然后改变遮罩的尺寸mask-size

image-20230715161936894

用代码实现就是

.img:first-child{



	-webkit-mask: linear-gradient(red,red) left center no-repeat; /*渐变绘制一个矩形*/
  -webkit-mask-size: calc( var(--pos, 0.5) * 100% ) 100%;
}

同样能得到这样的效果

Kapture 2023-07-15 at 15.41.20

你也可以查看以下任意链接:

四、总结一下

以上实现了一个图片对比的小交互,主要特点是通过 input range 的原生特性,省去了大量鼠标交互逻辑

接着是 CSS 变量的运用,JS只是一个媒介,很多交互就可以直接在 CSS 中完成了

然后在裁剪图片中用到了3种方式,3种不同的思路相信可以带来不一样的思维空间,可以视情况自行选择,如果还有新的想法也可以和我交流讨论。

最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤

欢迎关注我的公众号:前端侦探

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYbp4DxD' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片