寫一個可擴充的360度產品旋轉外掛

逛吃的柯基發表於2017-12-08

1.前言

做過電商的朋友應該比較熟悉,當我們在介紹一個實體產品的時候必不可少的會有這個產品的圖片,這是使用者對這個產品的最直觀瞭解,從以前的包括現在的電商網站來看,產品詳情頁裡面產品的圖片一般都是佔一大部分,而且一般的排版方式都是圖片從上往下排來展示產品的各個角度的圖片或者使用輪播圖(參照淘寶京東等),因為這個是最簡單的能使使用者仔細瞭解產品的外觀的方法,所以目前幾乎所有的電商都會加入這個環節。當然我們在這裡並不是為了替換掉這種展示方式,而是我們增加一個能讓使用者更方便去了解產品實際全貌的方式,而且在排版上做到只佔一張圖片的位置。我們先來看看360度旋轉產品是怎麼樣的效果

寫一個可擴充的360度產品旋轉外掛

2.前期工作

好了,大家可能會問,像這種圖片是怎麼拍的呢?這個是攝影師從產品的各個角度拍攝的,需要搭建一定的拍攝環境,而且每個角度的度數的一樣的,應該是使用了旋轉託盤。我們在這裡就不仔細解釋拍攝過程了,有興趣的朋友可以自己去查查資料,我們在這裡講的是前端的效果實現

3.HTML程式碼結構

一般使用外掛來講,第一,我們希望HTML程式碼越少越好,第二,可以增加一些配置項,第三,很簡單的使用方式。這個外掛來講是非常簡單的,所以HTML程式碼只需一行

<div id="3dplayer" class='proPlayer_container' data-width='550' data-height='400' data-path='https://img.ingping.com/images/pro_3dImgs/320/6198/'></div>複製程式碼

這行html程式碼是一個容器,是屬於最外層的,class裡面的類是控制排版樣式的,data-width,data-height是設定圖片畫布大小的,data-path是23張圖片的的圖片路徑,我們這裡的圖片命名是從1到23來命名的,比如1.jpg  2.jpg 3.jpg......這個路徑是資料夾路徑

4.JavaScript程式碼

寫一個可擴充的360度產品旋轉外掛

大家可以放大來看這張圖,此外掛程式碼共有三個物件:proPlayer , proImg , controlPanel

proPlayer是主物件,也可以理解為程式碼用從這個物件開始執行的。

proImg是產品圖片物件,用來載入23張圖片

controlPanel是控制皮膚,可以理解為使用者在互動的那一層

我們逐一從各個物件來開始介紹,不過首先我們先檢測使用者的裝置是電腦還是移動端,這個對於我們事件操作有很大關係,因為在js中電腦和移動端的事件物件是不一樣的。

  //detect events  
 var hasTouch = 'ontouchstart' in window,  
     startEvent = hasTouch ? 'touchstart' : 'mousedown', 
     moveEvent = hasTouch ? 'touchmove' : 'mousemove',  
     endEvent = hasTouch ? 'touchend' : 'mouseup',  
     cancelEvent = hasTouch ? 'touchcancel' : 'mouseup';複製程式碼

proPlayer物件屬性:

  var proPlayer = {};  
  proPlayer.id = '3dplayer';  
  proPlayer.canvasIndex=1;  //畫布索引  
  proPlayer.debug = false;  
  proPlayer.width=500;  
  proPlayer.height=333;  
  proPlayer.banner = '';複製程式碼

proPlayer物件的方法:

proPlayer.load = function(){    
    proPlayer.init_debug();    
    //set banner    
    var banner = '<div><img src="'+proPlayer.banner+'" alt=""></div>';      
    $('#'+proPlayer.id).before(banner);      
    //set attr      
    proPlayer.width = $('#'+proPlayer.id).attr('data-width');      
    proPlayer.height = $('#'+proPlayer.id).attr('data-height');      
    //24張圖片路徑      
    proImg.path = $('#'+proPlayer.id).attr('data-path');      
    // preload images      
    proImg.preloadImages(function(index,isCompleted){        
        if(isCompleted){          
            //showTip('yes')          
            proPlayer.init();        
        }else{          
            //showTip(index);        
        }      
      });  
}複製程式碼

這個方法是程式碼首次執行時執行的,從寫的來看,這段程式碼的作用是獲取設定的寬高,路徑,和載入圖片,之後載入完後進行初始化 proPlayer.init()

程式碼初始化

//player init on image loaded  
    proPlayer.init = function(){    
    proPlayer.createControlPanel();    
    //detect mouse event    
    controlPanel.setControlPanel();    
    //create Images canvas    
    proPlayer.createCanvas();    
    //show first image    
    $('#3dplayer_1').show();    
    proPlayer.rotate();  
}複製程式碼

從程式碼可以看到,首先創造出控制皮膚,設定控制皮膚的事件監聽,將圖片畫到畫布上,我們來看看這些方法的詳細程式碼

proPlayer.createControlPanel();

proPlayer.createControlPanel=function(){    
    var panel = '<canvas id="d3player_0" width="'+proPlayer.width+'" height="'+proPlayer.height+'" style="z-index:99"></canvas>'    
    $('#'+proPlayer.id).prepend(panel)  
}複製程式碼

controlPanel.setControlPanel();

controlPanel.setControlPanel=function(){    
    var canvas = document.getElementById('d3player_0');
    document.addEventListener(startEvent, function(){      
        controlPanel.mousedown = true;        
        //showTip('mousedown');    
    },false)      
    document.addEventListener(endEvent, function(){        
        controlPanel.mousedown = false;        
        //showTip('mouseup');      
    })         
    canvas.addEventListener(moveEvent, function (e) {       
         if(controlPanel.mousedown){            
            var x = e.clientX || e.touches[0].screenX;              
            var preX = controlPanel.preX;              
            //showTip(preX+':'+x);              
            //大於5才移動            
            if(Math.abs(x-preX)>=controlPanel.speed){              
                controlPanel.callPlayer(preX,x);              
                controlPanel.preX = x;            
            }          
        }           
     }, false);  
}複製程式碼

上述方法也是這個外掛的核心之一了,監聽事件,然後改變控制皮膚的屬性的值從而觸發對應的canvas顯示隱藏

proPlayer.createCanvas();

proPlayer.createCanvas = function(){    
    //create canvas from img    
    for(var i=1;i<=proImg.count;i++){      
        var canvas_id = "3dplayer_"+i      
        var canvas_str = '<canvas id="'+canvas_id+'" style="display: none;" width="'+proPlayer.width+'" height="'+proPlayer.height+'"></canvas>';      
        $('#'+proPlayer.id).append(canvas_str);      
        var canvas = document.getElementById(canvas_id);      
        var context = canvas.getContext('2d');      
        var imageObj = proImg.list[i];      
        context.drawImage(imageObj, 0, 0,imageObj.width,imageObj.height,0,0,canvas.width,canvas.height);    
    }  
}複製程式碼

將23張圖片按照順序迴圈畫到每個畫布上,插入到DOM中

好了,我們先回到controlPanel.setControlPanel(),我們看到最後一個監聽事件,儲存滑鼠或者觸控事件的座標物件,儲存當前座標再和上一個座標作差的絕對值進行和speed對比(speed是可以設定的變數,可以控制我們旋轉時的敏感度,也可以說旋轉快慢吧)

之後我們判斷是向左還是向右旋轉

controlPanel.callPlayer = function(preX,currX){    
    if(preX > currX)      
        proPlayer.turnLeft();    
    else      
        proPlayer.turnRight();  
}複製程式碼

向左或向右判斷程式碼

proPlayer.turn = function(turn){    
    var turn = turn;    
    //一開始proPlayer.canvasIndex == 1    
    var index = proPlayer.canvasIndex;    
    if(turn){      
        index--;      
        if(index<1)        
            index=23;    
     }else{      
        index++;      
        if(index>23)        
           index=1;    
     }    
        return index;  
 }
  
  proPlayer.turnLeft=function(){    
     var index = proPlayer.turn(false);    
     proPlayer.show(index);  
  }
  proPlayer.turnRight=function(){    
    var index = proPlayer.turn(true);    
    proPlayer.show(index);  
  }複製程式碼

proPlayer.show() 顯示當前畫布的前或後一張圖

proPlayer.show = function(index){    
    var preIndex = proPlayer.canvasIndex;      
    var currIndex = index;      
    $('#3dplayer_'+currIndex).show();      
    $('#3dplayer_'+preIndex).hide();      
    proPlayer.canvasIndex = index;  
}複製程式碼

好了,目前該外掛的大部分程式碼都出現了,還是比較簡單的,比較精簡,而且可擴充,需要增加新功能直接在物件裡面增加屬性或者方法就可以了,比如我們想當圖片載入完成後讓畫布自動旋轉一週

在proPlayer這個物件上我們增加一個方法即可:

proPlayer.rotate = function(){    
    var i = 1;        
    var rotate = setInterval(function(){          
        if(i=== 23){            
            $("#3dplayer_1").show();            
            $("#d3player_0").show();            
            clearInterval(rotate);          
          }         
         $("#3dplayer canvas").hide();          
         $("#3dplayer_"+i).show();          
         $("#d3player_0").show();          
         i++;        
  },50)  
}複製程式碼

之後在proPlayer.init() 方法裡最後一步呼叫它就行

5.總結

我相信這種需求在電商領域中是比較常見的,使用者體驗也不錯,效果生動有科技感,我還引用了Jquery,大家有興趣也可以擴充套件一下這個簡單的外掛。

Github link



相關文章