情人节动画笔记

github: https://github.com/miyiyiy/Tanabata_Demo

慕课网教程--H5+JS+CSS实现情人节动画

1. 页面布局

总共3幅图,实现横向布局,整个效果以小男孩为前提,在3个主题页面中切换并在每个主题页面中会有不同的效果呈现

页面滚动和小男孩走动,通过两者速率变化,产生视觉差,形成总体效果

页面是一个横向布局,包含3个主题,页面之间无缝拼接,实现滚动

布局上很好处理,我们做3个块级元素,每一个块元素代表一个主题页面容器节点。然后设置一个父容器是3个块元素的宽,通过float处理,这样就形成了一个横向的3个无缝拼接的页面

页面布局结构如下:

  • 页面1
  • 页面2
  • 页面3

var config={//整体布局配置
		keepZoomRatio:false,//界面比,设成true保持固定比
		layer:{//界面宽度和高度
			'width':'100%',
			'height':'100%',
			'top':0,
			'left':0
		},
}


实现固定比:

if(config.keepZoomRatio){
		var proportionY=900/1440;
		var screenHeight=$(document).height();
		var zoomHeight=screenHeight*proportionY;
		var zoomTop=(screenHeight-zoomHeight)/2;
		config.layer.height=zoomHeight;
		config.layer.top=zoomTop;
	}

function Swipe(contianer)//界面设置
{
	var element=contianer.find(':first');
	var swipe={};
	//li页面数量
	var slides=element.find('>');
	//获取容器尺寸
	var width=contianer.width();
	var height=contianer.height();
	element.css({
		width:(slides.length*width)+'px',
		height: height+'px'
	});
	//设置每个li页面的宽度
	$.each(slides,function(index){
		var slide=slides.eq(index);
		slide.css({
			width : width+'px',
			height: height+'px'
		});
	});

	swipe.scrollTo=function (x,speed) {//实现页面的滚动效果
		/* body... */
		//执行动画移动
		element.css({
			'transition-timing-function':'linear',
			'transition-duration':speed+'ms',
			'transform':'translate3d(-'+(x)+'px,0px,0px)'
		});
		return this;
	};
	return swipe;
}

页面的横向布局我们已经实现好了,那么如何实现页面与页面之间的切换呢?

一般来说要根据布局的结构来,大体有2种:

  • 移动父容器,改变父容器的坐标
  • 移动每一个子容器的坐标
移动父容器简单很多,只需要改变父容器X轴的坐标就可以了。如果父容器中子元素有很多的话,那么我们会考虑第二种算法,可以做成动态加载

改变坐标的处理的两种方法:传统的top、left坐标,CSS3中的transform属性。

传统的就是修改元素style是坐标属性,这个没什么好说的,使用简单,一般都需要配合定时器使用。

CSS3引入了一个新的属性transform,transform 属性向元素应用 2D 或 3D 转换,该属性允许我们对元素进行旋转、缩放、移动或倾斜。其中会有一个值translate3d(x,y,z) 是用来控制元素的位置在页面上的三轴的位置的,translate3d这里指明了3d就是启用了3d加速,也就是启动GPU来处理,性能更强

transition 可以实现简单的动画属性

这里需要特别注意的就是:

transform属性是静态属性,不是动画属性,一旦写到style里面,将会直接显示作用,无任何变化过程

简单的一句话描述就是

通过设置transition的一些参数,让translate3d这个属性发生变化

具体实现见Swipe中的scrollTo()


2. 小男孩的动画

小孩男走路是贯穿三个主题页面,因此小男孩在布局上不能嵌入任何一个页面内,否则无法切换到下一个页面中了。所以最终小男孩的布局与页面根节点属于并列结构

小男孩的布局很简单,但是要注意3个问题:

  • 小男孩其实只会在当前页面移动,所以是相对父级#content的范围
  • 小男孩的布局处理,因为小孩男是合成的"雪碧图",通过坐标取图,因此不能用CSS处理自适应布局了,需要动态调整//在圣诞节动画中有提到自适应处理
  • 采用动画的元素需要设置绝对定位
小男孩总是会沿着中间那个路线走动。因为背景图是靠百分比控制的,会随着分辨率的变化而变化。 但是人物是固定的尺寸是无法变化的(合成图的关系),这里只能通过JS动态调整

小男孩的top坐标值 = 中间路段的中间坐标值 - 小男孩的高度
var pathY=function () {
		var data=getValue('.a_background_middle');
		return data.top+data.height/2;
	}();
var $boy=$('#boy');
		var boyHeight=$boy.height();
		var boyWidth=$boy.width();
		//修正小男孩的正确位置
		//路的中间位置减去小孩的高度 25是一个修正值
		$boy.css({
			top:pathY-boyHeight+25
		});
CSS Sprites在国内很多人叫 CSS 精灵,其实这个技术不新鲜,原理就是: 靠不断的切换图片让人感觉视觉上不断在变化

传统的就是靠定时器不断去改变一个元素的background-image属性了,简单的来说就是靠不断的替换图片,但是值得注意的问题就是图片如果很多,加载会比较慢,会占用大量网络资源

大多数的做法就是把图片都合成一张大图再利用CSS的以下属性

background-image
background-repeat
background-position

组合进行背景定位,background-position可以用数字精确的定位出背景图片的位置

for example:

.slowWalk
{
	/* 填入动画 式规则 */
	/* 规定@keyframes动画的名称 */
	-webkit-animation-name: person-slow;
	/* 规定动画完成一个周期所花费的秒或毫秒。默认为0 */
	-webkit-animation-duration: 950ms;
	/* 规定动画被播放的次数。默认是1,infinite: 循环播放; */
	-webkit-animation-iteration-count: infinite;
	/* 动画切换的方式是一针一帧的改变 */
	-webkit-animation-timing-function: steps(1,start);
	-webkit-animation-play-state: running;//人物的状态控制
}
@-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;
	}
}

人物走动:

$boy.transition({
    'left': $("#content").width() + 'px',
}, 10000, 'linear', function() {});


3.异步编程处理

通过$.Deferred处理过的代码,很明显没有了回调的嵌套,虽然代码量看起来多了点,但是实际上,每一个代码执行部分都被封装了起来,只留了Deferred的接口处理了,等于是我们把执行的流程控制交给了Deferred,这样的好处就是我们在写嵌套函数的时候,可以用deferred提供的管道风格编写同步代码了

dtd.then(function() {
   //操作1
}).then(function() {
   //操作2
}).then(function() {
  //操作3
})

这里要了解3个步骤

var dtd = $.Deferred();  //创建
dtd.resolve();          //成功
dtd.then()              //执行回调

4. 视差效果

以小男孩走路变化,页面就跟着变化,两个元素用不同的速率变化就会产生视觉差的效果,感觉人物就是走了几个页面

其中需要注意

  • 小男孩的走路区间只是一个页面单位,相对点是父级的div
  • 页面滚动只有二个页面单位,因为本身会占据一个

注意以上这两点主要是为了设置比例的问题

  • 小男孩如果走到中间位置,那么比例是0.5 换算下就是  0.5*页面宽度
  • 页面要到中间位置就是,比例是1,换算就是 1*页面宽度
var config={//增加前面配置
setTime:{
	walkToThird:6000,
	walkToMiddle:6500,
	walkToEnd:6000,
	walkTobridge:2000,
	bridgeWalk:2000,
	walkToShop:1500,
	walkOutShop:1500,
	openDoorTime:800,
	shutDoorTime:500,
	waitRotate:850,
	waitFlower:800}
}
boy.walkTo(config.setTime.walkToThird,0.6).then(function(){
			scrollTo(config.setTime.walkToMiddle,1);
			return boy.walkTo(config.setTime.walkToMiddle,0.5);
		})

5. 太阳动画、云动画

CSS3的animation会有8个属性去定义一个动画的一些参数

animation-name
规定要绑定的keyframes的名称,随便你取,不过为了日后维护的方便,建议取一个跟动作相关名称相近的名称比较好
animation-duration
规定完成这个动画所需要的时间
animation-iteration-count
动画播放次数,默认值为1,infinite为无限制,假如设置为无限制,那么动画就会不停地播放
元素的布局上,我都是保留的原尺寸,如果需要自适应,单独可以用百分比控制,通过background-size 一般可以设置 100% 100%的方式平铺元素,这样设置后图片就能自适应大小缩放了

6. 开门关门--开灯关灯

开门关门的效果比较简单,用transition插件可以实现

在实现的时候还需要注意几个问题

  • 开关门是2组动画,需要2组transition的实现
  • 开关门是否完成,是需要监听2个动画是否完成才可以
  • 为了支持线性编程的逻辑,需要通过Deferred改善代码

开门的left的坐标是往反向变化,所以变化的值是:

  • 左边0%到-50%  
  • 右边50%到100%

关门的left还原到0%与50%即可。

在开门的同时会有一个灯光的变化,开门灯亮,关门灯灭,这个动作本身不难,主要是配合开关门之后的一个效果,需要依赖开关门的事件回调

由于开关门的代码封装了Deferred,很容易添加这个效果的逻辑

代码实现部分:

//开门
openDoor().then(function() {
    //开灯
    lamp.bright();
})
//关门
shutDoor().then(function() {
    //灯灭
    lamp.dark();
});

通过融入Deferred对象,我们可以很好的控制这个逻辑了,在then中直接书写回调后的开灯效果了。

其他功能类似、不赘述

animation-fill-mode的属性,forwards的意思就是保留在最终的状态

7.飘花实现

实现原理:

通过定时器调用JS代码不断的动态创建雪花节点,随机选择一个图片作为其背景,赋予三个初始的样式属性top,left与opacity,通过transition动画过度的方式执行这3个属性的动画变化。整个原理其实也是很简单的,主要涉及了一些细节的问题:例如元素的创建、图片的随机、开始的left与opacity的随机处理、最终值的计算等等

执行的流程:

  • getImagesName随机6张图片,snowflakeURl定义一个地址的范围
  • createSnowBox创建雪花元素的节点,并且增加一个snowRoll的样式,也就是旋转的关键帧实现
  • 定时器设置200ms不断的生成雪花对象,计算出3个属性的初始值,通过createSnowBox创建雪花元素,并且附上初始值,然后执行transition附上最终值,执行动画
  • 动画结束后执行$(this).remove()  删除这个对象


8.音乐播放

var audio = new Audio(url);   //创建一个音频对象并传入地址
audio.loop  = loop ||  false; //是否循环
audio.play(); //开始播放


END






你可能感兴趣的:(前端相关)