threesixty.min.js 和jquery.threesixty.js使用总结----实现360度展示
最近公司做一个项目需要360度展示汽车的外观,就用到了threesixty.min.js,自己总结一下使用方法:
treesixty.min.js 源码:
/*! threesixty-slider 2015-01-06 verison 2.0.5 */ /* http://github.com/vml-webdev/threesixty-slider.git */ !function (a) { "use strict"; a.ThreeSixty = function (b, c) { var d, e = this, f = []; e.$el = a(b), e.el = b, e.$el.data("ThreeSixty", e), e.init = function () { d = a.extend({}, a.ThreeSixty.defaultOptions, c), d.disableSpin && (d.currentFrame = 1, d.endFrame = 1), e.initProgress(), e.loadImages() }, e.resize = function () { }, e.initProgress = function () { e.$el.css({ width: d.width, height: d.height, "background-image": "none !important" }), d.styles && e.$el.css(d.styles), e.responsive(), e.$el.find(d.progress).css({marginTop: d.height / 2 - 15 + "px"}), e.$el.find(d.progress).fadeIn("slow"), e.$el.find(d.imgList).hide() }, e.loadImages = function () { var b, c, g, h; b = document.createElement("li"), h = d.zeroBased ? 0 : 1, c = d.imgArray ? d.imgArray[d.loadedImages] : d.domain + d.imagePath + d.filePrefix + e.zeroPad(d.loadedImages + h) + d.ext + (e.browser.isIE() ? "?" + (new Date).getTime() : ""), g = a("<img>").attr("src", c).addClass("previous-image").appendTo(b), f.push(g), e.$el.find(d.imgList).append(b), a(g).load(function () { e.imageLoaded() }) }, e.imageLoaded = function () { d.loadedImages += 1, a(d.progress + " span").text(Math.floor(100 * (d.loadedImages / d.totalFrames)) + "%"), d.loadedImages >= d.totalFrames ? (d.disableSpin && f[0].removeClass("previous-image").addClass("current-image"), a(d.progress).fadeOut("slow", function () { a(this).hide(), e.showImages(), e.showNavigation() })) : e.loadImages() }, e.showImages = function () { e.$el.find(".txtC").fadeIn(), e.$el.find(d.imgList).fadeIn(), e.ready = !0, d.ready = !0, d.drag && e.initEvents(), e.refresh(), e.initPlugins(), d.onReady(), setTimeout(function () { e.responsive() }, 50) }, e.initPlugins = function () { a.each(d.plugins, function (b, c) { if ("function" != typeof a[c])throw new Error(c + " not available."); a[c].call(e, e.$el, d) }) }, e.showNavigation = function () { if (d.navigation && !d.navigation_init) { var b, c, f, g; b = a("<div/>").attr("class", "nav_bar"), c = a("<a/>").attr({ href: "#", "class": "nav_bar_next" }).html("next"), f = a("<a/>").attr({ href: "#", "class": "nav_bar_previous" }).html("previous"), g = a("<a/>").attr({ href: "#", "class": "nav_bar_play" }).html("play"), b.append(f), b.append(g), b.append(c), e.$el.prepend(b), c.bind("mousedown touchstart", e.next), f.bind("mousedown touchstart", e.previous), g.bind("mousedown touchstart", e.play_stop), d.navigation_init = !0 } }, e.play_stop = function (b) { b.preventDefault(), d.autoplay ? (d.autoplay = !1, a(b.currentTarget).removeClass("nav_bar_stop").addClass("nav_bar_play"), clearInterval(d.play), d.play = null) : (d.autoplay = !0, d.play = setInterval(e.moveToNextFrame, d.playSpeed), a(b.currentTarget).removeClass("nav_bar_play").addClass("nav_bar_stop")) }, e.next = function (a) { a && a.preventDefault(), d.endFrame -= 5, e.refresh() }, e.previous = function (a) { a && a.preventDefault(), d.endFrame += 5, e.refresh() }, e.play = function (a) { var b = a || d.playSpeed; d.autoplay || (d.autoplay = !0, d.play = setInterval(e.moveToNextFrame, b)) }, e.stop = function () { d.autoplay && (d.autoplay = !1, clearInterval(d.play), d.play = null) }, e.moveToNextFrame = function () { 1 === d.autoplayDirection ? d.endFrame -= 1 : d.endFrame += 1, e.refresh() }, e.gotoAndPlay = function (a) { if (d.disableWrap)d.endFrame = a, e.refresh(); else { var b = Math.ceil(d.endFrame / d.totalFrames); 0 === b && (b = 1); var c = b > 1 ? d.endFrame - (b - 1) * d.totalFrames : d.endFrame, f = d.totalFrames - c, g = 0; g = a - c > 0 ? a - c < c + (d.totalFrames - a) ? d.endFrame + (a - c) : d.endFrame - (c + (d.totalFrames - a)) : f + a > c - a ? d.endFrame - (c - a) : d.endFrame + (f + a), c !== a && (d.endFrame = g, e.refresh()) } }, e.initEvents = function () { e.$el.bind("mousedown touchstart touchmove touchend mousemove click", function (a) { a.preventDefault(), "mousedown" === a.type && 1 === a.which || "touchstart" === a.type ? (d.pointerStartPosX = e.getPointerEvent(a).pageX, d.dragging = !0) : "touchmove" === a.type ? e.trackPointer(a) : "touchend" === a.type && (d.dragging = !1) }), a(document).bind("mouseup", function () { d.dragging = !1, a(this).css("cursor", "none") }), a(window).bind("resize", function () { e.responsive() }), a(document).bind("mousemove", function (a) { d.dragging ? (a.preventDefault(), !e.browser.isIE && d.showCursor && e.$el.css("cursor", "url(assets/images/hand_closed.png), auto")) : !e.browser.isIE && d.showCursor && e.$el.css("cursor", "url(assets/images/hand_open.png), auto"), e.trackPointer(a) }), a(window).resize(function () { e.resize() }) }, e.getPointerEvent = function (a) { return a.originalEvent.targetTouches ? a.originalEvent.targetTouches[0] : a }, e.trackPointer = function (a) { d.ready && d.dragging && (d.pointerEndPosX = e.getPointerEvent(a).pageX, d.monitorStartTime < (new Date).getTime() - d.monitorInt && (d.pointerDistance = d.pointerEndPosX - d.pointerStartPosX, d.endFrame = d.pointerDistance > 0 ? d.currentFrame + Math.ceil((d.totalFrames - 1) * d.speedMultiplier * (d.pointerDistance / e.$el.width())) : d.currentFrame + Math.floor((d.totalFrames - 1) * d.speedMultiplier * (d.pointerDistance / e.$el.width())), d.disableWrap && (d.endFrame = Math.min(d.totalFrames - (d.zeroBased ? 1 : 0), d.endFrame), d.endFrame = Math.max(d.zeroBased ? 0 : 1, d.endFrame)), e.refresh(), d.monitorStartTime = (new Date).getTime(), d.pointerStartPosX = e.getPointerEvent(a).pageX)) }, e.refresh = function () { 0 === d.ticker && (d.ticker = setInterval(e.render, Math.round(1e3 / d.framerate))) }, e.render = function () { var a; d.currentFrame !== d.endFrame ? (a = d.endFrame < d.currentFrame ? Math.floor(.1 * (d.endFrame - d.currentFrame)) : Math.ceil(.1 * (d.endFrame - d.currentFrame)), e.hidePreviousFrame(), d.currentFrame += a, e.showCurrentFrame(), e.$el.trigger("frameIndexChanged", [e.getNormalizedCurrentFrame(), d.totalFrames])) : (window.clearInterval(d.ticker), d.ticker = 0) }, e.hidePreviousFrame = function () { f[e.getNormalizedCurrentFrame()].removeClass("current-image").addClass("previous-image") }, e.showCurrentFrame = function () { f[e.getNormalizedCurrentFrame()].removeClass("previous-image").addClass("current-image") }, e.getNormalizedCurrentFrame = function () { var a, b; return d.disableWrap ? (a = Math.min(d.currentFrame, d.totalFrames - (d.zeroBased ? 1 : 0)), b = Math.min(d.endFrame, d.totalFrames - (d.zeroBased ? 1 : 0)), a = Math.max(a, d.zeroBased ? 0 : 1), b = Math.max(b, d.zeroBased ? 0 : 1), d.currentFrame = a, d.endFrame = b) : (a = Math.ceil(d.currentFrame % d.totalFrames), 0 > a && (a += d.totalFrames - (d.zeroBased ? 1 : 0))), a }, e.getCurrentFrame = function () { return d.currentFrame }, e.responsive = function () { d.responsive && e.$el.css({height: e.$el.find(".current-image").first().css("height"), width: "100%"}) }, e.zeroPad = function (a) { function b(a, b) { var c = a.toString(); if (d.zeroPadding)for (; c.length < b;)c = "0" + c; return c } var c = Math.log(d.totalFrames) / Math.LN10, e = 1e3, f = Math.round(c * e) / e, g = Math.floor(f) + 1; return b(a, g) }, e.browser = {}, e.browser.isIE = function () { var a = -1; if ("Microsoft Internet Explorer" === navigator.appName) { var b = navigator.userAgent, c = new RegExp("MSIE ([0-9]{1,}[\\.0-9]{0,})"); null !== c.exec(b) && (a = parseFloat(RegExp.$1)) } return -1 !== a }, e.getConfig = function () { return d }, a.ThreeSixty.defaultOptions = { dragging: !1, ready: !1, pointerStartPosX: 0, pointerEndPosX: 0, pointerDistance: 0, monitorStartTime: 0, monitorInt: 10, ticker: 0, speedMultiplier: 7, totalFrames: 180, currentFrame: 0, endFrame: 0, loadedImages: 0, framerate: 60, domains: null, domain: "", parallel: !1, queueAmount: 8, idle: 0, filePrefix: "", ext: "png", height: "300px", width: "300px", styles: {}, navigation: !1, autoplay: !1, autoplayDirection: 1, disableSpin: !1, disableWrap: !1, responsive: !1, zeroPadding: !1, zeroBased: !1, plugins: [], showCursor: !1, drag: !0, onReady: function () { }, imgList: ".threesixty_images", imgArray: null, playSpeed: 100 }, e.init() }, a.fn.ThreeSixty = function (b) { return Object.create(new a.ThreeSixty(this, b)) } }(jQuery), "function" != typeof Object.create && (Object.create = function (a) { "use strict"; function b() { } return b.prototype = a, new b });
treesixty.css 源码
.threesixty { position: relative; overflow: hidden; margin: 0 auto; } .threesixty .threesixty_images { display: none; list-style: none; margin: 0; padding: 0; } .threesixty .threesixty_images img { position: absolute; top: 0; width: 100%; height: auto; } .threesixty .threesixty_images img.previous-image { visibility: hidden; width: 0; } .threesixty .threesixty_images img.current-image { visibility: visible; width: 100%; } .threesixty .spinner { width: 60px; display: block; margin: 0 auto; height: 30px; background: #333; background: rgba(0, 0, 0, 0.7); -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .threesixty .spinner span { font-family: Arial, "MS Trebuchet", sans-serif; font-size: 12px; font-weight: bolder; color: #FFF; text-align: center; line-height: 30px; display: block; } .threesixty .nav_bar { position: absolute; top: 10px; right: 10px; z-index: 11; } .threesixty .nav_bar a { display: block; width: 32px; height: 32px; float: left; text-indent: -99999px; } .threesixty .nav_bar a.nav_bar_play { background-position: 0 0 !important; } .threesixty .nav_bar a.nav_bar_previous { background-position: 0 -73px !important; } .threesixty .nav_bar a.nav_bar_stop { background-position: 0 -37px !important; } .threesixty .nav_bar a.nav_bar_next { background-position: 0 -104px !important; } /* html */ .threesixty:-webkit-full-screen { background: #ffffff; width: 100%; height: 100%; margin-top: 0; padding-top: 200px; } .threesixty:-moz-full-screen { background: #ffffff; width: 100%; height: 100%; margin-top: 0; padding-top: 200px; }
使用方法:
html代码:
<link type="text/css" rel="stylesheet" href="css/threesixty.css"> <script type="text/javascript" src="js/jquery-2.1.1.js"></script> <script type="text/javascript" src="js/threesixty.min.js"></script> <div class="threesixty"> <div class="spinner"> <span>0%</span> </div> <ol class="threesixty_images "></ol> </div>
js代码:
$(window).ready(function(){ $('.threesixty').ThreeSixty({ totalFrames: 12,//图片的总数 endFrame: 2, currentFrame: 1,//初始化时现实的第几个元素 imgList: '.threesixty_images',//显示图片的父级div progress: '.spinner',//显示进度的div imagePath: 'images/car/',//图片的路径 filePrefix: '',//用到的图片的前缀名称 ext: '.png',//存放的图片的后缀名(要一致) height: "30%",//显示区域的高度 width: "100%",//显示区域的宽度 navigation: true,//是否显示导航条(可以进行的操作:上一步 下一步 开始自动旋转) disableSpin: false }); });
如果
navigation:true 就会添加
<div class="nav_bar"><a href="#" class="nav_bar_previous">previous</a><a href="#" class="nav_bar_play">play</a><a href="#" class="nav_bar_next">next</a></div>
可以根据自己的需求修改样式
jquery.threesixty.js 源码:
/*! * ThreeSixty: A jQuery plugin for generating a draggable 360 preview from an image sequence. * Version: 0.1.2 * Original author: @nick-jonas * Website: http://www.workofjonas.com * Licensed under the MIT license */ ;(function ( $, window, document, undefined ) { var scope, pluginName = 'threeSixty', defaults = { dragDirection: 'horizontal', useKeys: false, draggable: true }, dragDirections = ['horizontal', 'vertical'], options = {}, $el = {}, data = [], total = 0, loaded = 0; /** * Constructor * @param {jQuery Object} element main jQuery object * @param {Object} customOptions options to override defaults */ function ThreeSixty( element, customOptions ) { scope = this; this.element = element; options = options = $.extend( {}, defaults, customOptions) ; this._defaults = defaults; this._name = pluginName; // make sure string input for drag direction is valid if($.inArray(options.dragDirection, dragDirections) < 0){ options.dragDirection = defaults.dragDirection; } this.init(); } // PUBLIC API ----------------------------------------------------- $.fn.destroy = ThreeSixty.prototype.destroy = function(){ if(options.useKeys === true) $(document).unbind('keydown', this.onKeyDown); $(this).removeData(); $el.html(''); }; $.fn.nextFrame = ThreeSixty.prototype.nextFrame = function(){ $(this).each(function(i){ var $this = $(this), val = $this.data('lastVal') || 0, thisTotal = $this.data('count'); val = val + 1; $this.data('lastVal', val); if(val >= thisTotal) val = val % (thisTotal - 1); else if(val <= -thisTotal) val = val % (thisTotal - 1); if(val > 0) val = thisTotal - val; val = Math.abs(val); $this.find('.threesixty-frame').css({display: 'none'}); $this.find('.threesixty-frame:eq(' + val + ')').css({display: 'block'}); }); }; $.fn.prevFrame = ThreeSixty.prototype.prevFrame = function(){ $(this).each(function(i){ var $this = $(this), val = $this.data('lastVal') || 0, thisTotal = $this.data('count'); val = val - 1; $this.data('lastVal', val); if(val >= thisTotal) val = val % (thisTotal - 1); else if(val <= -thisTotal) val = val % (thisTotal - 1); if(val > 0) val = thisTotal - val; val = Math.abs(val); $this.find('.threesixty-frame').css({display: 'none'}); $this.find('.threesixty-frame:eq(' + val + ')').css({display: 'block'}); }); }; // PRIVATE METHODS ------------------------------------------------- /** * Initializiation, called once from constructor * @return null */ ThreeSixty.prototype.init = function () { var $this = $(this.element); // setup main container $el = $this; // store data attributes for each 360 $this.each(function(){ var $this = $(this), path = $this.data('path'), count = $this.data('count'); data.push({'path': path, 'count': count, 'loaded': 0, '$el': $this}); total += count; }); _disableTextSelectAndDragIE8(); this.initLoad(); }; /** * Start loading all images * @return null */ ThreeSixty.prototype.initLoad = function() { var i = 0, len = data.length, url, j; $el.addClass('preloading'); for(i; i < len; i++){ j = 0; for(j; j < data[i].count; j++){ url = data[i].path.replace('{index}', j); $('<img/>').data('index', i).attr('src', url).load(this.onLoadComplete); } } }; ThreeSixty.prototype.onLoadComplete = function(e) { var index = $(e.currentTarget).data('index'), thisObj = data[index]; thisObj.loaded++; if(thisObj.loaded === thisObj.count){ scope.onLoadAllComplete(index); } }; ThreeSixty.prototype.onLoadAllComplete = function(objIndex) { var $this = data[objIndex].$el, html = '', l = data[objIndex].count, pathTemplate = data[objIndex].path, i = 0; // remove preloader $this.html(''); $this.removeClass('preloading'); // add 360 images for(i; i < l; i++){ var display = (i === 0) ? 'block' : 'none'; html += '<img class="threesixty-frame" style="display:' + display + ';" data-index="' + i + '" src="' + pathTemplate.replace('{index}', i) + '"/>'; } $this.html(html); this.attachHandlers(objIndex); }; var startY = 0, thisTotal = 0, $downElem = null, lastY = 0, lastX = 0, lastVal = 0, isMouseDown = false; ThreeSixty.prototype.attachHandlers = function(objIndex) { var that = this; var $this = data[objIndex].$el; // add draggable events if(options.draggable){ // if touch events supported, use if(typeof document.ontouchstart !== 'undefined' && typeof document.ontouchmove !== 'undefined' && typeof document.ontouchend !== 'undefined' && typeof document.ontouchcancel !== 'undefined'){ var elem = $this.get()[0]; elem.addEventListener('touchstart', that.onTouchStart); elem.addEventListener('touchmove', that.onTouchMove); elem.addEventListener('touchend', that.onTouchEnd); elem.addEventListener('touchcancel', that.onTouchEnd); } } // mouse down $this.mousedown(function(e){ e.preventDefault(); thisTotal = $(this).data('count'); $downElem = $(this); startY = e.screenY; lastVal = $downElem.data('lastVal') || 0; lastX = $downElem.data('lastX') || 0; lastY = $downElem.data('lastY') || 0; isMouseDown = true; $downElem.trigger('down'); }); // arrow keys if(options.useKeys === true){ $(document).bind('keydown', that.onKeyDown); } // mouse up $(document, 'html', 'body').mouseup(that.onMouseUp); $(document).blur(that.onMouseUp); $('body').mousemove(function(e){ that.onMove(e.screenX, e.screenY); }); }; ThreeSixty.prototype.onTouchStart = function(e) { var touch = e.touches[0]; e.preventDefault(); $downElem = $(e.target).parent(); thisTotal = $downElem.data('count'); startX = touch.pageX; startY = touch.pageY; lastVal = $downElem.data('lastVal') || 0; lastX = $downElem.data('lastX') || 0; lastY = $downElem.data('lastY') || 0; isMouseDown = true; $downElem.trigger('down'); }; ThreeSixty.prototype.onTouchMove = function(e) { e.preventDefault(); var touch = e.touches[0]; scope.onMove(touch.pageX, touch.pageY); }; ThreeSixty.prototype.onTouchEnd = function(e) { }; ThreeSixty.prototype.onMove = function(screenX, screenY){ if(isMouseDown){ var x = screenX, y = screenY, val = 0; $downElem.trigger('move'); if(options.dragDirection === 'vertical'){ if(y > lastY){ val = lastVal + 1; }else{ val = lastVal - 1; } }else{ if(x > lastX){ val = lastVal + 1; }else if(x === lastX){ return; }else{ val = lastVal - 1; } } lastVal = val; lastY = y; lastX = x; $downElem.data('lastY', lastY); $downElem.data('lastX', lastX); $downElem.data('lastVal', lastVal); if(val >= thisTotal) val = val % (thisTotal - 1); else if(val <= -thisTotal) val = val % (thisTotal - 1); if(val > 0) val = thisTotal - val; val = Math.abs(val); $downElem.find('.threesixty-frame').css({display: 'none'}); $downElem.find('.threesixty-frame:eq(' + val + ')').css({display: 'block'}); } }; ThreeSixty.prototype.onKeyDown = function(e) { switch(e.keyCode){ case 37: // left $el.prevFrame(); break; case 39: // right $el.nextFrame(); break; } }; ThreeSixty.prototype.onMouseUp = function(e) { isMouseDown = false; $downElem.trigger('up'); }; /** * Disables text selection and dragging on IE8 and below. */ var _disableTextSelectAndDragIE8 = function() { // Disable text selection. document.body.onselectstart = function() { return false; }; // Disable dragging. document.body.ondragstart = function() { return false; }; }; /** * A really lightweight plugin wrapper around the constructor, preventing against multiple instantiations * @param {Object} options * @return {jQuery Object} */ $.fn[pluginName] = function ( options ) { return this.each(function () { if (!$.data(this, 'plugin_' + pluginName)) { $.data(this, 'plugin_' + pluginName, new ThreeSixty( this, options )); } }); }; })( jQuery, window, document );
使用方法:
html
<script src="assets/js/jquery-2.1.1.js"></script> <script src="assets/js/jquery.threesixty.js"></script> <div class="threesixty-wrapper"> <div class="threesixty" data-path="assets/img/threesixty_{index}.jpg" data-count="179"> <!-- put your preloader here -->在图片没有加载完毕时,现实的内容,在图片加载完毕之后,就自动删除 <div class="ui-spinner"> <span class="side side-left"> <span class="fill"></span> </span> <span class="side side-right"> <span class="fill"></span> </span> </div> <!-- end preloader --> </div> </div>
js
$(document).ready(function(){ var $threeSixty = $('.threesixty'); $threeSixty.threeSixty({ dragDirection: 'horizontal',//拖拽的方向 useKeys: true,//是否可以使用键盘上的左右按键进行操作 draggable: true//是否可以鼠标拖拽 }); $('.next').click(function(){//显示下一张图片 $threeSixty.nextFrame(); }); $('.prev').click(function(){//显示上一张图片 $threeSixty.prevFrame(); }); $threeSixty.on('down', function(){//拖拽图片时,标题隐藏 $('h1').stop().animate({opacity:0}, 300); }); $threeSixty.on('up', function(){//方法鼠标之后,标题回显 $(' h1').stop().animate({opacity:1}, 500); }); });