這個功能主要是參考yahoo奇摩在購物時,會提供給使用者某項便利的服務。例如:當您在
觀看某一項商品的細部內容時,一開始會有一張圖,此圖可能是縮小版的,因此當您滑鼠
移入該商品時,右邊的區塊就會呈現你滑鼠移入的局部放大圖示!因此本篇文章就是在探
討這個功能大概是如何實作的。
功能示範如下(來源:yahoo奇摩購物中心頁面,相關連結):
==========================正文如下==========================
首先要說明的是,原圖大小1000 x 1000 px、左圖400 x 400 px、小方框160 x 160 px
所以,圖與圖之間比例為2.5。1000/2.5 = 400, 400/2.5 = 160
因此,當你在左圖的方框圈選到的區域(160x160),在右邊(400 x 400長寬的限制下)
只會呈現1000x1000的某一塊400x400 px區域,可見下面的簡易圖:
若方框移到 left : 240的位置,換算成右圖1000x1000px只能呈現他內圖的(-600, 0)延伸
長、寬各400的區域!
所以,圖導覽的方式是以這種比例與概念去呈現的!
接下來就是自行實作的程式碼部分如下:
HTML部分:
CSS相關語法:
在這邊會先設定一個外圍的div區塊,寬度820px
source_block是左圖的區塊,裡面包含縮小圖(400x400)及方框(160x160)
tip_info區塊為右圖區塊的說明(以yahoo來想像的話是產品說明)
enlarge區塊為呈現方框導覽到的區域
JavaScript&jQuery部分
1. 初始化部分
這個部分會載入指定的圖片(1000x1000),並且分別定義source_block區塊與enlarge區塊
的圖片設定。請注意enlarge部分,background-size為原圖大小,但是長寬只呈現400x400!
2. 進入source區域(左圖)
這個部分是定義,當你的滑鼠移進左圖時,會帶出方框,但為什麼要減去
DEFAULT_START_POS,目的是當你滑鼠一移進去,剛好在方框正中間的位置!
而outside_check的目的就是調整方框不要超出左圖的範圍,最小是50,最大是290
照理說應該是0跟240,因為我調整body padding:50,因此得多算這50的部分!
3. 移動方框
當進入方框後,此時m_curr.state = true,因此就會執行
delta.x = e.pageX - (guide_obj.offsetLeft + DEFAULT_START_POS);
delta.y = e.pageY - (guide_obj.offsetTop + DEFAULT_START_POS);
上面這兩段code,e.pageX, e.pageY為當下滑鼠移動位置減去方框當下的座標(左上頂點),
此時方框還不會移動,因為在此設定要接近方框的正中間即可以自由移動!
所以才加DEFAULT_START_POS,否則delta.x = 0, delta.y = 0(表次原地踏步)
緊接著,當方框移動時也得去檢查是否過界!
最後就是去計算當下右圖的呈現座標位置(由於是圖的一部分,因此座標是負的)
最後,滑鼠移出左圖後,方框就會消失!但您若移很快方框還是會跟著動,因為在這邊
的mousemove選擇器是塞document XD
PS. 當方框可以移動後,就不用限制一定要在正中間才會移動,所以多了delta.move_x判斷,
一旦可以移動基本上就不需要考慮正中間的問題,否則移動起來會卡卡的。
成果圖如下:
初始畫面
一進去左圖,方框停在正中間,可以上下移動
問題探討:
最後有碰到一個問題,就是當滑鼠移動很快的時候,會出現一種情況,請見示意圖
這是我寫的code的特性碰到的問題。
m_curr.state = false; // 對方框失去移動控制作用
但是$("#source").mouseenter(..)事件觸發是在滑鼠一碰到左圖
m_curr.state等於false時,m_curr.state 會設成 true;
假設,今天我移動飛快(方框跟不上),此時出方框區域 (1),雖然m_curr.state = false;
但此時還在左圖區域,又觸發$("#source").mouseenter(..)事件,m_curr.state 會設成 true,
屆時,我雖然移出左圖區域 (2),但是還可以控制方框囉(m_curr.state = true)!
面對這種情況,我是在mousemove多加了一個判斷
m_curr.state && (e.target.nodeName == 'BODY' || e.target.nodeName == 'HTML')
只要一出這個區域,若m_curr.state = true,且target = BODY or HTML強制reset
,因此就不會出現上述的bug囉!
PS. 最後,如果您要demo這個功能,可以去yahoo的頁面玩玩看XD,說真的這個功能頗實
用的,因為網頁版面沒有那麼大,但如果要看到比較大的圖,用這種方式導覽還不錯囉!
觀看某一項商品的細部內容時,一開始會有一張圖,此圖可能是縮小版的,因此當您滑鼠
移入該商品時,右邊的區塊就會呈現你滑鼠移入的局部放大圖示!因此本篇文章就是在探
討這個功能大概是如何實作的。
功能示範如下(來源:yahoo奇摩購物中心頁面,相關連結):
正常頁面
滑鼠移入(注意左方的透明方框)
在這邊只是補充這功能的說明。
==========================正文如下==========================
首先要說明的是,原圖大小1000 x 1000 px、左圖400 x 400 px、小方框160 x 160 px
所以,圖與圖之間比例為2.5。1000/2.5 = 400, 400/2.5 = 160
因此,當你在左圖的方框圈選到的區域(160x160),在右邊(400 x 400長寬的限制下)
只會呈現1000x1000的某一塊400x400 px區域,可見下面的簡易圖:
若方框移到 left : 240的位置,換算成右圖1000x1000px只能呈現他內圖的(-600, 0)延伸
長、寬各400的區域!
所以,圖導覽的方式是以這種比例與概念去呈現的!
接下來就是自行實作的程式碼部分如下:
HTML部分:
<div style="width:820px;">
<div id="source_block">
<div id="guide_square"></div>
<img id="source" />
</div>
<div id="tip_info">...</div>
<div id="enlarge"></div>
</div>
CSS相關語法:
body{
margin: 0;
padding: 50px;
}
#guide_square{
position:absolute;
display:none;
width:160px;
height:160px;
background-color: #ccc;
opacity: 0.5;
z-index:2;
cursor: move;
}
#source_block{
width: 400px;
float: left;
}
#tip_info{
float:right;
border: 1px solid #000000;
width:400px;
height:400px;
}
#enlarge{
float:right;
}
在這邊會先設定一個外圍的div區塊,寬度820px
source_block是左圖的區塊,裡面包含縮小圖(400x400)及方框(160x160)
tip_info區塊為右圖區塊的說明(以yahoo來想像的話是產品說明)
enlarge區塊為呈現方框導覽到的區域
JavaScript&jQuery部分
1. 初始化部分
var img_obj = new Image();
var SCALE = 2.5;
img_obj.src = "CIMG4428.JPG";
var guide_obj = null;
guide_obj = document.getElementById('guide_square');
img_obj.onload = function(){
$("li").attr("type", "none");
$("#source").css({
"width" : img_obj.width/SCALE,
"height": img_obj.height/SCALE,
"background-size" : (img_obj.width/SCALE)+"px "+(img_obj.height/SCALE)+"px",
"background-image": "url("+img_obj.src+")"
});
$("#enlarge").css({
"display" : "none",
"width" : img_obj.width/SCALE,
"height": img_obj.height/SCALE,
"background-size" : img_obj.width+"px "+img_obj.height+"px",
"background-image": "url("+img_obj.src+")"
});
};
這個部分會載入指定的圖片(1000x1000),並且分別定義source_block區塊與enlarge區塊
的圖片設定。請注意enlarge部分,background-size為原圖大小,但是長寬只呈現400x400!
2. 進入source區域(左圖)
var m_curr = {
state: false,
x : 0,
y : 0
};
var DEFAULT_START_POS = 80;
var MIN_POS = 50;
var MAX_POS = MIN_POS + 240;
$("#source").mouseenter(function(e){
if(!m_curr.state){
m_curr.x = outside_check(e.pageX-DEFAULT_START_POS, MIN_POS, MAX_POS);
m_curr.y = outside_check(e.pageY-DEFAULT_START_POS, MIN_POS, MAX_POS);
$("#guide_square").css({
display: "block",
top: m_curr.y,
left: m_curr.x
});
$("#tip_info").hide();
$("#enlarge").show();
m_curr.state = true;
}
});
function outside_check(value, bottom, top){
if(value < bottom){
value = bottom;
}else if(value > top){
value = top;
}
return value;
}
這個部分是定義,當你的滑鼠移進左圖時,會帶出方框,但為什麼要減去
DEFAULT_START_POS,目的是當你滑鼠一移進去,剛好在方框正中間的位置!
而outside_check的目的就是調整方框不要超出左圖的範圍,最小是50,最大是290
照理說應該是0跟240,因為我調整body padding:50,因此得多算這50的部分!
3. 移動方框
var delta = {
move_x: false,
move_y: false,
x : 0,
y : 0
};
$(document).mousemove(function(e){
if(m_curr.state && (e.target.nodeName == 'BODY' || e.target.nodeName == 'HTML')){
reset_setting();
}
if(m_curr.state){
delta.x = e.pageX - (guide_obj.offsetLeft + DEFAULT_START_POS);
delta.y = e.pageY - (guide_obj.offsetTop + DEFAULT_START_POS);
if(Math.abs(delta.x) > DEFAULT_START_RANGE && !delta.move_x){
delta.x = 0;
}else{
delta.move_x = true;
}
if(Math.abs(delta.y) > DEFAULT_START_RANGE && !delta.move_y){
delta.y = 0;
}else{
delta.move_y = true;
}
m_move_x = outside_check(guide_obj.offsetLeft + delta.x, MIN_POS, MAX_POS);
m_move_y = outside_check(guide_obj.offsetTop + delta.y, MIN_POS, MAX_POS);
guide_obj.style.left = m_move_x+"px";
guide_obj.style.top = m_move_y+"px";
start_pos = "-"+(m_move_x-MIN_POS)*SCALE+"px -"+(m_move_y-MIN_POS)*SCALE+"px"
$("#enlarge").css({
"background-position" : start_pos,
});
}
});
$("#guide_square").mouseout(function(e){
if(m_curr.state){
reset_setting();
}
});
function reset_setting(){
guide_obj.style.display = 'none';
$("#guide_square").hide();
$("#enlarge").hide();
$("#tip_info").show();
delta.move_x = false;
delta.move_y = false;
m_curr.state = false;
}
當進入方框後,此時m_curr.state = true,因此就會執行
delta.x = e.pageX - (guide_obj.offsetLeft + DEFAULT_START_POS);
delta.y = e.pageY - (guide_obj.offsetTop + DEFAULT_START_POS);
上面這兩段code,e.pageX, e.pageY為當下滑鼠移動位置減去方框當下的座標(左上頂點),
此時方框還不會移動,因為在此設定要接近方框的正中間即可以自由移動!
所以才加DEFAULT_START_POS,否則delta.x = 0, delta.y = 0(表次原地踏步)
緊接著,當方框移動時也得去檢查是否過界!
最後就是去計算當下右圖的呈現座標位置(由於是圖的一部分,因此座標是負的)
最後,滑鼠移出左圖後,方框就會消失!但您若移很快方框還是會跟著動,因為在這邊
的mousemove選擇器是塞document XD
PS. 當方框可以移動後,就不用限制一定要在正中間才會移動,所以多了delta.move_x判斷,
一旦可以移動基本上就不需要考慮正中間的問題,否則移動起來會卡卡的。
成果圖如下:
初始畫面
一進去左圖,方框停在正中間,可以上下移動
移動至正中間方框,才可以左右移動
問題探討:
最後有碰到一個問題,就是當滑鼠移動很快的時候,會出現一種情況,請見示意圖
這是我寫的code的特性碰到的問題。
我的code是設定一移出方框就會執行
m_curr.state = false; // 對方框失去移動控制作用
但是$("#source").mouseenter(..)事件觸發是在滑鼠一碰到左圖
m_curr.state等於false時,m_curr.state 會設成 true;
假設,今天我移動飛快(方框跟不上),此時出方框區域 (1),雖然m_curr.state = false;
但此時還在左圖區域,又觸發$("#source").mouseenter(..)事件,m_curr.state 會設成 true,
屆時,我雖然移出左圖區域 (2),但是還可以控制方框囉(m_curr.state = true)!
面對這種情況,我是在mousemove多加了一個判斷
m_curr.state && (e.target.nodeName == 'BODY' || e.target.nodeName == 'HTML')
只要一出這個區域,若m_curr.state = true,且target = BODY or HTML強制reset
,因此就不會出現上述的bug囉!
PS. 最後,如果您要demo這個功能,可以去yahoo的頁面玩玩看XD,說真的這個功能頗實
用的,因為網頁版面沒有那麼大,但如果要看到比較大的圖,用這種方式導覽還不錯囉!
留言
張貼留言