资讯专栏INFORMATION COLUMN

360°产品展示

liukai90 / 2518人阅读

摘要:是一款可以对产品图片进行度全方位旋转展示的插件。动画帧通过切换的速度,默认值为毫秒。动画帧改编之后的回调函数以当前帧和总帧数为参数。返回对象的总的动画帧数。显示对象的元素节点。

Circlr是一款可以对产品图片进行360度全方位旋转展示的插件。Circlr通过按一定角度规律拍摄的产品图片,制作出可以使用鼠标拖动、鼠标滚轮和移动触摸来进行图片逐帧旋转的效果。比先前的Rollerblade,动画顺畅了许多,也更易于控制,该插件非常适合于商品的展示。它的特点有:
1、支持水平或垂直方向旋转。
2、支持移动触摸事件。
3、支持滚动事件。
4、图片预加载处理。
5、可以反向和循环旋转图片。

页面引用核心jquery.js和circlr.js文件


对于circlr.js可以去自行下载
原文件展示给大家,以供预览:

// Circlr © 2014-2015 Andrey Polischuk
// github.com/andrepolischuk/circlr

!function() {

  "use strict";

  /**
   * Mutable parameters
   */

  var mutable = [
    "vertical",
    "reverse",
    "cycle",
    "speed",
    "playSpeed"
  ];

  /**
   * Initialize module
   * @param {Object} el
   * @param {Object} options
   */

  function Circlr(options) {

    /**
     * Mouse events enabled
     */

    options.mouse = options.mouse || true;

    /**
     * Scroll events enabled
     */

    options.scroll = options.scroll || false;

    /**
     * Orientation
     */

    options.vertical = options.vertical || false;

    /**
     * Turning reverse
     */

    options.reverse = options.reverse || false;

    /**
     * Turning cycle
     */

    options.cycle = options.cycle || true;

    /**
     * Start frame
     */

    options.start = options.start || 0;

    /**
     * Turn speed (ms)
     */

    options.speed = options.speed || 50;

    /**
     * Autoplay
     */

    var autoplay = options.autoplay || false;

    /**
     * Play speed (ms)
     */

    options.playSpeed = options.playSpeed || 100;

    /**
     * DOM element
     */

    var el = this.el = options.element;

    /**
     * Exclude duplication
     */

    el.setAttribute("data-circlr", true);

    /**
     * DOM loader
     */

    var loader = options.loader ? document.getElementById(options.loader) : undefined;

    /**
     * Frames length
     */

    var length = this.length = el.getElementsByTagName("img").length;

    /**
     * Frames area height
     */

    var height = options.height || undefined;

    /**
     * Frames area width
     */

    var width = options.width || undefined;

    /**
     * Move enable
     */

    var movable = false;

    /**
     * Loaded images length
     */

    var loaded = [];

    /**
     * Not loaded length
     */

    var errored = [];

    /**
     * Current frame
     */

    var current;

    /**
     * Prevous options
     */

    var pre   = {};

    pre.Y     = null;
    pre.X     = null;
    pre.frame = 0;

    /**
     * Callbacks
     */

    var callbacks = {};

    // all images loaded callback
    callbacks.ready = options.ready || undefined;

    // turn callback
    callbacks.change = options.change || undefined;

    /**
     * Scroll events
     */

    var scrollEvents = [
      "wheel",
      "mousewheel",
      "scroll",
      "DOMMouseScroll"
    ];

    /**
     * Add event listener
     * @param {Object} target
     * @param {String} event
     * @param {Function} fn
     * @api private
     */

    function onEventListener(target, event, fn) {

      if (target.addEventListener) {
        target.addEventListener(event, fn, false);
      } else {
        target.attachEvent("on" + event, function() {
          fn.call(target, window.event);
        });
      }

    }

    /**
     * Prevent default
     * @param {Object} e
     */

    function preventDefault(e) {

      if (e.preventDefault) {
        e.preventDefault();
      } else {
        e.returnValue = false;
      }

    }

    /**
     * Pre moving event
     * @param {Object} e
     * @api private
     */

    function preMove(e) {

      autoplay = false;

      preventDefault(e);
      e = e.type === "touchstart" ? e.changedTouches[0] : e;

      movable = true;

      if (options.vertical) {
        pre.Y = e.clientY - el.offsetTop;
      } else {
        pre.X = e.clientX - el.offsetLeft;
      }

    }

    /**
     * Normalize current frame
     * @param  {Number} cur
     * @return {Number}
     * @api private
     */

    function normalize(cur) {

      if (cur < 0) {
        cur = options.cycle ? cur + length : 0;
      } else if (cur > length - 1) {
        cur = options.cycle ? cur - length : length - 1;
      }

      return cur;

    }

    /**
     * Moving event
     * @param {Object} e
     * @api private
     */

    function isMove(e) {

      if (movable) {

        preventDefault(e);
        e = e.type === "touchmove" ? e.changedTouches[0] : e;

        // current offset (px)
        var offset = (options.vertical) ? ((e.clientY - el.offsetTop) - pre.Y) : ((e.clientX - el.offsetLeft) - pre.X);
        offset = options.reverse ? -offset : offset;

        // frame step (px)
        var step = width / length;

        // prevous frame
        var previous = current;

        // current offset (frame)
        offset = Math.floor(offset / step);

        if (offset !== current) {

          current = normalize(pre.frame + offset);

          if (previous !== current) {

            // show current frame
            el.getElementsByTagName("img")[previous].style.display = "none";
            el.getElementsByTagName("img")[current].style.display = "block";

            if (typeof callbacks.change === "function") {
              callbacks.change(current, length);
            }

          }

        }

      }

    }

    /**
     * Post moving event
     * @param {Object} e
     * @api private
     */

    function stopMove(e) {

      preventDefault(e);

      movable   = false;
      pre.frame = current;

    }

    /**
     * Moving via scroll
     * @param {Object} e
     * @api private
     */

    function scrollMove(e) {

      autoplay = false;

      preventDefault(e);

      // scroll delta
      var delta = e.deltaY || e.detail || (-e.wheelDelta);
      delta = delta / Math.abs(delta);
      delta = options.reverse ? -delta : delta;

      current = normalize(current + delta);

      // show current frame
      el.getElementsByTagName("img")[pre.frame].style.display = "none";
      el.getElementsByTagName("img")[current].style.display = "block";

      pre.frame = current;

      if (typeof callbacks.change === "function") {
        callbacks.change(current, length);
      }

    }

    /**
     * Initialize events after success images loading
     * @api private
     */

    function initEvents() {

      // loader hide
      if (loader) {
        loader.style.display = "none";
      }

      if (errored.length === 0) {

        var start = normalize(options.start);

        // all images loaded
        el.getElementsByTagName("img")[start].style.display = "block";
        current = start;

        el.style.position   = "relative";
        el.style.width      = "100%";

        if ("ontouchstart" in window || "onmsgesturechange" in window) {

            if (options.mouse || options.scroll) {
              onEventListener(el, "touchstart", preMove);
              onEventListener(el, "touchmove", isMove);
              onEventListener(el, "touchend", stopMove);
            }

        } else {

          if (options.mouse) {
            onEventListener(el, "mousedown", preMove);
            onEventListener(el, "mousemove", isMove);
            onEventListener(document, "mouseup", stopMove);
          }

          if (options.scroll) {
            for (var e = 0; e < scrollEvents.length; e++) {
              if ("on" + scrollEvents[e] in window) {
                onEventListener(el, scrollEvents[e], scrollMove);
                break;
              }
            }
          }

        }

        if (autoplay) {
          play();
        }

      }

      if (typeof callbacks.ready === "function") {
        callbacks.ready(errored);
      }

    }

    /**
     * Initialize images events
     * @param {Object} img
     */

    function loadImagesEvents(img) {

      img.onload = function() {

        loaded.push(this.src);

        // show first frame when all images loaded
        if (loaded.length + errored.length === length) {
          initEvents();
        }

      };

      img.onerror = function() {

        errored.push(this.src);

        // show first frame when images loaded
        if (loaded.length + errored.length === length) {
          initEvents();
        }

      };

      img.onreadystatechange = function() {
        this.onload();
      };

    }

    /**
     * Load Object images
     * @api private
     */

    function loadImages() {

      // adding elements
      var img;

      // show loader
      if (loader) {
        loader.style.display = "block";
      }

      for (var i = 0; i < length; i++) {

        // get object
        img = el.getElementsByTagName("img")[i];

        // set object style
        img.style.display      = "none";
        img.style.width        = "100%";

        // set object options
        img.setAttribute("src", img.getAttribute("data-src"));
        img.setAttribute("data-index", i);
        img.removeAttribute("data-src");

        loadImagesEvents(img);

      }

      // check elements sizes
      height = height || el.clientHeight;
      width  = width || el.clientWidth;

    }

    /**
     * Initialize loading
     */

    loadImages();

    /**
     * Change current frame
     * @param  {Number} i
     * @api private
     */

    function setFrame(i) {

      el.getElementsByTagName("img")[current].style.display = "none";
      el.getElementsByTagName("img")[i].style.display = "block";

      pre.frame = current = i;

    }

    /**
     * Turn to specific frame
     * @param  {Number} i
     * @api public
     */

    var turn = this.turn = function(i) {

      i = normalize(i);
      autoplay = true;

      (function turnInterval() {

        if (i !== current && autoplay) {

          setFrame(normalize(i < current ? current - 1 : current + 1));
          setTimeout(turnInterval, typeof i === "undefined" ? options.playSpeed : options.speed);

        } else if (i === current) {

          pre.frame = current = i;
          autoplay = false;

          if (typeof callbacks.change === "function") {
            callbacks.change(current, length);
          }

        }

      })();

    };

    /**
     * Go to specific frame
     * @param  {Number} i
     * @api public
     */

    this.go = function(i) {

      if (i !== current) {

        setFrame(i);

        if (typeof callbacks.change === "function") {
          callbacks.change(current, length);
        }

      }

    };

    /**
     * Play sequence
     * @api public
     */

    var play = this.play = function() {
      autoplay = true;
      turn();
    };

    /**
     * Stop sequence playng
     * @api public
     */

    this.stop = function() {
      autoplay = false;
    };

    /**
     * Show object
     * @api public
     */

    this.show = function() {
      el.style.display = "block";
    };

    /**
     * Hide object
     * @api public
     */

    this.hide = function() {
      el.style.display = "none";
    };

    /**
     * Change Object options
     * @param {Object} options
     * @api public
     */

    this.set = function(set) {
      for (var i = 0, key; i < mutable.length; i++) {
        key = mutable[i];
        options[key] = typeof set[key] !== "undefined" ? set[key] : options[key];
      }
    };

  }

  /**
   * Example creator
   */

  function Creator(element, options) {

    element = document.getElementById(element);

    if (element.getAttribute("data-circlr")) {
      return;
    }

    options = options || {};
    options.element = element;

    return new Circlr(options);

  }

  /**
   * Module exports
   */

  if (typeof define === "function" && define.amd) {

    define([], function() {
      return Creator;
    });

  } else if (typeof module !== "undefined" && module.exports) {

    module.exports = Creator;

  } else {

    this.circlr = Creator;

  }

}.call(this);

circle插件的运用很简单:
var crl = circlr(element, options);
// element:放置图片的容器元素的ID。
// options:参数对象。
配置参数
mouse:是否通过鼠标进行图片旋转,默认值为true。
scroll:是否通过scroll进行图片旋转,默认值为false。
vertical:是否在垂直方向上移动鼠标时旋转图片,默认值为false。
reverse:是否反转方向,默认值为false。
cycle:是否循环旋转图片,默认值为true。
start:开始动画帧,默认值为0。
speed:动画帧通过circlr.turn(i)切换的速度,默认值为50毫秒。
autoplay:是否自动进行图片360度旋转播放,默认值为false。
playSpeed:动画序列的播放速度,默认值为100毫秒。
loader:预加载DOM元素的ID。
ready:图片加载完成后的回调函数。
change:动画帧改编之后的回调函数(以当前帧和总帧数为参数)。
方法
crl.el:返回对象的DOM元素节点。
crl.length:返回对象的总的动画帧数。
crl.turn(i):动画旋转到第i帧。
crl.go(i):动画跳转到第i帧。
crl.play():开始动画序列的播放。
crl.stop():停止动画播放。
crl.hide():隐藏对象的DOM元素节点。
crl.show():显示对象的DOM元素节点。
crl.set(options):在插件初始化之后改变对象的参数:vertical 、reverse、cycle、speed、playSpeed
浏览器兼容
Internet Explorer 7+
Chrome
Safari
Firefox
Opera
以下基于circle的插件

circlr-config.js的源码

/*
 *     @author: 21-sun
 *     @version 1.0.0
 *     @date 2017-05-10
*/
;
(function($){
    
    var defaults = {
        ID : "",
        filePath : "",  // 小图路径:本地
        imgFormat : ".png",  // 图片格式
        len : 50, // 张数配置
        scroll: true, //滚动发滚轮自动旋转
        playSpeed : 400,  // 播放速度
        autoplay : true, // 是否自动播放
        delay : 3 // 不操作后开始自传
        };
    
    $.fn.show360 = function(options, undefined){
        
        var opts = $.extend({}, defaults, options, undefined);
        
        obj = $(this);
        
        var timer = null;
        var isLoaded = false; //判断图片是否加载完成
        var crl = null;
        
        var show = {
            init : function (){
                this.create();
                this.crlFn();
                
                if(opts.autoplay){
                    this.play();
                    this.stop();
                    }
                },
            create : function (){
                var html = "";
                html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; html += "
"; obj.html(html); var step = 0; var imgList = ""; for(var i = 0; i < opts.len; i ++){ imgList += ""; } $(".img-wrap").html(imgList); }, crlFn : function(){ crl = circlr("circlr-" + opts.ID, { scroll: opts.scroll, loader: "loading-" + opts.ID, autoplay : opts.autoplay, playSpeed: opts.playSpeed }); }, play : function(){ $("#circlr-" + opts.ID).on("touchend || mouseup", function() { timer = setTimeout(function (){ crl.play(); }, opts.delay * 1000); }); }, stop : function(){ $("#circlr-" + opts.ID).on("touchstart || mousedown", function() { if(timer !== null){ clearTimeout(timer); timer = null; } crl.stop(); }); } }; return show.init(); }; })(jQuery);

html页面就更简单了:





test







页面中引入show.css
源码:

#effect_4{
    height: 100%;
    width: 100%;
}
#effect_4 .loading-center{
    width: 100%;
    height: 100%;
    position: relative;
}
#effect_4 .loading-center-absolute {
    position: absolute;
    left: 50%;
    top: 50%;
    height: 50px;
    width: 50px;
    margin-top: -25px;
    margin-left: -25px;
   -ms-transform: rotate(45deg); 
       -webkit-transform: rotate(45deg);
    transform: rotate(45deg); 
    -webkit-animation: loading-center-absolute 1.5s infinite;
    animation: loading-center-absolute 1.5s infinite;

}
#effect_4 .object{
    width: 25px;
    height: 25px;
    background-color: #FFF;
    float: left;
    
}

#effect_4 .object_one {
    -webkit-animation: object_one_4 1.5s infinite;
    animation: object_one_4 1.5s infinite;
    }
#effect_4 .object_two {
    -webkit-animation: object_two_4 1.5s infinite;
    animation: object_two_4 1.5s infinite;
    }
#effect_4 .object_three {
    -webkit-animation: object_three_4 1.5s infinite;
    animation: object_three_4 1.5s infinite;
    }
#effect_4 .object_four {
    -webkit-animation: object_four_4 1.5s infinite;
    animation: object_four_4 1.5s infinite;
    }

@-webkit-keyframes loading-center-absolute {
  100% { -webkit-transform: rotate(-45deg); }

}

@keyframes loading-center-absolute {
  100% { 
    transform:  rotate(-45deg);
    -webkit-transform:  rotate(-45deg);
  }
}

@-webkit-keyframes object_one_4 {
  25% { -webkit-transform: translate(0,-50px) rotate(-180deg); }
  100% { -webkit-transform: translate(0,0) rotate(-180deg); }

}

@keyframes object_one_4 {
  25% { 
    transform: translate(0,-50px) rotate(-180deg);
    -webkit-transform: translate(0,-50px) rotate(-180deg);
  } 
  100% { 
    transform: translate(0,0) rotate(-180deg);
    -webkit-transform: translate(0,0) rotate(-180deg);
  }
}

@-webkit-keyframes object_two_4 {
  25% { -webkit-transform: translate(50px,0) rotate(-180deg); }
  100% { -webkit-transform: translate(0,0) rotate(-180deg); }
}

@keyframes object_two_4 {
  25% { 
    transform: translate(50px,0) rotate(-180deg);
    -webkit-transform: translate(50px,0) rotate(-180deg);
  } 
  100% { 
    transform: translate(0,0) rotate(-180deg);
    -webkit-transform: translate(0,0) rotate(-180deg);
  }
}

@-webkit-keyframes object_three_4 {
  25% { -webkit-transform: translate(-50px,0) rotate(-180deg); }
  100% { -webkit-transform: translate(0,0) rotate(-180deg); }
}

@keyframes object_three_4 {
  25% { 
    transform:  translate(-50px,0) rotate(-180deg);
    -webkit-transform:  translate(-50px,0) rotate(-180deg);
  } 
  100% { 
    transform: translate(0,0) rotate(-180deg);
    -webkit-transform: rtranslate(0,0) rotate(-180deg);
  }
}

@-webkit-keyframes object_four_4 {
  25% { -webkit-transform: translate(0,50px) rotate(-180deg); }
  100% { -webkit-transform: translate(0,0) rotate(-180deg); }
}

@keyframes object_four_4 {
  25% { 
    transform: translate(0,50px) rotate(-180deg); 
    -webkit-transform: translate(0,50px) rotate(-180deg);  
  } 
  100% { 
    transform: translate(0,0) rotate(-180deg);
    -webkit-transform: translate(0,0) rotate(-180deg);
  }
}

这样就ok了,有兴趣,可以尝试一下奥。
如果文章有问题,请大家积极指正,共同进步。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/112001.html

相关文章

  • 创建一个360°视图 第一部分:概述&数据分析

    摘要:第一部分包括一个视图示例以及在构建视图时需要考虑的要点概述,第二部分将介绍一个示例数据模型的实现,第三部分将深入探讨如何将数据迁移到的机制。让我们假设你已经有创建一个视图的想法了。 本文源地址:http://www.mongoing.com/archives/884 本系列的三篇博客将会提供一个关于在MongoDB上构建360°视图的介绍。第一部分包括一个360°视图示例以及在构建...

    SegmentFault 评论0 收藏0
  • 创建一个360°视图 第一部分:概述&数据分析

    摘要:第一部分包括一个视图示例以及在构建视图时需要考虑的要点概述,第二部分将介绍一个示例数据模型的实现,第三部分将深入探讨如何将数据迁移到的机制。让我们假设你已经有创建一个视图的想法了。 本文源地址:http://www.mongoing.com/archives/884 本系列的三篇博客将会提供一个关于在MongoDB上构建360°视图的介绍。第一部分包括一个360°视图示例以及在构建...

    joywek 评论0 收藏0
  • 创建一个360°视图 第一部分:概述&数据分析

    摘要:第一部分包括一个视图示例以及在构建视图时需要考虑的要点概述,第二部分将介绍一个示例数据模型的实现,第三部分将深入探讨如何将数据迁移到的机制。让我们假设你已经有创建一个视图的想法了。 本文源地址:http://www.mongoing.com/archives/884 本系列的三篇博客将会提供一个关于在MongoDB上构建360°视图的介绍。第一部分包括一个360°视图示例以及在构建...

    winterdawn 评论0 收藏0
  • 找货神器(360浏览器抢货神器怎么用?)

    360浏览器抢货神器怎么用?打开360极速浏览器,抢货神器的主页面也会随同打开。页面下方有抢货神器为用户提供的360购物小蜜的收藏数据,根据网友的喜爱罗列出最受欢迎的手机数码产品、最受欢迎的女装、最受欢迎的鞋包配饰。用户只需点击任意链接就能在快速进入天猫商品页面。据透露,使用360极速浏览器抢货神器进入天猫页面仅需0.42秒,绝对保证了用户的抢购成功率。  在用户快速进入抢购商品页面之后,商品价格...

    不知名网友 评论0 收藏2224
  • Android之应用市场排行榜、上架、首发

    摘要:文章大纲一应用市场排行榜介绍二应用市场上架介绍三应用市场首发介绍四参考文档一应用市场排行榜介绍艾媒咨询权威发布中国移动应用商店市场监测报告。应用上架必须要提交阿里的保证函。应用首发申请提交后,工作人员将在个工作文章大纲 一、应用市场排行榜介绍二、应用市场上架介绍三、应用市场首发介绍四、参考文档   一、应用市场排行榜介绍   iiMedia Research(艾媒咨询)权威发布...

    岳光 评论0 收藏0
  • 360前端星学习笔记-HTML

    摘要:前端与一枚大三学生,非常感谢前端星计划,在这里学习了很多,非常幸运获得的校招实习,非常感谢面试我的王峰老师和卢岳文老师总的来说,这天的学习,让我坚定了走前端这条路。使用在模式下可以使元素水平居中,但在模式下却会失效。 前端与HTML 一枚大三学生,非常感谢360前端星计划,在这里学习了很多,非常幸运获得360的校招实习offer~,非常感谢面试我的王峰老师和卢岳文老师!总的来说,这7天...

    PAMPANG 评论0 收藏0

发表评论

0条评论

liukai90

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<