Skip to content

交互式的图片对比控件

效果

作用:比较两张图片

思路:把两张图片叠加起来,通过滑动只显示上层的一部分,剩下一部分“剪切掉”,形成上层图片和下层图片的比较效果

resize

作用:规定是否可由用户调整元素的尺寸

属性:

描述
none用户无法调整元素的尺寸。
both用户可调整元素的高度和宽度。
horizontal用户可调整元素的宽度。
vertical用户可调整元素的高度。

一般元素默认值是 none,其中 textareaboth ,可以由用户拖动大小

解决方案

令两张图片上下(Z轴)叠加

给最上层图片添加 resize 属性以让其可以拖动,但直接拖动图片会导致其失真,所以应该用一层 div 包裹图片,然后拖动 div,让其“剪切”图片(overflow: hidden

这里为了视觉效果更好,使用一样的图片,但给上层图片添加一个滤镜,效果如上图

html
<div class="image-slider">
    <div>
        <img src="avatar.jpg" alt="before">
    </div>
    <img src="avatar.jpg" alt="after">
</div>
css
.image-slider {
    position: relative;
    width: 100px;
    height: 100px;
}
.image-slider > div {
    position: absolute; /* 脱离文档流 */
    top: 0; bottom: 0; left: 0;
    width: 50%; /* 初始宽度 */
    max-width: 100%; /* 让其拖动最多只能在父级容器的范围 */
    overflow: hidden; /* 裁剪图片 */
    resize: horizontal;
    filter: contrast(.5);
}
.image-slider img {
    display: block;
    width: 100px;
    height: 100%;
}

范围输入控件方案

右下角的拖动控件太小,会使用户体验大大降低,所以可以用一个范围输入控件提高可操作性

html
<div class="image-slider">
    <div class=“cut”>
        <img src="avatar.jpg" alt="before">
    </div>
    <img src="avatar.jpg" alt="after">
    <input type="range" />
</div>
css
/* 调整控件  */
.image-slider input {
    position: absolute;
    left: 0;
    bottom: 0;
	/* 控件相对图片来说太大,要缩小,但宽度要占满容器,所以先扩大宽度为两倍,在所以一倍 */
    width: 200%; 
    transform: scale(.5);
    transform-origin: left bottom;
}
js
// 还需要写一段脚本控制
const cut = document.querySelector('.cut')
const range = document.getElementsByTagName('input')[0]
range.oninput = function() {
    cut.style.width = this.value + '%'
}