6-5 3D旋转特效(下)
本节编程练习不计算学习进度,请电脑登录imooc.com操作

3D旋转特效(下)

旋转的原理与实现大体已经了解了,这一节我们需要把零碎的代码整合起来。具体参考右边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行处填入任务代码

点击可以调用旋转效果开始,并且每次点击旋转的面是叠加的

  1. <!DOCTYPE html>
  2. <html>
  3.  
  4. <head>
  5. <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
  6. <title>圣诞主题</title>
  7. <link rel='stylesheet' href='common.css' />
  8. <link rel="stylesheet" type="text/css" href="pageB.css">
  9. <script src="http://libs.baidu.com/jquery/1.9.1/jquery.js"></script>
  10. <script type="text/javascript" src="http://img1.sycdn.imooc.com//down/55ac9ea30001ace700000000.js"></script>
  11. <script src="carousel.js"></script>
  12. <script src="pageB.js"></script>
  13. <script src="christmas.js"></script>
  14. </head>
  15.  
  16. <body>
  17. <section class="container">
  18. <!-- 第一幅画面 -->
  19. <section class="page-a bg-adaptive">
  20. </section>
  21. <!-- 第二幅画面 -->
  22. <section class="page-b bg-adaptive">
  23. <!-- 猫 -->
  24. <figure class="cat"></figure>
  25. <!-- 小女孩 -->
  26. <figure class="girl"></figure>
  27. <!-- 圣诞男孩 -->
  28. <figure class="christmas-boy-head"></figure>
  29. <figure class="christmas-boy boy-walk"> </figure>
  30. <!-- 旋转木马 -->
  31. <div id="carousel">
  32. <figure id="spinner"></figure>
  33. </div>
  34. </section>
  35. <!-- 第三幅画面 -->
  36. <section class="page-c bg-adaptive">
  37. </section>
  38. </section>
  39. <button>点击执行</button>
  40. <script type="text/javascript">
  41. //rem设置
  42. (function(doc, win) {
  43. var docEl = doc.documentElement,
  44. resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
  45. recalc = function() {
  46. var clientWidth = docEl.clientWidth;
  47. if (!clientWidth) return;
  48. docEl.style.fontSize = 20 * (clientWidth / 320) + 'px';
  49. //宽与高度
  50. document.body.style.height = clientWidth * (900 / 1440) + "px"
  51. };
  52. win.addEventListener(resizeEvt, recalc, false);
  53. doc.addEventListener('DOMContentLoaded', recalc, false);
  54. })(document, window);
  55. </script>
  56. </body>
  57.  
  58. </html>
  59.  
  1. /**
  2.  * 慕课网特制
  3.  * 圣诞主题效果
  4.  * @type {Object}
  5.  */
  6.  
  7. /**
  8.  * 中间调用
  9.  */
  10. var Christmas = function() {
  11. //页面容器元素
  12. var $pageB = $(".page-b");
  13. //构建第二个场景页面对象
  14. new pageB($pageB);
  15. };
  16.  
  17. $(function() {
  18. Christmas();
  19. })
  1.  
  2. /**
  3.  * 第二副场景页面
  4.  *
  5.  */
  6. function pageB(element, pageComplete) {
  7.  
  8. //3d旋转节点
  9. var $carousel = element.find("#carousel");
  10.  
  11. //旋转木马对象
  12. var carousel = new Carousel($carousel, {
  13. imgUrls: [
  14. "http://img1.sycdn.imooc.com//5662e29a0001905a14410901.png",
  15. "http://img1.sycdn.imooc.com//5662e2960001f16314410901.png",
  16. "http://img1.sycdn.imooc.com//5662e26f00010dea14410901.png"
  17. ]
  18. });
  19.  
  20. var i = 0;
  21. $("button").on("click", function() {
  22. // ?
  23. })
  24.  
  25.  
  26. }
  27.  
  1. *{
  2. margin: 0;
  3. padding: 0;
  4. }
  5.  
  6.  
  7. .container {
  8. width: 100%;
  9. height: 100%;
  10. position: relative;
  11. overflow: hidden;
  12. }
  13.  
  14. .bg-adaptive {
  15. background-size: 100% 100%;
  16. }
  17.  
  18. .container .page-b {
  19. width : 100%;
  20. height : 100%;
  21. background-image: url("http://img1.sycdn.imooc.com//565d09fa000145a614410901.png");
  22. position: absolute;
  23. z-index: 40;
  24. }
  25.  
  1. //================================================
  2. //格式化字符串
  3. var slice = Array.prototype.slice
  4.  
  5. function toArray(a, i, j) {
  6. return slice.call(a, i || 0, j || a.length);
  7. }
  8. /**
  9.  * 返回true,如果传递的值不是未定义。
  10.  * @param {Mixed}
  11.  * @return {Boolean}
  12.  */
  13. function isDefined(v) {
  14. return typeof v !== 'undefined';
  15. }
  16.  
  17. /**
  18.  * 拷贝对象,跳过已存在的
  19.  * @param {[type]} o [接受方对象]
  20.  * @param {[type]} c [源对象]
  21.  * @return {[type]} [description]
  22.  */
  23. function applyIf(o, c) {
  24. if (o) {
  25. for (var p in c) {
  26. //跳过已存在
  27. if (!isDefined(o[p])) {
  28. o[p] = c[p];
  29. }
  30. }
  31. }
  32. return o;
  33. }
  34. /**
  35.  * @class String
  36.  * 格式化字符串
  37.  */
  38. applyIf(String, {
  39. format: function(format) {
  40. var args = toArray(arguments, 1);
  41. return format.replace(/\{(\d+)\}/g, function(m, i) {
  42. return args[i];
  43. });
  44. }
  45. });
  46.  
  47.  
  48. /**
  49.  * 3d旋转木马
  50.  * @param {[type]} argument [description]
  51.  * @return {[type]} [description]
  52.  */
  53. function Carousel(carousel, options) {
  54. //图片
  55. var imgUrls = options.imgUrls;
  56. //场景元素
  57. var $carousel = carousel;
  58. //容器元素
  59. var $spinner = carousel.find("#spinner");
  60. var angle = 0;
  61. //图片数
  62. var numpics = imgUrls.length;
  63. //角度
  64. var rotate = 360 / numpics;
  65. var start = 0;
  66. var current = 1;
  67. //子元素
  68. var $contentElements;
  69.  
  70. //图片数量
  71. this.numpics = numpics;
  72.  
  73. /**
  74.   * 创建结构
  75.   * @param {[type]} imgUrl [description]
  76.   * @return {[type]} [description]
  77.   */
  78. function createStr(imgUrl) {
  79. var str = '<figure style="transform:rotateY({0}deg) translateZ({1}) scaleY(.9);position:absolute;">'
  80. + '<img src="{2}" style="width:100%;height:100%;">'
  81. + '</figure>';
  82.  
  83. return String.format(str,
  84. start,
  85. "2.5rem",
  86. imgUrl
  87. )
  88. }
  89.  
  90. /**
  91.   * 初始化样式
  92.   * @return {[type]} [description]
  93.   */
  94. function initStyle() {
  95. //场景元素
  96. $carousel.css({
  97. // "transform": "scale(0.3)",
  98. "-webkit-perspective": "500",
  99. "-moz-perspective": "500px",
  100. "position": "absolute",
  101. "left": "6.8rem",
  102. "top": "4.5rem"
  103. });
  104. //容器
  105. $spinner.css({
  106. "width": "4rem",
  107. "transform-style": "preserve-3d"
  108. })
  109. }
  110.  
  111. /**
  112.   * 绘制页面节点
  113.   * @return {[type]} [description]
  114.   */
  115. function render() {
  116. //创建内容
  117. var contentStr = '';
  118. $.each(imgUrls, function(index, url) {
  119. contentStr += createStr(url);
  120. start = start + rotate;
  121. })
  122. $contentElements = $(contentStr);
  123. $spinner.append($contentElements)
  124. }
  125.  
  126. //样式
  127. initStyle();
  128. //绘制节点
  129. render();
  130.  
  131.  
  132. //旋转次数,游标,当前页码
  133. var currIndex;
  134.  
  135. /**
  136.   * 运行旋转
  137.   * @param {[type]} count [description]
  138.   * @param {Function} callback [description]
  139.   * @return {[type]} [description]
  140.   */
  141. this.run = function(count, callback) {
  142. currIndex = count;
  143. //360
  144. //480
  145. //600
  146. angle = (count - 1) * rotate + 360
  147. $spinner
  148. .css({
  149. "transform": "rotateY(-" + angle + "deg)",
  150. "transition":"1s"
  151. })
  152. .css({
  153. "-moz-transform": "rotateY(-" + angle + "deg)",
  154. "-moz-transition":"1s"
  155. })
  156. .one("transitionend webkitTransitionend", function() {
  157. //去掉transition保留在样式上
  158. //照成的缩放元素会有动画变化
  159. $spinner.css("transition","")
  160. $spinner.css("-moz-transition","")
  161. alert("旋转完成")
  162. })
  163. }
  164. }
  165.  
下一节