小男孩与商店在布局上是没有关系的,只是都是相对的靠近中间位置动作,那么随着分辨率的变化,二者之间的位置都有不同的变化,这里都是采用JS动态计算的。
创建一个Qixi.js,把BoyWalk.js等一些逻辑代码全都放到这个里面,这个就是主文件代码了,之后会把所有的代码都会合并方到这个文件里面
小男孩进出商店的走路还是属于小男孩自身的一个动作,所以代码最终要封装到BoyWalk中。在Qixi.js中找到BoyWalk代码部分,在进出商店部分增加了toShop与outShop两个接口,具体的实现部分没有采用变化left与top,而用了translateX,主要是学习为目的,采用互通是实现搭配
小男孩走进门的中间位置,具体的算法比较简单:
translateX = 门中间的left值 - 小男孩中间的left值 translateY = 人物底部的top值 - 门中间的top值
这里的取值采用jQuery的offset处理的,注意下position与offset的取值不同点,.offset()是相对于文档(document)的当前位置,.position()是相对于父级元素的位移,一个元素可以嵌套多个position所以这里要特别注意下。
在实际的的进门路线的处理中,代码是采用translateX + scale的组合,并没有采用translateY,原因就是scale是一个缩放效果,在实际上会有替代translateY这个Y轴变化的感觉,具体我们可以参考代码部分的处理
具体,我们参考代码部分walkToShop与walkOutShop两个实现方法
//开始走路
var walkPlay = stratRun({
    transform: 'translateX,scale',//代码略
    opacity: 0.1
}, 2000);
//走路完毕
walkPlay.done(function() {
    $boy.css({
        opacity: 0
    })
    defer.resolve();
})
在走路完毕后,监听了一个done的成功方法,用来设置人物的隐藏,这个是Deferred的一个接口,与then效果一致
备注:
特别注意下,很多时候大家都是通过left与top修改元素的页面坐标,那么left与top确实也是页面元素的一个准确的坐标值。这样的情况直到css3的transform的出现,因为会有一个translate同样能改变页面的坐标
所以如果运用了translate的元素,最终的坐标需要加上这个属性的值
元素的页面X坐标 = left + translateX 元素的页面Y坐标 = top + translateY
所以在这个案例上,小孩男运用了left与translateX,所以实现的X坐标值 = left + translateX 之和了。
打开Qixi.js文件,在代码的162行填入相应代码,可以观察到人物走路商店的动作
var defer = $.Deferred();
restoreWalk();
//开始走路
var walkPlay = stratRun({
    transform: 'translateX(' + instanceX + 'px),scale(1,1)',
   opacity: 1
}, runTime);
//走路完毕
walkPlay.done(function() {
    defer.resolve();
});
return defer;          
	
 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title>慕课七夕主题</title> <link rel='stylesheet' href='style.css' /> <link rel='stylesheet' href='pageA.css' /> <link rel='stylesheet' 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> </head> <body> <div id='content'> <ul class='content-wrap'> <!-- 第一副画面 --> <li> <!-- 背景 --> <div class="a_background"> <div class="a_background_top"></div> <div class="a_background_middle"></div> <div class="a_background_botton"></div> </div> <!-- 云 --> <div class="cloudArea"> <div class="cloud"></div> <div class="cloud"></div> </div> <!-- 太阳 --> <div id="sun"></div> </li> <!-- 第二副画面 --> <li> <!-- 背景图 --> <div class="b_background"></div> <div class="b_background_preload"></div> <!-- 商店 --> <div class="shop"> <div class="door"> <div class="door-left"></div> <div class="door-right"></div> </div> <!-- 灯 --> <div class="lamp"></div> </div> </li> <li> 页面3 </li> </ul> <div id="boy" class="charector"></div> <div class="button"> <button>开始</button> </div> </div> </body> <script type="text/javascript"> $(function() { var container = $("#content"); var swipe = Swipe(container); // 页面滚动到指定的位置 function scrollTo(time, proportionX) { var distX = container.width() * proportionX; swipe.scrollTo(distX, time); } //////////////////////////////////////////////////////// // ================= 动画处理 ======================= // //////////////////////////////////////////////////////// // 用来临时调整页面 swipe.scrollTo(container.width(), 0); var boy = BoyWalk(); function startRun() { boy.walkTo(2000, 0.5) .then(function() { //暂停走路 boy.stopWalk() }) .then(function() { //开门 return openDoor(); }) .then(function() { //开灯 lamp.bright() }) .then(function() { //进商店 return boy.toShop(2000) }).then(function() { //出商店 return boy.outShop(2000) }).then(function() { //灯暗 lamp.dark() }); } // 开始 $("button:first").click(startRun); }) </script> <script type="text/javascript" src="Swipe.js"></script> <script type="text/javascript" src="Qixi.js"></script> </html>
 /////////// //灯动画 // /////////// var lamp = { elem: $('.b_background'), bright: function() { this.elem.addClass('lamp-bright'); }, dark: function() { this.elem.removeClass('lamp-bright'); } }; function doorAction(left, right, time) { var $door = $('.door'); var doorLeft = $('.door-left'); var doorRight = $('.door-right'); var defer = $.Deferred(); var count = 2; // 等待开门完成 var complete = function() { if (count == 1) { defer.resolve(); return; } count--; }; doorLeft.transition({ 'left': left }, time, complete); doorRight.transition({ 'left': right }, time, complete); return defer; } // 开门 function openDoor() { return doorAction('-50%', '100%', 2000); } // 关门 function shutDoor() { return doorAction('0%', '50%', 2000); } var instanceX; /** * 小孩走路 * @param {[type]} container [description] */ function BoyWalk() { var container = $("#content"); // 页面可视区域 var visualWidth = container.width(); var visualHeight = container.height(); // 获取数据 var getValue = function(className) { var $elem = $('' + className + ''); // 走路的路线坐标 return { height: $elem.height(), top: $elem.position().top }; } // 路的Y轴 var pathY = function() { var data = getValue('.a_background_middle'); return data.top + data.height / 2; }(); var $boy = $("#boy"); var boyWidth = $boy.width(); var boyHeight = $boy.height(); // 设置下高度 $boy.css({ top: pathY - boyHeight + 25 }) // 暂停走路 function pauseWalk() { $boy.addClass('pauseWalk'); } // 恢复走路 function restoreWalk() { $boy.removeClass('pauseWalk'); } // css3的动作变化 function slowWalk() { $boy.addClass('slowWalk'); } // 用transition做运动 function stratRun(options, runTime) { var dfdPlay = $.Deferred(); // 恢复走路 restoreWalk(); // 运动的属性 $boy.transition( options, runTime, 'linear', function() { dfdPlay.resolve(); // 动画完成 }); return dfdPlay; } // 开始走路 function walkRun(time, dist, disY) { time = time || 3000; // 脚动作 slowWalk(); // 开始走路 var d1 = stratRun({ 'left': dist + 'px', 'top': disY ? disY : undefined }, time); return d1; } // 走进商店 function walkToShop(runTime) { var defer = $.Deferred(); var doorObj = $('.door') // 门的坐标 var offsetDoor = doorObj.offset(); var doorOffsetLeft = offsetDoor.left; // 小孩当前的坐标 var offsetBoy = $boy.offset(); var boyOffetLeft = offsetBoy.left; // 当前需要移动的坐标 instanceX = (doorOffsetLeft + doorObj.width() / 2) - (boyOffetLeft + $boy.width() / 2); // 开始走路 var walkPlay = stratRun({ transform: 'translateX(' + instanceX + 'px),scale(0.3,0.3)', opacity: 0.1 }, 2000); // 走路完毕 walkPlay.done(function() { $boy.css({ opacity: 0 }) defer.resolve(); }) return defer; } // 走出店 function walkOutShop(runTime) { // ? } // 计算移动距离 function calculateDist(direction, proportion) { return (direction == "x" ? visualWidth : visualHeight) * proportion; } return { // 开始走路 walkTo: function(time, proportionX, proportionY) { var distX = calculateDist('x', proportionX) var distY = calculateDist('y', proportionY) return walkRun(time, distX, distY); }, // 走进商店 toShop: function() { return walkToShop.apply(null, arguments); }, // 走出商店 outShop: function() { return walkOutShop.apply(null, arguments); }, // 停止走路 stopWalk: function() { pauseWalk(); }, setColoer: function(value) { $boy.css('background-color', value) } } }
 ///////// //页面滑动 // ///////// /** * [Swipe description] * @param {[type]} container [页面容器节点] * @param {[type]} options [参数] */ function Swipe(container) { // 获取第一个子节点 var element = container.find(":first"); var swipe = {}; // li页面数量 var slides = element.find("li"); // 获取容器尺寸 var width = container.width(); var height = container.height(); // 设置li页面总宽度 element.css({ width: (slides.length * width) + 'px', height: height + 'px' }) // 设置每一个页面li的宽度 $.each(slides, function(index) { var slide = slides.eq(index); // 获取到每一个li元素 slide.css({ width: width + 'px', height: height + 'px' }); }); // 监控完成与移动 swipe.scrollTo = function(x, speed) { // 执行动画移动 element.css({ 'transition-timing-function' : 'linear', 'transition-duration' : speed + 'ms', 'transform' : 'translate3d(-' + x + 'px,0px,0px)' }); return this; } return swipe; }
 * { padding: 0; margin: 0; } ol, ul, li { list-style-type: none; } /*主体部分*/ #content { width: 100%; height: 100%; /* top: 20%; */ overflow: hidden; position: absolute; } .content-wrap { position: relative; } .content-wrap > li { background: #CAE1FF; color: red; float: left; overflow: hidden; position: relative; } li:nth-child(2) { background: #9BCD9B; } li:nth-child(3) { background: yellow; } a { position: absolute; top: 50%; left: 40%; } .charector { position: absolute; left: 0%; top: 55%; position: absolute; width: 100%; height: 100%; width: 151px; height: 291px; background: url(http://img.mukewang.com/55ade248000198ae10550582.png) -0px -291px no-repeat; } .slowWalk { -webkit-animation-name: person-slow; -webkit-animation-duration: 950ms; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: steps(1, start); -moz-animation-name: person-slow; -moz-animation-duration: 950ms; -moz-animation-iteration-count: infinite; -moz-animation-timing-function: steps(1, start) } /*人物暂停*/ .pauseWalk { -webkit-animation-play-state: paused; } /*普通慢走*/ @-webkit-keyframes person-slow { 0% { background-position: -0px -291px; } 25% { background-position: -602px -0px; } 50% { background-position: -302px -291px; } 75% { background-position: -151px -291px; } 100% { background-position: -0px -291px; } } @-moz-keyframes person-slow { 0% { background-position: -0px -291px; } 25% { background-position: -602px -0px; } 50% { background-position: -302px -291px; } 75% { background-position: -151px -291px; } 100% { background-position: -0px -291px; } }
 /*背景图*/ .a_background { width: 100%; height: 100%; /* background-image: url("../images/QixiA.png"); background-size: 100% 100%;*/ position: absolute; } .a_background_top { width: 100%; height: 71.6%; background-image: url("http://img1.sycdn.imooc.com//55addf6900019d8f14410645.png"); background-size: 100% 100%; } .a_background_middle { width: 100%; height: 13.1%; background-image: url("http://img1.sycdn.imooc.com//55addf800001ff2e14410118.png"); background-size: 100% 100%; } .a_background_botton { width: 100%; height: 15.3%; background-image: url("http://img1.sycdn.imooc.com//55addfcb000189b314410138.png"); background-size: 100% 100%; } button { width: 80px; height: 50px; } .button { position: absolute; bottom: 0; } /*人物暂停*/ .pauseWalk { animation-play-state: paused; } /*-------- 太阳自转以及动画 --------*/ #sun { background: url("http://img1.sycdn.imooc.com//55ade004000106c202010201.png") no-repeat; position: absolute; z-index: 1; top: -30px; height: 201px; width: 201px; right: 40%; } .rotation { -webkit-animation-name: rotation; -webkit-animation-duration: 30s; -webkit-animation-iteration: 1; -moz-animation-name: rotation; -moz-animation-duration: 30s; -moz-animation-iteration: 1; } @-webkit-keyframes rotation { 0% { transform: translateX(0) translateY(0); } 100% { transform: translateX(-2000px) translateY(400px); } } @-moz-keyframes rotation { 0% { transform: translateX(0) translateY(0); } 100% { transform: translateX(-2000px) translateY(400px); } } /*天空云*/ .cloud { z-index: 2; position: absolute; } .cloud1 { width: 20%; height: 30%; left: -5%; top: 15%; background: url("http://img1.sycdn.imooc.com//55addfde0001aec501810101.png") no-repeat; -webkit-animation-name: smallCloud; -webkit-animation-duration: 30s; -webkit-animation-iteration: infinite; -moz-animation-name: smallCloud; -moz-animation-duration: 30s; -moz-animation-iteration: infinite } .cloud2 { width: 20%; height: 30%; right: -5%; background: url("http://img1.sycdn.imooc.com//55addff500016df503010140.png") no-repeat; -webkit-animation-name: largeCloud; -webkit-animation-duration: 60s; -webkit-animation-iteration: infinite; -moz-animation-name: largeCloud; -moz-animation-duration: 60s; -moz-animation-iteration: infinite; } @-webkit-keyframes smallCloud { 0% { left: -5%; } 100% { left: 100%; } } @-moz-keyframes smallCloud { 0% { left: -5%; } 100% { left: 100%; } } @-webkit-keyframes largeCloud { 0% { right: -5%; } 100% { right: 100%; } } @-moz-keyframes largeCloud { 0% { right: -5%; } 100% { right: 100%; } }
 /*背景图*/ .b_background { width: 100%; height: 100%; background-image: url("http://img1.sycdn.imooc.com//55ade06f00015a0d14410901.png"); background-size: 100% 100%; position: absolute; } .b_background_preload { background: url("http://img1.sycdn.imooc.com//55ade0be0001a37914410901.png") no-repeat -9999px -9999px; } .lamp-bright { background-image: url("http://img1.sycdn.imooc.com//55ade0be0001a37914410901.png"); } /*商店*/ .shop { width: 39.5%; height: 35.5%; position: absolute; left: 29%; top: 36.5%; } .door { position: absolute; width: 32%; height: 100%; top: 32%; height: 68%; overflow: hidden; left: 58.5%; } .door-left, .door-right { width: 50%; height: 100%; position: absolute; } .door-left { left: 0%; background: url(http://img.mukewang.com/55ade1140001050d00910231.png); background-size: 100% 100%; } .door-right { left: 50%; background: url(http://img.mukewang.com/55ade12100019f5b00910231.png); background-size: 100% 100%; }