zoukankan      html  css  js  c++  java
  • 利用Canvas实现360度浏览

    前言:最近几个月来到新公司,主要从事移动端方面的开发,有时候也挺忙挺累的,于是就好一段时间没写博客了。其实自己在这几个月里,自己对canvas以及createjs和egret都有了一定程度上的认识与掌握了,所以有挺多东西想总结一下的。趁着今天广州下雪的日子,就写点东西吧,先从简单的demo开始吧。因为自己在走HTML5游戏方向,所以最近都在做小游戏。后续会再写关于canvas和createjs的系列文章吧,毕竟国内的资料比较少。一旦爱上了canvas,我便逐渐嫌弃DOM了。

    360度浏览效果

      利用最简单的多张图片,让产品实现360旋转浏览效果。以往用DOM来实现图片或者背景更换,是挺方便也容易,但是在移动端上面尤其安卓系统,流畅度真让人堪忧。而且现在移动端基本上都支持canvas上下文2d,所以能用canvas实现的尽量避免使用DOM。当然,如果是数量或简单少的动画,还是用CSS3比较好。交互操作类的当下则非canvas莫属。

    准备工作:

      首先是素材问题,围绕商品的四周各拍几张图片,然后让设计师重新修一下图,最终分解成多张图片素材。多则三四十张,小则十几张,视情况而定。要说明的是,我这里用的只是替换图片的方法实现仿3D旋转,日后我会再写一个仅需几张图片的3D全景浏览效果。

      如图所示(是不是很多,哈哈,简单的方法实现肯定要牺牲点什么的,下次再写另外的方法吧):

    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的宽高变成对应的物理像素大小,然后把真正需要显示的区域画在屏幕位置,其余的隐藏掉。如图所示:

      另外,DPR通过window.devicePixelRatio即可获取,基于webkit的浏览器都支持,IE不支持。

      再者,这里的滑动我使用了原生方法touchstart和touchmove触摸事件,通过记录手指起点以及终点的X轴坐标大小判断左右滑动。如果加入了zepto的TOUCH组件,则可以直接使用swipeLeft和swipeRight触发(拖动使用drag),从而改变相应的图片。

    关于绘图:

      使用drawImage()方法绘图,还要注意的是,一定要待图片完全加载后才能进行绘图,否则会报错。

    DEMO地址:

      360度浏览示例

      请使用移动设备或者谷歌浏览器的手机模式打开。

  • 相关阅读:
    Codeforces 631A Interview【模拟水题】
    Codeforces 651E Table Compression【并查集】
    Codeforces 651D Image Preview【二分+枚举】
    Codeforces 651C Watchmen【模拟】
    Codeforces 651B Beautiful Paintings【贪心】
    18.06.26 16年期末10:游览规划
    18.06.25 POJ4129 16年期末09:变换的迷宫
    18.06.25 POJ4150 16年期末07:上机
    18.06.25 16年期末06 42点
    18.06.25 16年期末01-05集合
  • 原文地址:https://www.cnblogs.com/chengguanhui/p/5155440.html
Copyright © 2011-2022 走看看