JavaScript面向?qū)ο髮崿F(xiàn)放大鏡案例
本文實例為大家分享了JavaScript面向?qū)ο髮崿F(xiàn)放大鏡的具體代碼,供大家參考,具體內(nèi)容如下
效果圖
實現(xiàn)原理分析
如圖所示
觸發(fā)鼠標(biāo)的移動事件時,根據(jù)事件對象的 clientX 和 clientY 屬性得到實時的坐標(biāo)點(diǎn) x 和 y
值 ,減去 small_box 的 offsetLeft 值 和 cutting_box 的寬度的一半 ,可以得到 cutting_box 的偏移量 left 值,top值同理。當(dāng) cutting_box 到達(dá)右側(cè)和下側(cè)時,left 和 top 取得最大值。用 實時變化的left和top值 比上 各自的最大值,可得到一個比例,再根據(jù)這個比例,算出右側(cè) big_img 元素的 left 和 top。具體求法是:先求出 big_img 放大后的寬高,由這個寬高求得big_img的 left和top 最大值。在用這個最大值乘以上述的比例值即得到相應(yīng)的 big_img 的 left 和 top值。
注意點(diǎn):big_img 放大后的寬高求法
small_box寬高 / cutting_box = big_img寬高 / big_box寬高。(只有big_img寬高未知)
基本頁面結(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ū)ο髮崿F(xiàn)
分析(OOA)
- 元素選擇功能
- 綁定事件驅(qū)動
- 元素的顯示與隱藏功能
- 小圖移動,大圖的放大跟隨移動功能
- 鼠標(biāo)滾輪縮放功能
設(shè)計(OOD)
構(gòu)造函數(shù)
function Magnifier(){}
初始化各個功能模塊
function init(){}
事件綁定功能
function bindEvent(){}
元素的顯示與隱藏功能
function eleToggle(){}
小圖移動,大圖放大跟隨功能
function eleMove(){}
編寫(OOP)
- 首先明確應(yīng)該把所有功能都放到放大鏡構(gòu)造函數(shù)的原型上。
- 其次實例化一個對象時應(yīng)該傳入的是對象類型的參數(shù),如下所示:
new Magnifier({ small_box : ".small", cutting_box : ".grayBox", big_box : ".big", big_img : ".big img" });
構(gòu)造函數(shù)此時需要接收實例化時傳入的參數(shù):
function Magnifier( options ) { // 調(diào)用初始化函數(shù),處理接收到的參數(shù)對象 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指向為當(dāng)前實例對象 }.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)移動,元素運(yùn)動; 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)移動時得到的坐標(biāo)點(diǎn) x 和 y 值:
Magnifier.prototype.factoryPosition = function( x , y ){ // 根據(jù)接收到的 x 和 y 計算得到 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)測; _left = _left <= 0 ? 0 : _left; _top = _top <= 0 ? 0 : _top // 最大值檢測 _left = _left >= _left_max ? _left_max : _left; _top = _top >= _top_max ? _top_max : _top; // 返回處理好的坐標(biāo)點(diǎn)值 以及 移動的距離與最大值的比例系數(shù) return { x : _left, y : _top, xp: _left / _left_max, yp:_top / _top_max } }
小圖移動,大圖放大跟隨功能:
Magnifier.prototype.eleMove = function( position_obj ){ // 左側(cè)cutting_box移動范圍 this.cutting_box_ele.style.left = position_obj.x + "px"; this.cutting_box_ele.style.top = position_obj.y + "px"; // 大圖big_img的移動范圍。cutting_box和big_img的移動方向時相反的 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, } // 計算出big_img運(yùn)動的邊界; 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)滾輪滾動時同時需要改變左側(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 向左 向上移動 讓鼠標(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)的比例計算工具; this.scaleBigImg(); // 重新進(jìn)行大圖運(yùn)動的計算; 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>
最后只需在實例化放大鏡對象后,分別給每個按鈕綁定點(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(){ // 獲取每個按鈕上的不同的 data-src 屬性 var src = this.getAttribute("data-src"); for(var k = 0 ; k < imgs.length ; k ++){ // 替換相應(yīng)的 src 屬性的屬性值 imgs[k].src = src; } } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
javascript用defineProperty實現(xiàn)簡單的雙向綁定方法
這篇文章主要介紹了javascript用defineProperty實現(xiàn)簡單的雙向綁定方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04