旋转的原理与实现大体已经了解了,这一节我们需要把零碎的代码整合起来。具体参考右边carousel.js文件,旋转效果的样式与结构都是通过脚本代码动态生成。
定义了一个Carousel类,这里没有采用prototype原型对象,直接在构造函数中定义了this.run方法,这里一个特权方法。可以通过这个方法在外部能直接访问到内部的私有成员与方法。
在pageB.js中构造这个类,在运动的时候可以调用对应的接口,下面代码简化了部分
//旋转木马对象 var carousel = new Carousel($carousel, ...); carousel.run()
Carousel类代码内部的通过initStyle方法构建场景与容器元素,主要是设置布局与一些3D需要的必要设置,perspective、preserve-3d等等
子节点是由3个图片构成,在render方法中需要循环生成对应的节点,需要注意rotateY角度与translateZ值的初始化处理
特权this.run方法是暴露给外部调用的接口,通过传递旋转的次数触发旋转动作
注意旋转动画是采用的transition,所以在监听这个动作事件的时候需要绑定transitionend webkitTransitionend事件,这样才能连接后面的动作了
代码布局还扩展了String.format的一个格式化方法,这个是动态生成HTML结构的的简单模版
在pageB.js文件的22行处填入任务代码
点击可以调用旋转效果开始,并且每次点击旋转的面是叠加的
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title>圣诞主题</title> <link rel='stylesheet' href='common.css' /> <link rel="stylesheet" type="text/css" href="pageB.css"> <script src="http://libs.baidu.com/jquery/1.9.1/jquery.js"></script> <script type="text/javascript" src="http://img1.sycdn.imooc.com//down/55ac9ea30001ace700000000.js"></script> <script src="carousel.js"></script> <script src="pageB.js"></script> <script src="christmas.js"></script> </head> <body> <section class="container"> <!-- 第一幅画面 --> <section class="page-a bg-adaptive"> </section> <!-- 第二幅画面 --> <section class="page-b bg-adaptive"> <!-- 猫 --> <figure class="cat"></figure> <!-- 小女孩 --> <figure class="girl"></figure> <!-- 圣诞男孩 --> <figure class="christmas-boy-head"></figure> <figure class="christmas-boy boy-walk"> </figure> <!-- 旋转木马 --> <div id="carousel"> <figure id="spinner"></figure> </div> </section> <!-- 第三幅画面 --> <section class="page-c bg-adaptive"> </section> </section> <button>点击执行</button> <script type="text/javascript"> //rem设置 (function(doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function() { var clientWidth = docEl.clientWidth; if (!clientWidth) return; docEl.style.fontSize = 20 * (clientWidth / 320) + 'px'; //宽与高度 document.body.style.height = clientWidth * (900 / 1440) + "px" }; win.addEventListener(resizeEvt, recalc, false); doc.addEventListener('DOMContentLoaded', recalc, false); })(document, window); </script> </body> </html>
/** * 慕课网特制 * 圣诞主题效果 * @type {Object} */ /** * 中间调用 */ var Christmas = function() { //页面容器元素 var $pageB = $(".page-b"); //构建第二个场景页面对象 new pageB($pageB); }; $(function() { Christmas(); })
/** * 第二副场景页面 * */ function pageB(element, pageComplete) { //3d旋转节点 var $carousel = element.find("#carousel"); //旋转木马对象 var carousel = new Carousel($carousel, { imgUrls: [ "http://img1.sycdn.imooc.com//5662e29a0001905a14410901.png", "http://img1.sycdn.imooc.com//5662e2960001f16314410901.png", "http://img1.sycdn.imooc.com//5662e26f00010dea14410901.png" ] }); var i = 0; $("button").on("click", function() { // ? }) }
*{ margin: 0; padding: 0; } .container { width: 100%; height: 100%; position: relative; overflow: hidden; } .bg-adaptive { background-size: 100% 100%; } .container .page-b { width : 100%; height : 100%; background-image: url("http://img1.sycdn.imooc.com//565d09fa000145a614410901.png"); position: absolute; z-index: 40; }
//================================================ //格式化字符串 var slice = Array.prototype.slice function toArray(a, i, j) { return slice.call(a, i || 0, j || a.length); } /** * 返回true,如果传递的值不是未定义。 * @param {Mixed} * @return {Boolean} */ function isDefined(v) { return typeof v !== 'undefined'; } /** * 拷贝对象,跳过已存在的 * @param {[type]} o [接受方对象] * @param {[type]} c [源对象] * @return {[type]} [description] */ function applyIf(o, c) { if (o) { for (var p in c) { //跳过已存在 if (!isDefined(o[p])) { o[p] = c[p]; } } } return o; } /** * @class String * 格式化字符串 */ applyIf(String, { format: function(format) { var args = toArray(arguments, 1); return format.replace(/\{(\d+)\}/g, function(m, i) { return args[i]; }); } }); /** * 3d旋转木马 * @param {[type]} argument [description] * @return {[type]} [description] */ function Carousel(carousel, options) { //图片 var imgUrls = options.imgUrls; //场景元素 var $carousel = carousel; //容器元素 var $spinner = carousel.find("#spinner"); var angle = 0; //图片数 var numpics = imgUrls.length; //角度 var rotate = 360 / numpics; var start = 0; var current = 1; //子元素 var $contentElements; //图片数量 this.numpics = numpics; /** * 创建结构 * @param {[type]} imgUrl [description] * @return {[type]} [description] */ function createStr(imgUrl) { var str = '<figure style="transform:rotateY({0}deg) translateZ({1}) scaleY(.9);position:absolute;">' + '<img src="{2}" style="width:100%;height:100%;">' + '</figure>'; return String.format(str, start, "2.5rem", imgUrl ) } /** * 初始化样式 * @return {[type]} [description] */ function initStyle() { //场景元素 $carousel.css({ // "transform": "scale(0.3)", "-webkit-perspective": "500", "-moz-perspective": "500px", "position": "absolute", "left": "6.8rem", "top": "4.5rem" }); //容器 $spinner.css({ "width": "4rem", "transform-style": "preserve-3d" }) } /** * 绘制页面节点 * @return {[type]} [description] */ function render() { //创建内容 var contentStr = ''; $.each(imgUrls, function(index, url) { contentStr += createStr(url); start = start + rotate; }) $contentElements = $(contentStr); $spinner.append($contentElements) } //样式 initStyle(); //绘制节点 render(); //旋转次数,游标,当前页码 var currIndex; /** * 运行旋转 * @param {[type]} count [description] * @param {Function} callback [description] * @return {[type]} [description] */ this.run = function(count, callback) { currIndex = count; //360 //480 //600 angle = (count - 1) * rotate + 360 $spinner .css({ "transform": "rotateY(-" + angle + "deg)", "transition":"1s" }) .css({ "-moz-transform": "rotateY(-" + angle + "deg)", "-moz-transition":"1s" }) .one("transitionend webkitTransitionend", function() { //去掉transition保留在样式上 //照成的缩放元素会有动画变化 $spinner.css("transition","") $spinner.css("-moz-transition","") alert("旋转完成") }) } }