js+css实现星空动画

【今日文章】:使用js+css 实现星空效果

实现效果

先来看一下实现的动画效果

在这里插入图片描述

需求分析

1、我们需要捕捉一块天空,设置成黑色的夜空(一定宽高的黑色背景而已)。
2、在黑色的夜空中随机分布着一定数量的星星(其实就是若干张图片,我们用定位就能实现)。
3、有大星星小星星(图片宽度随机,高度自适应就可以了)。
4、星星交替在夜空中一眨一眨闪耀星光(我们使用animation给图片设置一个透明度渐变,动画给一个延时就行)

实现步骤

1、新建一个块,设置成黑色背景;

相信大家应该都知道怎么设置了,就不叙述了

2、在黑色的夜空中随机分布着一定数量的星星

首先给父元素设置相对定位,父元素包含若干个图片,每张图片设置绝对定位,图片的x轴坐标和y轴坐标随机,这里x、y值单位使用百分比,那么x、y值得大小范围就是0到100,另外每个图片还有一个最小间距。
我们使用类实现:

class Star {
 constructor(starQuantity,distancePercent = 6{
  	this.starQuantity = starQuantity
    this.distancePercent = distancePercent
  }
  initStar() {
    const xyArr = Star.getPointList(this.distancePercent)
    const starArr = Star.getStar(xyArr, this.starQuantity)
  }
  /**
   * 获取坐标
   * @params num: 坐标间距
   */
  static getPointList(num) {
    let x = num
    let y = num
    let maxX = 100 - num
    let maxY = 100 - num
    const arr = []
    while (y < maxY) {
      arr.push({
        x,
        y
      })
      x+= num
      if (x > maxX) {
        x = num
        y+= num
      }
    }
    // console.log('arr', arr)
    return arr
  }
  **
   * 随机获取一定数量的星星坐标
   * @params arr: 所有坐标
   * @params len: 坐标数组长度
   */
  static getStar(arr, len) {
    // 获取的最大长度不能超过坐标列表长度
    if (arr.length < len) {
      len = arr.length
    }
    const newArr = arr.slice(0)
    const leng = newArr.length - 1
    for(let i = 0; i< len; i++) {
      const index = Math.floor(Math.random() * (leng - i)) 
      const temp = newArr[leng - i]
      newArr[leng - i] = newArr[index]
      newArr[index] = temp
    }
    // console.log('arr===>', newArr.slice(-len))
    return newArr.slice(-len)
  }
}

3、给星星设置宽高

代码见第4步

4、星星交替在夜空中一眨一眨闪耀星光(我们使用animation给图片设置一个透明度渐变,动画给一个延时就行)

此步骤方法中添加了延时时间,星星动画通过css实现

// 我们需要新增方法
 /**
   * 设置星星大小和延迟时间
   * @params starArr: 坐标
   * @params widthArr: 宽度集合
   * @params delay: 最大延迟时间
   */
  getWidthAndDur(starArr, widthArr, delay = 2) {
    return starArr.map(item => {
      const index = Math.floor(Math.random() * widthArr.length)
      return {
        ...item,
        width: widthArr[index],
        delay: parseFloat(Math.random() * delay)
      }
    })
  }
  // 需要修改方法
  /**
   * @params distancePercent: 间距百分比
   * @params starQuantity: 要展示的星星数量
   * @params size: 星星尺寸width
   * @params delay: 星星最大延迟展示时间单位秒
   */
  constructor(starQuantity, distancePercent = 6, widthArr = [8, 12, 20], delay = 2) {
    this.starQuantity = starQuantity
    this.distancePercent = distancePercent
    this.widthArr = widthArr
    this.delay = delay
  }
  initStar() {
    const xyArr = Star.getPointList(this.distancePercent)
    const starArr = Star.getStar(xyArr, this.starQuantity)
    return this.getWidthAndDur(starArr, this.widthArr, this.delay)
  }

星星图片

在这里插入图片描述

完整vue文件

<template>
  <div class="receive-blind">
    <div class="receive-blind-star">
      <img 
        class="star"
        v-for="(item, index) in starArr" 
        :key="index" 
        src="./star.png"
        :style="{
          left: item.x + '%',
          top: item.y + '%',
          width: item.width + 'px',
          'animation-delay': item.delay + 's'
        }"
      >
    </div>
  </div>
</template>

<script>
import Star from './star'
export default {
  data() {
    return {
      starArr: new Star(80).initStar() // 星星数据
    }
  },
  created() {
  },
  methods: {
  },
}
</script>

<style lang="less" scoped>
  .receive-blind {
    width: 100%;
    height: 100%;
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1100;
    background: rgba(0,0,0,1);
    &-star {
      width: 100%;
      height: 100%;
      position: absolute;
      left: 0;
      top: 50%;
      transform: translateY(-50%);
      .star {
        position: absolute;
        opacity: 0.5;
        animation: starMove 3s ease-in-out infinite;
      }
    }
    .receive-block {
      width: 100%;
      position: absolute;
      left: 0;
      top: 50%;
      transform: translateY(-50%);
      text-align: center;
      
    }
  }
@keyframes starMove{
  0%{
    opacity: 0.1;
  }
  50% {
    opacity: 0.1;
  }
  75% {
    opacity: 1;
  }
  100%{
    opacity: 0.1;
  }
}

</style>

star类

// 
export default class Star {
  /**
   * @params distancePercent: 间距百分比
   * @params starQuantity: 要展示的星星数量
   * @params size: 星星尺寸width
   * @params delay: 星星最大延迟展示时间单位秒
   */
  constructor(starQuantity, distancePercent = 6, widthArr = [8, 12, 20], delay = 2) {
    this.starQuantity = starQuantity
    this.distancePercent = distancePercent
    this.widthArr = widthArr
    this.delay = delay
  }
  initStar() {
    const xyArr = Star.getPointList(this.distancePercent)
    const starArr = Star.getStar(xyArr, this.starQuantity)
    return this.getWidthAndDur(starArr, this.widthArr, this.delay)
  }
  /**
   * 获取坐标
   * @params num: 坐标间距
   */
  static getPointList(num) {
    let x = num
    let y = num
    let maxX = 100 - num
    let maxY = 100 - num
    const arr = []
    while (y < maxY) {
      arr.push({
        x,
        y
      })
      x+= num
      if (x > maxX) {
        x = num
        y+= num
      }
    }
    // console.log('arr', arr)
    return arr
  }
  /**
   * 随机获取一定数量的星星坐标
   * @params arr: 所有坐标
   * @params len: 坐标数组长度
   */
  static getStar(arr, len) {
    // 获取的最大长度不能超过坐标列表长度
    if (arr.length < len) {
      len = arr.length
    }
    const newArr = arr.slice(0)
    const leng = newArr.length - 1
    for(let i = 0; i< len; i++) {
      const index = Math.floor(Math.random() * (leng - i)) 
      const temp = newArr[leng - i]
      newArr[leng - i] = newArr[index]
      newArr[index] = temp
    }
    // console.log('arr===>', newArr.slice(-len))
    return newArr.slice(-len)
  }
   /**
   * 设置星星大小和延迟时间
   * @params starArr: 坐标
   * @params widthArr: 宽度集合
   * @params delay: 最大延迟时间
   */
  getWidthAndDur(starArr, widthArr, delay = 2) {
    return starArr.map(item => {
      const index = Math.floor(Math.random() * widthArr.length)
      return {
        ...item,
        width: widthArr[index],
        delay: parseFloat(Math.random() * delay)
      }
    })
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值