藉助 input range 實現圖片對比功能
之前在項目中做了一個圖片對比的工具,演示如下
有一些有趣實用的小細節,一起看看如何實現的吧
一、佈局
佈局比較簡單,兩張圖片上下重疊在一起就行了
<div>
<img src="img1" >
<img src="img2">
</div>
這裏可以只給第一個圖片設置絕對定位,有幾個好處
-
第 1 張圖片層級自動就高了
-
第 1 張圖片仍在原處,也無需設置 left、top
-
第 1 張圖片不佔空間,父級高度就由第 2 張圖片決定了
.img:first-of-type{
position: absolute
}
示意如下
二、滑動圖片
這裏有個滑動的操作,如果直接使用 JS
來實現的話可能是這樣(實際還有更多細節)
wrap.onmousedown = () => {}
document.onmousemove = () => {}
document.onmouseup = () => {}
其實在這裏大可不必這麼麻煩,完全可以藉助**「原生標籤」**的能力。提到 "滑動",是不是可以想到 input range
呢?
<input type="range">
顯然這個效果與實際相差甚遠,不過完全可以用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;
}
這樣就變成了一個**「背景透明,只剩下滑塊」**的滑動條了,並且整個範圍都是可以滑動的
然後把滑動條覆蓋在圖片之上就行了
<div>
<img src="img1" >
<input type="range">
<img src="img2">
</div>
三、裁切圖片
現在需要在滑動過程中,動態裁剪上面的圖片,可以通過 input
的 oninput
事件監聽當前的進度,這裏可以通過 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%
}
但是這樣很明顯會有一個問題,圖片被拉伸變形了
怎麼解決呢?其實通過圖片的 「object-」* 屬性就可以完美解決了
object-fit - CSS:層疊樣式表 | MDN (mozilla.org)[2]
object-position - CSS:層疊樣式表 | MDN (mozilla.org)[3]
這裏用cover
可以滿足我們的需求
.img:first-child{
width: calc( var(--pos, .5) * 100% );
height: 100%;
object-fit: cover;
object-position: left;
}
這樣就正常了
2. clip-path 裁剪
可以直接利用 clip-path
中的 inset
函數裁剪一個矩形。inset
的四個參數分別表示距離上
、右
、下
、左
的距離,示意如下
用代碼實現就是
.img:first-child{
clip-path: inset( 0 calc( 100% - var(--pos, .5) * 100% ) 0 0 )
}
這種實現簡單快速,也很好理解
3. mask 遮罩
還可以通過 mask 遮罩 實現,具體做法就是繪製一個矩形,然後改變遮罩的尺寸mask-size
用代碼實現就是
.img:first-child{
-webkit-mask: linear-gradient(red,red) left center no-repeat; /*漸變繪製一個矩形*/
-webkit-mask-size: calc( var(--pos, 0.5) * 100% ) 100%;
}
同樣能得到這樣的效果
你也可以查看以下任意鏈接:
-
img-diff (juejin.cn)[4]
-
img-diff (codepen.io)[5]
-
img-diff (runjs.work)[6]
四、總結一下
以上實現了一個圖片對比的小交互,主要特點是通過 input range
的原生特性,省去了大量鼠標交互邏輯
接着是 CSS
變量的運用,JS
只是一個媒介,很多交互就可以直接在 CSS 中完成了
然後在裁剪圖片中用到了 3 種方式,3 種不同的思路相信可以帶來不一樣的思維空間,可以視情況自行選擇,如果還有新的想法也可以和我交流討論。
參考鏈接
[1] 你可能不知道的絕對定位:_ https://juejin.cn/post/7204633786934607929_
[2]object-fit - CSS:層疊樣式表 | MDN (mozilla.org):_ https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-fit_
[3]object-position - CSS:層疊樣式表 | MDN (mozilla.org):_ https://developer.mozilla.org/zh-CN/docs/Web/CSS/object-position_
[4]img-diff (juejin.cn):_ https://code.juejin.cn/pen/7255942145469579319_
[5]img-diff (codepen.io):_ https://codepen.io/xboxyan/pen/XWgMLxg_
[6]img-diff (runjs.work):_ https://runjs.work/projects/f62ed9adee7f426b_
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/B0dIoanTwpQ4PXe5HhQMTw