利用Canvas實現360度瀏覽

前言:最近幾個月來到新公司,主要從事移動端方面的開發,有時候也挺忙挺累的,因而就好一段時間沒寫博客了。其實本身在這幾個月裏,本身對canvas以及createjs和egret都有了必定程度上的認識與掌握了,因此有挺多東西想總結一下的。趁着今天廣州下雪的日子,就寫點東西吧,先從簡單的demo開始吧。由於本身在走HTML5遊戲方向,因此最近都在作小遊戲。後續會再寫關於canvas和createjs的系列文章吧,畢竟國內的資料比較少。一旦愛上了canvas,我便逐漸嫌棄DOM了。css

360度瀏覽效果

  利用最簡單的多張圖片,讓產品實現360旋轉瀏覽效果。以往用DOM來實現圖片或者背景更換,是挺方便也容易,可是在移動端上面尤爲安卓系統,流暢度真讓人堪憂。並且如今移動端基本上都支持canvas上下文2d,因此能用canvas實現的儘可能避免使用DOM。固然,若是是數量或簡單少的動畫,仍是用CSS3比較好。交互操做類的當下則非canvas莫屬。html

準備工做:

  首先是素材問題,圍繞商品的四周各拍幾張圖片,而後讓設計師從新修一下圖,最終分解成多張圖片素材。多則三四十張,小則十幾張,視狀況而定。要說明的是,我這裏用的只是替換圖片的方法實現仿3D旋轉,往後我會再寫一個僅需幾張圖片的3D全景瀏覽效果。前端

  如圖所示(是否是不少,哈哈,簡單的方法實現確定要犧牲點什麼的,下次再寫另外的方法吧):web

HTML+CSS:canvas

  

複製代碼
 1 <!DOCTYPE html>
 2 <html>
 3     <head>
 4         <meta charset="UTF-8">
 5         <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no" />
 6         <title>360度旋轉瀏覽</title>
 7         <style type="text/css">
 8             *{
 9                 margin: 0;
10                 padding: 0;
11             }
12             body,html{
13                 width: 100%;
14                 height: 100%;
15                 overflow: hidden;
16             }
17             .loading{
18                 position: absolute;
19                 width: 100%;
20                 height: 100%;
21                 left: 0;
22                 top: 0;
23                 background-color: #888888;
24                 z-index: 10;
25             }
26             .loading img{
27                 position: relative;
28                 width: 32px;
29                 height: 32px;
30                 left: 50%;
31                 top: 50%;
32                 margin-left: -16px;
33                 margin-top: -16px;
34             }
35             canvas{
36                 width: 100%;
37                 height: 100%;
38                 z-index: 100;
39             }
40         </style>
41     </head>
42     <body>
43         <div class="loading">
44             <img src="img/loading.gif"/>
45         </div>
46         <canvas id="canvas" width="750" height="1254">你的瀏覽器太老啦,換瀏覽器啦!</canvas>
47         <script src="js/zepto.min.js"></script>
48     </body>
49 </html>
複製代碼

JavaScript:

複製代碼
 1 var canvas = document.getElementById("canvas"),
 2                 DPR =  window.devicePixelRatio,//獲取設備的物理像素比
 3                 viewW = window.innerWidth,
 4                 viewH = window.innerHeight,
 5                 cansW = viewW*DPR,//放大canvas
 6                 cansH = viewH*DPR,
 7                 ctx = canvas.getContext("2d"),
 8                 imgArr = [],//圖片數組
 9                 curDeg = 1,//表明當前顯示的圖片下標
10                 imgTotal = 51,//圖片總數
11                 imgRatio = (447/1000), //圖片高寬比
12                 imgW = viewW*1.5,//圖寬
13                 imgH = imgW*imgRatio;//圖高
14                             
15             //重設canvas寬高
16                 //顯示的寬高
17             canvas.style.width = cansW + "px";
18             canvas.style.height = cansH + "px";
19                 //畫布寬高
20             canvas.width = cansW;
21             canvas.height = cansH;
22             //loading
23             $(function(){
24                 var baseURL = "img/",
25                     imgURL ="",
26                     imgObj = null,
27                     imgIndex = 1;
28                 //loading
29                 for(var i = 1;i <= imgTotal;i++){
30                     imgURL = baseURL + i + ".png";
31                     imgObj = new Image();
32                     imgObj.src = imgURL;
33                     //將全部圖片對象壓入一個數組,方便調用
34                     imgArr.push(imgObj);
35                     imgObj.onload = function(){
36                         imgIndex ++;
37                         if(imgIndex > 51){
38                             $(".loading").hide();
39                             //默認圖
40                             drawImg(0);
41                         }
42                     }
43                 }
44                     //手指觸摸起點
45                  var startPoint = 0,
46                      //滑動多長距離,這裏取(canvas寬/圖片總數的一半)
47                      //數值越大約靈敏
48                      distance = cansW/30;
49                 //開始
50                 $("#canvas").on({
51                     "touchstart":function(e){
52                         //記錄起始觸摸點
53                         startPoint = e.touches[0].clientX;
54                         //去掉默認事件,iPhone下可去除雙擊頁面默認跳動(翻頁)效果
55                         e.preventDefault();
56                     },
57                     "touchmove":function(e){
58                         var tempPoint = e.touches[0].clientX;
59                         //向右移動
60                         if((tempPoint - startPoint) > distance){
61                             drawImg(curDeg,"right");
62                             //符合距離條件移動後,將記錄點設到手指最新位置
63                             startPoint = tempPoint;
64                         }else if((tempPoint - startPoint) < -distance){//左
65                             drawImg(curDeg,"left");
66                             startPoint = tempPoint;
67                         }
68                         //禁止移動頁面
69                         e.preventDefault();
70                     }
71                 });
72             });
73             //繪圖
74             //參數:圖片對象下標,移動方向
75             function drawImg(n,type){
76                 if(type == "left"){
77                     if(curDeg > 0){
78                         curDeg--;
79                     }else{
80                         curDeg = 50;
81                     }    
82                 }else if(type == "right"){
83                     if(curDeg < 50){
84                         curDeg++;
85                     }else{
86                         curDeg = 0;
87                     }
88                 }
89                 ctx.clearRect(0,0,cansW,cansH);    
90                 //參數:圖片對象,X偏移量,Y偏移量,圖寬,圖高
91                 ctx.drawImage(imgArr[n],-(imgW-viewW)*0.5,(viewH-imgH)*0.5,imgW,imgH);
92             }
複製代碼

代碼說明:數組

  對於canvas,我還想說明的是,在移動端使用canvas畫布,必定要記得處理DPR,DPR全稱是DevicePixelRatio(設備像素比)。意思是設備上物理像素和設備獨立像素(device-independent pixels (dips))的比例。也就是一個設備獨立像素(能夠理解爲CSS中的1px)至關於多少個物理像素。假如DPR=2,那麼CSS中的1px就至關於設備物理像素的2px。可是在Canvas繪圖中,畫布大小跟可視區域大小是不同的。可視區域大小會根據DPR大小進行調整,可是畫布大小並不會。例如DPR=2,我在retina屏中設置canvas的可視寬高等於畫布寬高,那麼畫布裏的1px會在retina屏上以2px展現,因此會致使模糊現象。瀏覽器

  關於DPR和view的參考文章:移動前端開發之viewport的深刻理解ide

  因此爲了解決模糊問題,咱們須要根據DPR對畫布寬高進行調整,讓畫布大小等於物理像素大小。也就是把canvas的寬高變成對應的物理像素大小,而後把真正須要顯示的區域畫在屏幕位置,其他的隱藏掉。如圖所示:post

  另外,DPR經過window.devicePixelRatio便可獲取,基於webkit的瀏覽器都支持,IE不支持。動畫

  再者,這裏的滑動我使用了原生方法touchstart和touchmove觸摸事件,經過記錄手指起點以及終點的X軸座標大小判斷左右滑動。若是加入了zepto的TOUCH組件,則能夠直接使用swipeLeft和swipeRight觸發(拖動使用drag),從而改變相應的圖片。

關於繪圖:

  使用drawImage()方法繪圖,還要注意的是,必定要待圖片徹底加載後才能進行繪圖,不然會報錯。

DEMO地址:

  360度瀏覽示例

  請使用移動設備或者谷歌瀏覽器的手機模式打開。

相關文章
相關標籤/搜索