放飞孔明灯

我们都知道在很多地方都有元宵节放孔明灯的习惯,但是近年来,一些地方因为环境和安全考虑,开始限制或禁止放孔明灯,以避免火灾和环境污染等问题。于是我就是手写了一个孔明灯放飞的动画,来弥补大家的遗憾。

动画

jcode

HTML源码

<div class="container">
  <section class="z-100">
    <div class="blur">
    <img class="lantern l9" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cd0ea77244db4b4f81d1342ecb7da38d~tplv-k3u1fbpfcp-image.image#?w=109&amp;h=121&amp;s=7562&amp;e=svg&amp;a=1&amp;b=cc793a" alt="孔明灯" />
    </div>
    <img class="lantern l10" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cd0ea77244db4b4f81d1342ecb7da38d~tplv-k3u1fbpfcp-image.image#?w=109&amp;h=121&amp;s=7562&amp;e=svg&amp;a=1&amp;b=cc793a" alt="孔明灯" />
  </section>
  <section class="cloud-wrap">
   <img class="cloud c4" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5251241ced334d3db28f54a47e71389d~tplv-k3u1fbpfcp-image.image#?w=103&amp;h=45&amp;s=1482&amp;e=svg&amp;a=1&amp;b=14243a" alt="" />
  </section>
  <aside class="land"><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7353a091fac64b5aa0650e3068fd95c8~tplv-k3u1fbpfcp-image.image#?w=521&amp;h=69&amp;s=85120&amp;e=svg&amp;a=1&amp;b=13263d" alt="地面" />
  </aside>
</div>

源码设计分析

我们先编写一个html页面来为我们的孔明灯升起设施背景框架

  1. 首先我们先定义一个<div class="container">容器,用来存放我们所有的元素和内容,通过container来控制网页的布局和样式。

  2. 然后我们定义一个<section> 元素,用来放置我们的孔明灯。

    • 内部包含了一个带有 <div> 元素,可能用于添加模糊效果。

    • <div> 元素里面包含我们的孔明灯图片,这里我们放置多张

  3. 云的部分我们使用<section class="cloud-wrap">元素来存载。我们在里面存放我们的云的图片,这里放置多张。

  4. 地面部分我们使用<aside class="land">元素来存载,我们在里面存放我们的地面的图片 。

scss源码

$bg-light: #243C54
$bg-dark: #091726

html, body, .container, section
	width: 100%
	height: 100vh
	overflow: hidden

.container
	position: relative
	background: $bg-dark
	background: linear-gradient(180deg, $bg-dark 0%, $bg-light 100%)

section
	position: absolute
	top: 0
	right: 0
	bottom: 0
	left: 0
	&.z-100
		z-index: 100

.land
	position: absolute
	right: 0
	bottom: -.5rem
	left: 0
	z-index: 999
	img
		width: 101vw
	.copyright
		position: absolute
		right: 1rem
		left: 1rem
		bottom: 1rem
		display: flex
		justify-content: space-between
		font-size: 12px
		@media screen and (max-width: 640px)
			flex-wrap: wrap
	a
		text-decoration: none
		color: rgba(#FFF, .8)



// 孔明灯
$bg-light: #243C54
$bg-dark: #091726

html, body, .container, section
	width: 100%
	height: 100vh
	overflow: hidden

.container
	position: relative
	background: $bg-dark
	background: linear-gradient(180deg, $bg-dark 0%, $bg-light 100%)

section
	position: absolute
	top: 0
	right: 0
	bottom: 0
	left: 0
	&.z-100
		z-index: 100

.land
	position: absolute
	right: 0
	bottom: -.5rem
	left: 0
	z-index: 999
	img
		width: 101vw
	.copyright
		position: absolute
		right: 1rem
		left: 1rem
		bottom: 1rem
		display: flex
		justify-content: space-between
		font-size: 12px
		@media screen and (max-width: 640px)
			flex-wrap: wrap
	a
		text-decoration: none
		color: rgba(#FFF, .8)



// 孔明灯
@keyframes lantern-rise
	0%
		transform: translate(0, 0) rotate(0deg)
	30%
		transform: translate(20%, -40vh) rotate(10deg)
	50%
		transform: translate(-30%, -90vh) rotate(-10deg)
	70%
		opacity: 1
		transform: translate(20%, -115vh) rotate(10deg)
	90%
		opacity: 1
		transform: translate(10%, -130vh) rotate(5deg)
	100%
		opacity: 0
		transform: translate(0, -140vh) rotate(-10deg)

.lantern
	position: absolute
	animation: lantern-rise infinite linear

@for $i from 1 through 300
	$posX: random() * 90%
	$posY: random() * 100% + 90%
	$random: random(100) + 16
	$second: abs(($random / 1.2) - 150) + s
	$delay: $i * -.1s
	$size: $random + px
	$sizeM: $random / 2 + px
	$abs: $random / 100
	$g: abs($random / 100 * 100% - 100%)
	.l#{$i}
		top: $posY
		left: $posX
		z-index: $random
		max-width: $size
		filter: grayscale($g)
		animation-duration: $second
		animation-delay: $delay
	.blur .l#{$i}
		@if $random % 2 == 0 & $random > 40
			filter: blur(7px)
	@media screen and (max-width: 640px)
		.l#{$i}
			max-width: $sizeM



// 云
@keyframes cloud-move-left
	5%
		opacity: 1
	100%
		transform: translateX(100vw)

@keyframes cloud-move-right
	5%
		opacity: 1
	100%
		transform: translateX(-100vw) rotateY(180deg)
	
.cloud-wrap
	.cloud
		position: absolute
		opacity: 0
	.cloud:nth-of-type(odd)
		animation: cloud-move-left linear infinite
	.cloud:nth-of-type(even)
		transform: translateX(100vw) rotateY(180deg)
		animation: cloud-move-right ease-in-out

@for $x from 1 through 20
	$posY: random() * 20% + 40%
	$z: random(30)
	$random: random(100)
	$size: ($random + 50) + px
	$sizeM: $random / 2 + px
	$second: ($z + 100) + s
	$delay: ($x * random(10)) + s
	.cloud-wrap .cloud.c#{$x}
		top: $posY
		z-index: $z
		max-width: $size
		animation-duration: $second
		animation-delay: $delay
	@media screen and (max-width: 640px)
		.cloud-wrap .cloud.c#{$x}
			max-width: $sizeM

源码设计分析

  • 首先,我们先定义了两个颜色变量 $bg-light$bg-dark,分别用于定义我们的浅色背景和深色背景
  1. 然后我们要修改我们浏览器的默认样式,html, body, .container, section修改成,

    • widthheight 设置为 100%,使它们占据整个可视窗口的宽度和高度。
    • overflow: hidden 隐藏了元素的溢出内容。
  2. 我们定义.container采用相对定位,背景色采用了一个深色到浅色的线性渐变

  3. 我们定义section采用绝对定位,占满父容器。

    • 并且.z-100 类设置 z-index 为 100
  4. 设置.land地面,采用绝对定位。使用元素固定在底部

接下来是我们最核心的动画,也就是孔明灯放飞的部分。

核心动画

首先我们要定义一个控制了孔明灯升起的关键帧动画 lantern-rise,来控制了孔明灯升起的动画效果。

@keyframes lantern-rise
	0%
		transform: translate(0, 0) rotate(0deg)
	30%
		transform: translate(20%, -40vh) rotate(10deg)
	50%
		transform: translate(-30%, -90vh) rotate(-10deg)
	70%
		opacity: 1
		transform: translate(20%, -115vh) rotate(10deg)
	90%
		opacity: 1
		transform: translate(10%, -130vh) rotate(5deg)
	100%
		opacity: 0
		transform: translate(0, -140vh) rotate(-10deg)
  • 0%:初始状态,孔明灯保持最初位置。
  • 30%:在 30% 的时候,向右平移20%的宽度,向上平移40vh(视窗高度的百分比),并顺时针旋转了10度。
  • 50%:在 50% 的时候,左平移30%的宽度,向上平移90vh,同时逆时针旋转了10度。
  • 70%:在 70% 的时候,孔明灯的透明度变为1,将孔明灯向右平移20%的宽度,向上平移115vh,并以10度的角度顺时针旋转。
  • 90%:在 90% 的时候,孔明灯继续向上移动,透明度保持为1,将孔明灯向右平移10%的宽度,向上平移130vh,并以5度的角度顺时针旋转。
  • 100%:最终状态,透明度变为0,孔明灯回到初始位置下方,向上平移140vh,并以-10度的角度逆时针旋转。
	position: absolute
	animation: lantern-rise infinite linear

给的孔明灯添加.lantern 类,并且设置为无限循环播放,线性过渡。

循环孔明灯

我们可以使用 Sass 的控制流语法,在一个循环中生成了一系列的孔明灯(lantern)元素,并且随机属性让得孔明灯看起来分布随机,大小和动画速度各异。

  1. @for $i from 1 through 300:,我们循环生成300个孔明灯元素。

  2. 在每次循环迭代中,都进行随机设置了值

    • $posX:随机的水平位置,位于页面宽度的90%内。
    • $posY:随机的垂直位置,位于页面高度的90%以上。这会使孔明灯从屏幕底部开始升起。
    • $random:随机数,取值范围从16到115(100+16),用于确定其他随机属性。
    • $second:根据随机数计算的动画持续时间,单位为秒。
    • $delay:动画延迟时间,通过每次循环迭代的 $i 值生成,每个孔明灯的延迟递减0.1秒。
    • $size:随机的孔明灯大小,以像素为单位。
    • $sizeM:随机的孔明灯大小,用于小屏幕设备,大小是正常大小的一半。
    • $abs:随机的透明度,介于0到1之间。
    • $g:随机的灰度滤镜强度,用于使孔明灯变得灰色。
  3. 定义一个.l#{$i}:选择器,因为我们生成的孔明灯元素会具有类名 从.l1.l300,类名中的数字根据我们当前循环的 $i 值而变化。这样我们可以为每个孔明灯元素定义不同的样式。

  4. 然后我们孔明灯元素的样式定义中,会根据以下样式属性随机变量进行设置:

    • topleft:分别设置孔明灯的随机垂直和水平位置。
    • z-index:设置孔明灯的随机堆叠顺序。
    • max-width:设置孔明灯的随机最大宽度。
    • filter:设置孔明灯的随机灰度滤镜强度。
    • animation-duration:设置孔明灯的动画持续时间。
    • animation-delay:设置孔明灯的动画延迟。

然后我们要给符合条件的孔明灯添加模糊效果

	.blur .l#{$i}
		@if $random % 2 == 0 & $random > 40
			filter: blur(7px)
	@media screen and (max-width: 640px)
		.l#{$i}
			max-width: $sizeM

这里我们定义一个模糊样式.blur .l#{$i},当$random 是偶数且大于40,就会为孔明灯应用模糊效果。

  • 在这里,如果 $random 是偶数且大于40,就会为孔明灯应用模糊效果,filter: blur(7px)

在这里我们要进行一个屏幕适配,进行一个媒体查询,用于针对小屏幕设备设置特定的样式。

如果是小于640px的屏幕.l#{$i} 孔明灯元素的 max-width 会根据 $sizeM 改变,

云的动画

我们定义两个云的动画 cloud-move-leftcloud-move-right,分别用于云向左和向右移动。

cloud-move-left(向左)
@keyframes cloud-move-left
	5%
		opacity: 1
	100%
		transform: translateX(100vw)
  • 5%:初始状态,透明度为1,云的位置不发生变化。
  • 100%:最终状态,云通过 transform 属性在水平方向上向右移动了整个视窗的宽度,即 translateX(100vw)
cloud-move-right向右
@keyframes cloud-move-right
	5%
		opacity: 1
	100%
		transform: translateX(-100vw) rotateY(180deg)
  • 5%:初始状态,透明度为1,云的位置不发生变化。
  • 100%:最终状态,云通过 transform 属性在水平方向上向左移动了整个视窗的宽度,同时发生了180度的Y轴旋转,即 translateX(-100vw) rotateY(180deg)

分两部控住云

.cloud-wrap
	.cloud
		position: absolute
		opacity: 0
	.cloud:nth-of-type(odd)
		animation: cloud-move-left linear infinite
	.cloud:nth-of-type(even)
		transform: translateX(100vw) rotateY(180deg)
		animation: cloud-move-right ease-in-out
  1. .cloud-wrap 类:

    • position: absolute:设置云元素的定位方式为绝对定位,这样它们可以自由定位在父元素内。
    • opacity: 0:设置初始时云元素的不透明度为0,即完全透明。
  2. .cloud:nth-of-type(odd).cloud:nth-of-type(even)

    • 这些选择器选择了云元素中的奇数和偶数项。这是为了使奇数项的云元素应用 cloud-move-left 动画,而偶数项的云元素应用 cloud-move-right 动画。
  3. .cloud:nth-of-type(odd)

    • animation: cloud-move-left linear infinite:为奇数项的云元素应用 cloud-move-left 动画效果,使用线性时间函数(linear)并设置为无限循环(infinite)。
  4. .cloud:nth-of-type(even)

    • transform: translateX(100vw) rotateY(180deg):将偶数项的云元素初始时移动到页面的右侧,同时进行180度的Y轴旋转,以实现出现在页面的右侧并以不同的方向移动。
    • animation: cloud-move-right ease-in-out:为偶数项的云元素应用 cloud-move-right 动画效果,使用 ease-in-out 时间函数,也设置为无限循环。

循环云动画

@for $x from 1 through 20
	$posY: random() * 20% + 40%
	$z: random(30)
	$random: random(100)
	$size: ($random + 50) + px
	$sizeM: $random / 2 + px
	$second: ($z + 100) + s
	$delay: ($x * random(10)) + s
	.cloud-wrap .cloud.c#{$x}
		top: $posY
		z-index: $z
		max-width: $size
		animation-duration: $second
		animation-delay: $delay
	
  • @for $x from 1 through 20:我们要循环将生成20个云元素。

  • 在每次循环迭代中,都进行随机设置了值

    • $posY:随机的垂直位置,位于页面高度的40%以上,最多不超过60%。
    • $z:随机的 z-index 值,最大为30。
    • $random:随机数,取值范围从0到99(100-1),用于确定其他随机属性。
    • $size:随机的云元素大小,通过将随机数加上50,然后加上 px 单位。
    • $sizeM:用于小屏幕设备的随机云元素大小,是正常大小的一半。
    • $second:根据随机数 $z 计算的动画持续时间,单位为秒,范围为100秒到130秒。
    • $delay:动画延迟时间,通过每次循环迭代的 $x 值和随机数生成,每个云元素的延迟时间不同。
  • 定义一个.cloud-wrap .cloud.c#{$x}:选择器,因为我们生成的云元素会具有类名 从.c1.c20,类名中的数字根据我们当前循环的 $x 值而变化。这样我们可以为每个云元素定义不同的样式。

  • 然后我们云元素的样式定义中,会根据以下样式属性随机变量进行设置:

    • top:设置云元素的垂直位置为随机的 $posY。
    • z-index:设置云元素的 z-index 值为随机的 $z,决定了它们的堆叠顺序。
    • max-width:设置云元素的最大宽度为随机的 $size,使它们具有不同的大小。
    • animation-duration:设置云元素的动画持续时间为随机的 $second,使它们有不同的速度。
    • animation-delay:设置云元素的动画延迟时间为随机的 $delay,使它们的动画开始时间不同。
    • @media screen and (max-width: 640px):这是一个媒体查询,用于针对小屏幕设备设置特定的样式。
@media screen and (max-width: 640px)
		.cloud-wrap .cloud.c#{$x}
			max-width: $sizeM

在这里我们要进行一个屏幕适配,进行一个媒体查询,用于针对小屏幕设备设置特定的样式。

如果是小于640px的屏幕.cloud-wrap .cloud.c#{$x} 云元素的 max-width 会根据 $sizeM 改变,

  • 18
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zayyo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值