藉助 input range 實現圖片對比功能

之前在項目中做了一個圖片對比的工具,演示如下

有一些有趣實用的小細節,一起看看如何實現的吧

一、佈局

佈局比較簡單,兩張圖片上下重疊在一起就行了

<div>

	<img src="img1" >

	<img src="img2">

</div>

這裏可以只給第一個圖片設置絕對定位,有幾個好處

  1. 第 1 張圖片層級自動就高了

  2. 第 1 張圖片仍在原處,也無需設置 left、top

  3. 第 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%;

}

同樣能得到這樣的效果

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

四、總結一下

以上實現了一個圖片對比的小交互,主要特點是通過 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