利用Canvas實現360度瀏覽

jopen 8年前發布 | 16K 次閱讀 canvas

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

360度瀏覽效果

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

準備工作:

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

如圖所示(是不是很多,哈哈,簡單的方法實現肯定要犧牲點什么的,下次再寫另外的方法吧):

利用Canvas實現360度瀏覽

HTML+CSS:

 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的深入理解

所以為了解決模糊問題,我們需要根據DPR對畫布寬高進行調整,讓畫布大小等于物理像素大小。也就是把canvas的寬高變成對應的物理像素大小,然后把真正需要顯示的區域畫在屏幕位置,其余的隱藏掉。如圖所示:

利用Canvas實現360度瀏覽

另外,DPR通過window.devicePixelRatio即可獲取,基于webkit的瀏覽器都支持,IE不支持。

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

關于繪圖:

使用drawImage()方法繪圖,還要注意的是,一定要待圖片完全加載后才能進行繪圖,否則會報錯。

DEMO地址:

360度瀏覽示例

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

來自: http://www.cnblogs.com/chengguanhui/p/5155440.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!