首先知道幾個頁面位置信息的apicss
補充:html
這一版主要是在小圖右側放一個大圖,經過大圖移動位置以及利用層級關係,顯示大圖的部分區域,展示放大的效果. 計算公式: 大圖的left = -(左側圖片內滑塊left / (左側圖片寬度 - 滑塊寬度)) * (右側大圖寬度 - 右側大圖展示區域寬度)api
頁面結構很簡單,總的來講就是須要兩張圖片,一張小圖片和一張如出一轍的大圖片,主要複雜的是js中的計算部分:瀏覽器
<div id="demo">
<!-- 左邊的小圖 -->
<div id="small-box">
<div id="mark"></div>
<!-- 放大鏡 -->
<div id="float-box"></div>
<img src="small.jpg"/>
</div>
<!-- 顯示的大圖 -->
<div id="big-box">
<img src="big.jpg"/>
</div>
</div>
複製代碼
<style>
* {
margin: 0;
padding: 0
}
#demo {
display: block;
width: 400px;
height: 255px;
margin: 50px;
position: relative;
border: 1px solid #ccc;
}
#small-box {
position: relative;
z-index: 1;
}
#float-box {
display: none;
width: 160px;
height: 120px;
position: absolute;
background: #ffffcc;
border: 1px solid #ccc;
filter: alpha(opacity=50);
opacity: 0.5;
}
#mark {
position: absolute;
display: block;
width: 400px;
height: 255px;
background-color: #fff;
filter: alpha(opacity=0);
opacity: 0;
z-index: 10;
}
#big-box {
display: none;
position: absolute;
top: 0;
left: 460px;
width: 400px;
height: 300px;
overflow: hidden;
border: 1px solid #ccc;
z-index: 1;;
}
#big-box img {
position: absolute;
z-index: 5
}
</style>
複製代碼
此時咱們頁面上就只有一張小圖片markdown
<script>
//頁面加載完畢後執行
window.onload = function () {
var objDemo = document.getElementById("demo");
var objSmallBox = document.getElementById("small-box");
var objMark = document.getElementById("mark");
var objFloatBox = document.getElementById("float-box");
var objBigBox = document.getElementById("big-box");
var objBigBoxImage = objBigBox.getElementsByTagName("img")[0];
//鼠標一如事件
objMark.onmouseover = function () {
objFloatBox.style.display = "block"
objBigBox.style.display = "block"
}
//鼠標移出事件
objMark.onmouseout = function () {
objFloatBox.style.display = "none"
objBigBox.style.display = "none"
}
//鼠標移動事件
objMark.onmousemove = function (ev) {
var _event = ev || window.event; //兼容多個瀏覽器的event參數模式
var left = _event.clientX - objDemo.offsetLeft - objSmallBox.offsetLeft - objFloatBox.offsetWidth / 2;
var top = _event.clientY - objDemo.offsetTop - objSmallBox.offsetTop - objFloatBox.offsetHeight / 2;
if (left < 0) {
left = 0;
} else if (left > (objMark.offsetWidth - objFloatBox.offsetWidth)) {
left = objMark.offsetWidth - objFloatBox.offsetWidth;
}
if (top < 0) {
top = 0;
} else if (top > (objMark.offsetHeight - objFloatBox.offsetHeight)) {
top = objMark.offsetHeight - objFloatBox.offsetHeight;
}
objFloatBox.style.left = left + "px";
objFloatBox.style.top = top + "px";
var percentX = left / (objMark.offsetWidth - objFloatBox.offsetWidth);
var percentY = top / (objMark.offsetHeight - objFloatBox.offsetHeight);
objBigBoxImage.style.left = -percentX * (objBigBoxImage.offsetWidth - objBigBox.offsetWidth) + "px";
objBigBoxImage.style.top = -percentY * (objBigBoxImage.offsetHeight - objBigBox.offsetHeight) + "px";
}
}
</script>
複製代碼
所謂優雅版就是把鼠標變成放大鏡,這樣就會有比較真實的用放大鏡看東西的效果函數
大體實現思路以下:url
1)原圖部分添加mouseover監聽函數,在鼠標移入原圖後,獲取鼠標距離原圖的top和left的位置spa
2)在鼠標放大鏡區域,設置區域背景爲放大後的圖片,設置爲backgroundcode
3)反向計算放大後圖片應該移動的距離,設置background-positionorm
html部分代碼很是簡單,就是一個原圖背景圖,還有就是兩個不顯示的img元素,這兩個不顯示的元素,主要是用來獲取圖片的寬高
<div id="background" className={styles.originImage} style={{backgroundImage: `url(${url})`}}>
<img src={url} />
<img id="bigger" src={url} />
<div id="manifier" className={styles.biggerImage} style={{backgroundImage: `url(${url})`}} />
</div>
複製代碼
js代碼主要分爲兩部分
1)監聽鼠標在原圖上的移動
const listenBackMousemove = (e: globalThis.MouseEvent) => {
if (!manifier || !background) return
let left = e.offsetX - manifier.offsetWidth / 2,
top = e.offsetY - manifier.offsetHeight / 2
if (left < 0) left = 0
else if (left > background.offsetWidth - manifier.offsetWidth)
left = background.offsetWidth - manifier.offsetWidth
if (top < 0) top = 0
else if (top > background.offsetHeight - manifier.offsetHeight)
top = background.offsetHeight - manifier.offsetHeight
manifier.style.visibility = 'visible'
manifier.style.left = left + 'px'
manifier.style.top = top + 'px'
imgMove(left, top)
}
複製代碼
2)根據鼠標在原圖上移動的距離,反向計算放大後的圖片應該移動的距離
const imgMove = (left: number, top: number) => {
if (!bigger || !background || !manifier) return
const imgWidth = bigger.offsetWidth
const imgHeight = bigger.offsetHeight
const backHeight = background.offsetHeight
const backWidth = background.offsetWidth
const manHeight = manifier.offsetHeight
const manWidth = manifier.offsetWidth
const rateX = left / (backWidth - manWidth)
const rateY = top / (backHeight - manHeight)
let imgLeft = -(rateX * (imgWidth - manWidth)),
imgTop = -(rateY * (imgHeight - manHeight))
if (imgLeft > 0) imgLeft = 0
else if (imgLeft < -(imgWidth - manWidth)) imgLeft = -(imgWidth - manWidth)
if (imgTop > 0) imgTop = 0
else if (imgTop < -(imgHeight - manHeight)) imgTop = -(imgHeight - manHeight)
manifier.style.backgroundPosition = `${imgLeft}px ${imgTop}px`
}
複製代碼
.originImage {
background-position: center center;
background-size: contain;
background-repeat: no-repeat;
position: relative;
& > img:nth-child(1) {
width: 100%;
height: auto;
visibility: hidden;
}
& > img:nth-child(2) {
width: auto;
height: auto;
position: absolute;
left: -9999px;
top: 0;
}
.biggerImage {
position: absolute;
width: 100px;
height: 100px;
border: 1px solid #ededed;
border-radius: 10px;
cursor: none;
pointer-events: none;
}
}
複製代碼
css部分有一個點須要注意,須要將鼠標放大鏡的鼠標屬性設置爲none,即穿透效果,這樣在背景原圖上的移動就不會受影響。不然可能會走進鼠標放大鏡區域的mouseover事件