前端優化之商品圖片放大鏡
阿新 • • 發佈:2018-12-13
優化原因
現在的電商商城專案解決的主要是購買商品的問題,那麼購買商品主要要看清楚商品表面外形的主要特徵和細節,如果圖片處理過小,或者細節過於模糊,就需要做一個商品高清圖片放大區域性的功能。
技術關鍵點
- 左側和上側距離,在一個水平位置和垂直位置中有我們可以挪動的區域,就是原圖片區域,滑鼠挪動位置是一個塊狀位置,他的左側和上側距離瀏覽器上側和左側分別有一個長度,我們叫它們 ClientX 和 ClientY,而左上側滑鼠沒有略過的位置實際上是一個點,我們拖動放大塊時,它會由一個點變成一個方塊,這個放大鏡左上邊的點所控制的這一點距離螢幕上側和左側的 ClientY 和 ClientX 會隨著滑鼠的移動而變大變小,那麼要計算放大塊左側距離原點和上側原點就要減去原圖距離螢幕的上邊高度和左邊高度。在一個水平位置和垂直位置中有我們可以挪動的區域,就是原圖片區域,滑鼠挪動位置是一個塊狀位置,他的左側和上側距離瀏覽器上側和左側分別有一個長度,我們叫它們 ClientX 和 ClientY,而左上側滑鼠沒有略過的位置實際上是一個點,我們拖動放大塊時,它會由一個點變成一個方塊,這個放大鏡左上邊的點所控制的這一點距離螢幕上側和左側的 ClientY 和 ClientX 會隨著滑鼠的移動而變大變小,那麼要計算放大塊左側距離原點和上側原點就要減去原圖距離螢幕的上邊高度和左邊高度。
計算方式 x = 事件物件.clientX - 外側盒子.offsetLeft; Y = 事件物件.clientY - 外側盒子.offsetTop;
- 解決如何滑鼠在黃塊內居中的問題,橫縱位移分別加上放大黃塊一半的長度和寬度。
計算方式 x = 事件物件.clientX - 外側盒子.offsetLeft - 小黃.offsetWidth/2; Y = 事件物件.clientY - 外側盒子.offsetTop - 小黃.offsetHeight/2; // 事件物件的 offsetX 和 offsetY // 歸屬於事件物件 // 作用:關注的滑鼠的座標(滑鼠相對於當前元素的座標) // 元素的 offsetLeft 和 offsetTop // 歸屬於元素 // 作用:關注的元素的座標(相對於offsetParent的座標)
3. 小黃塊的最大距離
- 用preventDefault阻止事件冒泡
簡易實現程式碼
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="base.css"/>
</head>
<body>
<div class="w">
<div class="fdj">
<!-- 左側 -->
<div class="leftBox" id="_leftBox">
<!-- 小圖 -->
<img src="img/m.jpg" alt=""/>
<!-- 小黃盒子 -->
<div class="tool" id="_tool"></div>
</div>
<!-- 右側 -->
<div class="rightBox" id="_rightBox">
<img id="_bImg" src="img/b.jpg" alt=""/>
</div>
</div>
</div>
<!-- 引入的外部js程式檔案 -->
<script src="index.js"></script>
</body>
</html>
* {
margin:0;
padding:0;
}
.w {
width: 1190px;
margin: 0 auto;
}
.fdj {
margin-top: 20px;
}
.fdj .leftBox {
width: 400px;
height: 400px;
border: 1px solid #ccc;
float: left;
position: relative;
overflow: hidden;
}
.fdj .tool {
width: 250px;
height: 250px;
background:gold;
opacity:.5;
filter:alpha(opacity=50);
position: absolute;
top:0;
left: 0;
cursor: move;
/* 預設隱藏 */
display: none;
}
/* 給小黃加上active 就會顯示 */
.fdj .tool.active {
display: block;
}
.fdj .rightBox {
width: 500px;
height: 500px;
border:1px solid #ccc;
float: left;
overflow: hidden;
/* 隱藏 */
display: none;
position: relative;
}
/* 加上active表示顯示 */
.fdj .rightBox.active {
display: block;
}
.fdj .rightBox img {
position: absolute;
}
//【準備:獲取要操作的元素】
var _leftBox = document.querySelector('#_leftBox'); // 左側盒子
var _tool = document.querySelector('#_tool'); // 小黃盒子
var _rightBox = document.querySelector('#_rightBox'); // 右側盒子
var _bImg = document.querySelector('#_bImg'); // 右側盒子中的大圖片
//【功能1:滑鼠進入/離開左側盒子顯示/隱藏小黃和右側盒子】
// 1. 給_leftBox註冊滑鼠進入事件 onmouseenter
_leftBox.onmouseenter = function () {
// 1.1 顯示小黃盒子,給小黃盒子新增類名 active
_tool.className = 'tool active';
// 1.2 顯示右側盒子,給右側盒子新增類名 active
_rightBox.className = 'rightBox active';
}
// 2. 給_leftBox註冊滑鼠離開事件 onmouseleave
_leftBox.onmouseleave = function () {
// 2.1 顯示小黃盒子,給小黃盒子去除類名 active
_tool.className = 'tool';
// 2.2 顯示右側盒子,給右側盒子去除類名 active
_rightBox.className = 'rightBox';
}
//【功能2:滑鼠在左側區域移動時,控制小黃和右側盒子中圖片的位置】
// 1. 給左側盒子註冊滑鼠移動事件 onmosuemove
_leftBox.onmousemove = function (e) {
// 2. 通過事件物件獲取滑鼠相對元素的位置(x,y)
var x = e.clientX - _leftBox.offsetLeft- _tool.offsetWidth/2;
var y = e.clientY - _leftBox.offsetTop - _tool.offsetHeight/2;
// 這裡給x和y賦值時,不要用事件物件的offsetX和offsetY。
// 原因:因為【事件冒泡】,滑鼠在移動時,有時會移動到小黃盒子上。若移動到小黃盒子上時,獲取的值不是相對於左側盒子元素,而是相對小黃盒子元素。所以當滑鼠進入或離開小黃時,獲取的座標值時大時小,導致小黃盒子上下左右波動。
// 解決方案:在小黃移動事件中,停止冒泡。但是滑鼠在移動時,就沒有效果了。
// 最終解決方案:放棄使用事件物件offsetX/Y。 選擇事件物件的clienX/Y 結合左側盒子的位置計算出正確的位置。
// 2.1 對x和y限制
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
if (x > _leftBox.offsetWidth - _tool.offsetWidth) {
x = _leftBox.offsetWidth - _tool.offsetWidth;
}
if (y > _leftBox.offsetHeight - _tool.offsetHeight) {
y = _leftBox.offsetHeight - _tool.offsetHeight;
}
// 3. 把計算好的位置 賦值給小黃
_tool.style.left = x + 'px';
_tool.style.top = y + 'px';
// 4. 設定右側大圖片的位置(設定的方向是相反的,比例關係是1:2)
_bImg.style.left = -2 * x + 'px';
_bImg.style.top = -2 * y + 'px';
}