摘要:是一款可以對產品圖片進行度全方位旋轉展示的插件。動畫幀通過切換的速度,默認值為毫秒。動畫幀改編之后的回調函數以當前幀和總幀數為參數。返回對象的總的動畫幀數。顯示對象的元素節點。
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了,有興趣,可以嘗試一下奧。
如果文章有問題,請大家積極指正,共同進步。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/112001.html
摘要:第一部分包括一個視圖示例以及在構建視圖時需要考慮的要點概述,第二部分將介紹一個示例數據模型的實現,第三部分將深入探討如何將數據遷移到的機制。讓我們假設你已經有創建一個視圖的想法了。 本文源地址:http://www.mongoing.com/archives/884 本系列的三篇博客將會提供一個關于在MongoDB上構建360°視圖的介紹。第一部分包括一個360°視圖示例以及在構建...
摘要:第一部分包括一個視圖示例以及在構建視圖時需要考慮的要點概述,第二部分將介紹一個示例數據模型的實現,第三部分將深入探討如何將數據遷移到的機制。讓我們假設你已經有創建一個視圖的想法了。 本文源地址:http://www.mongoing.com/archives/884 本系列的三篇博客將會提供一個關于在MongoDB上構建360°視圖的介紹。第一部分包括一個360°視圖示例以及在構建...
閱讀 2416·2023-04-25 15:00
閱讀 2602·2021-11-18 13:14
閱讀 1574·2021-11-15 11:37
閱讀 3372·2021-09-24 13:55
閱讀 1440·2019-08-30 15:52
閱讀 2827·2019-08-29 12:35
閱讀 3543·2019-08-29 11:04
閱讀 1455·2019-08-26 12:13