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

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是可以设置的变量,可以控制我们旋转时的敏感度,也可以说旋转快慢吧)

之后我们判断是向左还是向右旋转

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



转载于:https://juejin.im/post/5a28985f6fb9a044fd11a5ad

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值