废话不多说,直接上效果图:
源码:中隔线滑动案例
你可以先别往下看,自己想想怎么实现~~ 本文的实现只是作者的方式,你当然可以使用自己的方式。
实现思路
- 将输入内容做成中隔线的样子,拖动后触发数值变化
- 根据数值变化,设置横向百分比的遮罩
定义中隔线
html
<div class="compare">
<!-- range 元素默认 0 - 100 -->
<input type="range" id="range">
</div>
然后我们给输入框添加事件:
js
// html 中标记有 id 的元素,可以在 js 里直接使用同名 dom
range.oninput = () => {
document.body.style.setProperty('--pos', range.value + '%');
}
这样我们就能通过用户的拖拽往 css 里写入变量了。但是还有个问题,这个 range 他不是中隔线的样子,需要定义 css 样式:
css
input[type="range"] {
z-index: 1; // 为了置顶
appearance: none;
background: transparent;
cursor: pointer;
}
其中 appearance:none 是为了不显示拖动条,不设置的话就这样:
这样设置完后,效果如下:
为什么是个红点呢?因为我的电脑主题色是红色的,如果你是火狐,或者windows,就是一个白色的圆点,这个就是原生的 input 拖拽 bar 的颜色。我们需要把这个点变成一条线:
css
input[type="range"]::-webkit-slider-thumb {
appearance: none;
width: 4px;
height: 390px;
background-color: hotpink;
}
-webkit-slider-thumb 是 webkit 内核浏览器特有的样式,对于 firefox 需要另外写兼容:
css
input[type="range"]::-moz-range-thumb {
appearance: none;
width: 4px;
height: 390px;
background-color: hotpink;
}
这样他就变成了一条自定义颜色的中隔线。
定义遮罩
我们先把两张图片放置一下:
html
<div class="compare">
<section class="before">
<img src="https://images.unsplash.com/photo-1454496522488-7a8e488e8606?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2952&q=80" />
</section>
<section class="after">
<img src="https://images.unsplash.com/photo-1611605645802-c21be743c321?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80" />
</section>
<!-- range 元素默认 0 - 100 -->
<input type="range" id="range">
</div>
现在长这样:
我们现在加上遮罩属性:
css
.before {
mask: linear-gradient(to right, #000 0, var(--pos, 50%), #0000 0);
}
.after {
mask: linear-gradient(to right, #0000 0, var(--pos, 50%), #000 0);
}
mask 实战可以参考 使用 mask 实现视频弹幕人物遮罩过滤
本案例中,mask 属性接受一个线性渐变,配置为从左到右,#000 0
表示在 0% 处是黑色的,#0000 0
表示在 0% 处是黑色的,但是是透明的。var(--pos, 50%)
表示读取 css 变量,如果读取不到,默认是 50%,他是一个渐变停止点。
举个例子,比如 .before { mask: linear-gradient(to right, #000 0, 20%, #0000 0) }
表示前 20% 的区域有内容:
图片与 mask 生成的渐变的 transparent 的重叠部分,将会变得透明;而与 mask 渐变有颜色(这里是黑色)的地方交集就会原样显示
现在的效果图长这样:
我们还需要把他们叠在一起布局。
mask 兼容性:
设置网格布局
添加样式:
css
.compare {
display: grid;
}
.compare > * {
grid-area: 1 / 1;
}
可以看到他们重叠在一起了:
解释一下 grid-area,它用于指定网格项目在网格容器中的位置和跨度。这个属性是 grid-row-start、grid-column-start、grid-row-end 和 grid-column-end 的简写形式,因此它可以同时设置项目的起始行、起始列、结束行和结束列。
例如,如果要将一个项目放置在网格容器的第一行第一列,并跨越两行两列,可以这样写:
css
.item {
grid-area: 1 / 1 / 3 / 3;
}
本文的案例中,就是强制所有元素都在第一行第一列,因为就没有分行分列。
至此,核心实现就完成啦~
源码:中隔线滑动案例