JavaScript面向?qū)ο髮?shí)現(xiàn)放大鏡案例
本文實(shí)例為大家分享了JavaScript面向?qū)ο髮?shí)現(xiàn)放大鏡的具體代碼,供大家參考,具體內(nèi)容如下
效果圖

實(shí)現(xiàn)原理分析
如圖所示

觸發(fā)鼠標(biāo)的移動(dòng)事件時(shí),根據(jù)事件對(duì)象的 clientX 和 clientY 屬性得到實(shí)時(shí)的坐標(biāo)點(diǎn) x 和 y
值 ,減去 small_box 的 offsetLeft 值 和 cutting_box 的寬度的一半 ,可以得到 cutting_box 的偏移量 left 值,top值同理。當(dāng) cutting_box 到達(dá)右側(cè)和下側(cè)時(shí),left 和 top 取得最大值。用 實(shí)時(shí)變化的left和top值 比上 各自的最大值,可得到一個(gè)比例,再根據(jù)這個(gè)比例,算出右側(cè) big_img 元素的 left 和 top。具體求法是:先求出 big_img 放大后的寬高,由這個(gè)寬高求得big_img的 left和top 最大值。在用這個(gè)最大值乘以上述的比例值即得到相應(yīng)的 big_img 的 left 和 top值。
注意點(diǎn):big_img 放大后的寬高求法
small_box寬高 / cutting_box = big_img寬高 / big_box寬高。(只有big_img寬高未知)
基本頁(yè)面結(jié)構(gòu)
<div class="small"> <img src="images/timg.jpg" alt=""> <span class="grayBox"></span> </div> <div class="big"> <img src="images/timg.jpg" alt=""> </div>
CSS代碼
.small {
width: 400px;
height: 400px;
position: relative;
border:4px solid #ddd;
box-shadow: 0 0 5px rgba(0,0,0,.5);
}
.small img{
width: 100%;
height: 100%;
}
.small .grayBox{
display: none;
width: 100px;
height: 100px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
position: absolute;
left: 0;
top: 0;
}
.big{
width: 400px;
height: 400px;
position: absolute;
left: 700px;
top: 100px;
border:1px solid #f10;
display: none;
overflow: hidden;
}
.big img{
position: absolute;
}
面向?qū)ο髮?shí)現(xiàn)
分析(OOA)
- 元素選擇功能
- 綁定事件驅(qū)動(dòng)
- 元素的顯示與隱藏功能
- 小圖移動(dòng),大圖的放大跟隨移動(dòng)功能
- 鼠標(biāo)滾輪縮放功能
設(shè)計(jì)(OOD)
構(gòu)造函數(shù)
function Magnifier(){}
初始化各個(gè)功能模塊
function init(){}
事件綁定功能
function bindEvent(){}
元素的顯示與隱藏功能
function eleToggle(){}
小圖移動(dòng),大圖放大跟隨功能
function eleMove(){}
編寫(xiě)(OOP)
- 首先明確應(yīng)該把所有功能都放到放大鏡構(gòu)造函數(shù)的原型上。
- 其次實(shí)例化一個(gè)對(duì)象時(shí)應(yīng)該傳入的是對(duì)象類型的參數(shù),如下所示:
new Magnifier({
small_box : ".small",
cutting_box : ".grayBox",
big_box : ".big",
big_img : ".big img"
});
構(gòu)造函數(shù)此時(shí)需要接收實(shí)例化時(shí)傳入的參數(shù):
function Magnifier( options ) {
// 調(diào)用初始化函數(shù),處理接收到的參數(shù)對(duì)象
this.init( options );
}
初始化功能完成初始化元素、獲取small_box、cutting_box、big_box的offset系列的值:
Magnifier.prototype.init = function( options ){
// 初始化元素;
for(var attr in options){
this[attr+"_ele"] = this.$(options[attr]);
}
// 為了節(jié)省性能,所以只獲取一次offsetLeft;
this.small_box_offset = {
left : this.small_box_ele.offsetLeft,
top : this.small_box_ele.offsetTop,
width : parseInt( getComputedStyle(this.small_box_ele).width ),
height : parseInt( getComputedStyle(this.small_box_ele).width )
}
this.cutting_box_offset = {
width : parseInt( getComputedStyle(this.cutting_box_ele).width ),
height : parseInt( getComputedStyle(this.cutting_box_ele).height ),
}
this.big_box_offset = {
width : parseInt( getComputedStyle(this.big_box_ele).width ),
height : parseInt( getComputedStyle(this.big_box_ele).height ),
}
// 標(biāo)志變量 ,鼠標(biāo)是否移入放大鏡
this.magnifier_start = false;
this.bindEvent();
// 圖片縮放功能
this.scaleBigImg();
}
選擇元素功能:
Magnifier.prototype.$ = function(selector){
return document.querySelector(selector);
}
事件綁定功能:
Magnifier.prototype.bindEvent = function(){
// 鼠標(biāo)移入左側(cè)small_box
this.small_box_ele.addEventListener( "mouseover" , function(){
// cutting_box big_box元素顯示;
this.eleToggle("show");
// 修改標(biāo)志變量為true
this.magnifier_start = true;
// 修改事件函數(shù)里面的this指向?yàn)楫?dāng)前實(shí)例對(duì)象
}.bind(this));
// 鼠標(biāo)移出左側(cè)small_box
this.small_box_ele.addEventListener( "mouseout" , function(){
// cutting_box big_box元素隱藏;
this.eleToggle("hide");
this.magnifier_start = false;
}.bind(this));
// 鼠標(biāo)移動(dòng),元素運(yùn)動(dòng);
this.small_box_ele.addEventListener("mousemove" , function( evt ){
var e = evt || event;
// 獲取鼠標(biāo)點(diǎn)距離瀏覽器可視區(qū)的 x y 值
var x = e.clientX ;
var y = e.clientY ;
// 調(diào)用factoryPosition處理得到的坐標(biāo)值
this.res = this.factoryPosition( x , y );
// 把處理好后的坐標(biāo)值傳入eleMove方法,改變相應(yīng)的left、top值
this.eleMove( this.res );
}.bind(this));
// 滾輪事件;
document.addEventListener("mousewheel" , function( evt ){
// 如果鼠標(biāo)未移入放大鏡,則不執(zhí)行滾輪事件函數(shù)
if(!this.magnifier_start){ return false }
var e = evt || event;
// 判定滾輪向上(縮?。┻€是向下(放大);
this.changeCutBoxScale( e.wheelDelta > 0 ? "narrow" : "large" );
}.bind(this));
}
元素顯示隱藏功能:
Magnifier.prototype.eleToggle = function( type ){
// 根據(jù)type類型,判定元素的display的屬性值 block | none
this.cutting_box_ele.style.display = type === "show" ? "block" : "none";
this.big_box_ele.style.display = type === "show" ? "block" : "none";
}
處理鼠標(biāo)移動(dòng)時(shí)得到的坐標(biāo)點(diǎn) x 和 y 值:
Magnifier.prototype.factoryPosition = function( x , y ){
// 根據(jù)接收到的 x 和 y 計(jì)算得到 cutting_box 的 left 和 top 偏移量
var _left = x - this.small_box_offset.left - this.cutting_box_offset.width / 2;
var _top = y - this.small_box_offset.top - this.cutting_box_offset.height / 2
// cutting_box 的 left 和 top 的最大值
var _left_max = this.small_box_offset.width - this.cutting_box_offset.width;
var _top_max = this.small_box_offset.height - this.cutting_box_offset.height;
// 最小值邊界監(jiān)測(cè);
_left = _left <= 0 ? 0 : _left;
_top = _top <= 0 ? 0 : _top
// 最大值檢測(cè)
_left = _left >= _left_max ? _left_max : _left;
_top = _top >= _top_max ? _top_max : _top;
// 返回處理好的坐標(biāo)點(diǎn)值 以及 移動(dòng)的距離與最大值的比例系數(shù)
return {
x : _left,
y : _top,
xp: _left / _left_max,
yp:_top / _top_max
}
}
小圖移動(dòng),大圖放大跟隨功能:
Magnifier.prototype.eleMove = function( position_obj ){
// 左側(cè)cutting_box移動(dòng)范圍
this.cutting_box_ele.style.left = position_obj.x + "px";
this.cutting_box_ele.style.top = position_obj.y + "px";
// 大圖big_img的移動(dòng)范圍。cutting_box和big_img的移動(dòng)方向時(shí)相反的
this.big_img_ele.style.left = -position_obj.xp * this.big_img_boundary.left_max + "px";
this.big_img_ele.style.top = -position_obj.yp * this.big_img_boundary.top_max + "px";
}
放大圖片功能:
Magnifier.prototype.scaleBigImg = function(){
// 放大的比例 ;
var width_p = this.big_box_offset.width / this.cutting_box_offset.width;
var height_p = this.big_box_offset.height / this.cutting_box_offset.height;
// 獲得了big_img放大之后的寬高;
this.big_img_offset = {
width : width_p * this.small_box_offset.width,
height : height_p * this.small_box_offset.height,
}
// 計(jì)算出big_img運(yùn)動(dòng)的邊界;
this.big_img_boundary = {
left_max : this.big_img_offset.width - this.big_box_offset.width,
top_max : this.big_img_offset.height - this.big_box_offset.height
}
// 給圖片設(shè)置等比例寬高;
this.big_img_ele.style.width = this.big_img_offset.width + "px";
this.big_img_ele.style.height = this.big_img_offset.height + "px";
}
鼠標(biāo)滾輪滾動(dòng)時(shí)同時(shí)需要改變左側(cè) cutting_box 的大?。?/p>
Magnifier.prototype.changeCutBoxScale = function( type ){
switch ( type ) {
// 放大
case "large":
this.cutting_box_offset.width += 2;
this.cutting_box_offset.height += 2;
// 讓cutting_box 向左 向上移動(dòng) 讓鼠標(biāo)始終保持在中心位置
this.res.x --;
this.res.y --;
break;
// 縮小
case "narrow":
this.cutting_box_offset.width -= 2;
this.cutting_box_offset.height -= 2;
this.res.x ++;
this.res.y ++;
break;
default:
break;
}
this.cutting_box_ele.style.width = this.cutting_box_offset.width + "px";
this.cutting_box_ele.style.height = this.cutting_box_offset.height + "px";
// 位置改變之后,調(diào)用相應(yīng)的比例計(jì)算工具;
this.scaleBigImg();
// 重新進(jìn)行大圖運(yùn)動(dòng)的計(jì)算;
this.eleMove(this.res);
}
功能補(bǔ)充:多圖片切換,可以放大相應(yīng)的圖片。
添加標(biāo)簽:data-src自定義屬性存放不同的圖片路徑
<button class="btn" data-src=""><img src="" alt=""></button> <button class="btn" data-src=""><img src="" alt=""></button>
最后只需在實(shí)例化放大鏡對(duì)象后,分別給每個(gè)按鈕綁定點(diǎn)擊或者移入事件,再替換 small 和 big 容器中的 img 的 src 的屬性值為相應(yīng)的 data-src 的屬性值即可,如下所示:
// 選中所有代表不同圖片的button按鈕
var btns = document.querySelectorAll(".btn");
// 選中small 和 big 容器中的 img 標(biāo)簽
var imgs = document.querySelectorAll(".big img,.small img");
for(var i = 0 ; i < btns.length ; i ++){
btns[i].onclick = function(){
// 獲取每個(gè)按鈕上的不同的 data-src 屬性
var src = this.getAttribute("data-src");
for(var k = 0 ; k < imgs.length ; k ++){
// 替換相應(yīng)的 src 屬性的屬性值
imgs[k].src = src;
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS沙箱繞過(guò)以及競(jìng)爭(zhēng)條件型漏洞復(fù)現(xiàn)
沙箱繞過(guò)"是指攻擊者利用各種方法和技術(shù)來(lái)規(guī)避或繞過(guò)應(yīng)用程序或系統(tǒng)中的沙箱,本文主要介紹了JS沙箱繞過(guò)以及競(jìng)爭(zhēng)條件型漏洞復(fù)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-08-08
原生js通過(guò)一行代碼實(shí)現(xiàn)簡(jiǎn)易輪播圖
這篇文章主要介紹了原生js一行代碼實(shí)現(xiàn)簡(jiǎn)易輪播圖功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2019-06-06
用javascript實(shí)現(xiàn)鼠標(biāo)框選
用javascript實(shí)現(xiàn)鼠標(biāo)框選...2007-05-05
javascript用defineProperty實(shí)現(xiàn)簡(jiǎn)單的雙向綁定方法
這篇文章主要介紹了javascript用defineProperty實(shí)現(xiàn)簡(jiǎn)單的雙向綁定方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
JS實(shí)現(xiàn)仿QQ聊天窗口抖動(dòng)特效
本文給大家分享的是類似QQ窗口的抖動(dòng)效果,只是覺(jué)得好玩,沒(méi)什么技術(shù)含量,推薦給大家,有需要的小伙伴可以參考下。2015-05-05
JS簡(jiǎn)單獲取當(dāng)前年月日星期的方法示例
這篇文章主要介紹了JS簡(jiǎn)單獲取當(dāng)前年月日星期的方法,結(jié)合完整實(shí)例形式分析了javascript基于自定義函數(shù)獲取當(dāng)前日期時(shí)間的方法,涉及javascript中Date()類的使用與日期相關(guān)運(yùn)算技巧,需要的朋友可以參考下2017-02-02

