专栏名称: 蚂蚁金服ProtoTeam
数据前端团队
目录
相关文章推荐
宝山消防支队  ·  以案为例 |《油锅起火怎么办?》 ·  昨天  
IT服务圈儿  ·  45K*16薪,进字节了! ·  昨天  
前端早读课  ·  【第3459期】两款 AI 编程助手 ... ·  昨天  
前端早读课  ·  【第3458期】React ... ·  2 天前  
51好读  ›  专栏  ›  蚂蚁金服ProtoTeam

写一个可拓展的360度产品旋转插件

蚂蚁金服ProtoTeam  · 掘金  · 前端  · 2017-12-08 02:28

正文

1.前言

做过电商的朋友应该比较熟悉,当我们在介绍一个实体产品的时候必不可少的会有这个产品的图片,这是用户对这个产品的最直观了解,从以前的包括现在的电商网站来看,产品详情页里面产品的图片一般都是占一大部分,而且一般的排版方式都是图片从上往下排来展示产品的各个角度的图片或者使用轮播图(参照淘宝京东等),因为这个是最简单的能使用户仔细了解产品的外观的方法,所以目前几乎所有的电商都会加入这个环节。当然我们在这里并不是为了替换掉这种展示方式,而是我们增加一个能让用户更方便去了解产品实际全貌的方式,而且在排版上做到只占一张图片的位置。 我们先来看看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代码


大家可以放大来看这张图,此插件代码共有三个对象: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是可以设置的变量,可以控制我们旋转时的敏感度,也可以说旋转快慢吧)







请到「今天看啥」查看全文