web前端实现下雪特效

本文采用typescript编写,最终效果和js代码见
https://codepen.io/HowieYoung/pen/YzGvRMg

css代码:
body占满整个屏幕,添加溢出隐藏

body,html {
     
  width: 100%;
  height: 100%;
  overflow: hidden;
}

Random,一个工具类

class Random {
     
    /**
     * 获得一个 [0,max)之内的随机数
     */
    public static nextInt(max: number): number {
     
        return Math.floor(Math.random() * max);
    }

    /**
     * 从array随机挑选一个并返回
     */
    public static itemOf(array: Array<any>): any {
     
        return array[Math.floor(Math.random() * array.length)];
    }
}

雪花类

class Snowflake {
     
    // 枚举一下雪花形状
    public static readonly SNOW_FLAKE_SHAPE: Array<string> = ['❉', '❈', '*', '✲', '❀', '❅', '❄', '❆', '❃', '❁', '❊', '✴', '❇', '✽', '✼']
    // 枚举一下雪花颜色
    public static readonly SNOW_FLAKE_COLOR: Array<string> = ["#ffec00", "#e8820c", "#ff0000", "#830ce8", "#0d7aff", "#ab2322", "green"]
    // 创建一个div
    private _elem = document.createElement(`div`)
    // 每一帧在x方向上的移动距离
    private _dx: number = 0
    // 每一帧在y方向上的移动距离
    private _dy: number = 0

    constructor() {
     
        // 使用fixed定位
        this._elem.style.position = 'fixed'
    }

    set left(left: number) {
      this._elem.style.left = `${
       left}px` }

    set top(top: number) {
      this._elem.style.top = `${
       top}px` }

    set shape(value: string) {
      this._elem.innerHTML = value }

    set color(value: string) {
      this._elem.style.color = value }

    set dx(value: number) {
      this._dx = value }

    set dy(value: number) {
      this._dy = value }

    get dx(): number {
      return this._dx }

    get dy(): number {
      return this._dy }

    get elem(): HTMLDivElement {
      return this._elem }

    get offsetLeft(): number {
      return this._elem.offsetLeft }

    get offsetTop(): number {
      return this._elem.offsetTop }
}

雪花工厂类

class SnowflakeFactory {
     
    /**
     * 生产一个随机的雪花
     * @param snowWidth
     */
    public getRandomSnowFlake(snowWidth: number): Snowflake {
     
        let snowflake = new Snowflake()
        // 随机挑选一种形状
        snowflake.shape = Random.itemOf(Snowflake.SNOW_FLAKE_SHAPE)
        // 随机挑选一个颜色
        snowflake.color = Random.itemOf(Snowflake.SNOW_FLAKE_COLOR)
        // 把初始状态设置到屏幕外
        snowflake.left = Random.nextInt(snowWidth)
        snowflake.top = -Random.nextInt(100)
        // 设置一下每帧运动的距离
        snowflake.dx = Random.nextInt(10) + 2
        snowflake.dy = Random.nextInt(10) + 2
        return snowflake
    }
}

雪类

class Snow {
     
    // 浏览器的宽
    private _width: number = document.body.clientWidth
    // 浏览器的高
    private _height = document.body.clientHeight
    // 最大雪花数量
    private _snowflakeNum: number
    // 用于储存雪花的数组
    private _snowflakeArray: Array<Snowflake> = new Array<Snowflake>()
    // 生产雪花的工厂
    private _snowflakeFactory: SnowflakeFactory = new SnowflakeFactory()

    // 默认最大雪花数量为100
    constructor(snowflakeNum: number = 100) {
     
        this._snowflakeNum = snowflakeNum;
    }

    public start(): void {
     
        // 雪花数量不足设定的最大的雪花数量,就产生雪花,每30ms进行一次判断
        setInterval(() => {
     
            if (this._snowflakeArray.length < this._snowflakeNum) {
     
                let snowflake = this._snowflakeFactory.getRandomSnowFlake(this._width * 2 / 3);
                // 把生产的雪花push到数组里去
                this._snowflakeArray.push(snowflake)
                // 把雪花渲染在dom中
                document.body.appendChild(snowflake.elem)
            }
        }, 30)
        // 移动屏幕上的所有雪花 每10ms移动一次
        setInterval(() => {
     
            for (let i = 0; i < this._snowflakeArray.length; i++) {
     
                // 判断雪花是否飘到屏幕外,如果是,则从dom中移除雪花
                if (this._snowflakeArray[i].elem.offsetLeft >= this._width || this._snowflakeArray[i].elem.offsetHeight >= this._height) {
     
                    document.body.removeChild(this._snowflakeArray[i].elem);
                    this._snowflakeArray.splice(i, 1);
                }
                // 移动雪花
                this._snowflakeArray[i].left = this._snowflakeArray[i].offsetLeft + this._snowflakeArray[i].dx
                this._snowflakeArray[i].top = this._snowflakeArray[i].offsetTop + this._snowflakeArray[i].dy
            }
        }, 10)

    }
}

new一场雪,然后start

new Snow().start()

最终效果

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