效果演示

HTML

 <div class="wrap">
    <div class="body"></div>
    <div class="ear"></div>
    <div class="ear rightEar"></div>
    <div class="leftHand"></div>
    <div class="rightHand"></div>
    <div class="leftFoot"></div>
    <div class="rightFoot"></div>
    <div class="heart"></div>
    <div class="greenFace"></div>
    <div class="blueFace"></div>
    <div class="pinkFace"></div>
    <div class="yellowFace"></div>
    <div class="blackFace"></div>
    <div class="leftEye"></div>
    <div class="rightEye"></div>
    <div class="nose"></div>
    <div class="mouth"></div>
    <div class="chin"></div>
</div>

CSS

body,
html {
    margin: 0;
    padding: 0;
    transform: scale(0.65);
}

body {
    width: 100vh;
    height: 100vh;
    background: linear-gradient(#adf, #ddd);
}

.wrap {
    position: relative;
    margin-left: 279px;
    margin-top: 139px;
    height: 948px;
    width: 837px;
}

.body {
    height: 100%;
    width: 100%;
    border: 16px solid #000;
    position: absolute;
    border-radius: 55% 55% 55% 55% / 50% 50% 60% 60%;
    top: 0;
    left: 0;
    background: #fff;
    z-index: 1;
}

.ear {
    width: 250px;
    height: 334px;
    position: absolute;
    top: 0;
    left: 55px;
    border: 16px solid #000;
    border-radius: 50% 60% 60% 50% / 50% 50% 50% 50%;
    background: #000;
    z-index: 0;
    transform: rotate(-20deg);
}

.rightEar {
    right: 55px;
    left: auto;
    transform: rotateY(180deg) rotate(-20deg);
}

.leftHand {
    position: absolute;
    z-index: 0;
    width: 223px;
    height: 362px;
    border-radius: 50%;
    background: #000;
    top: 280px;
    left: -140px;
    transform: rotate(-15deg);
}

.leftHand:after {
    position: absolute;
    top: 195px;
    content: '';
    width: 362px;
    height: 223px;
    background: #000;
    border-radius: 50%;
    transform: rotate(35deg);
}

.rightHand {
    position: absolute;
    right: -210px;
    top: 470px;
    z-index: 0;
    height: 223px;
    width: 223px;
    border-radius: 50%;
    background: #000;
}

.rightHand:after {
    position: absolute;
    top: -66px;
    left: -70px;
    background: #000;
    width: 220px;
    height: 223px;
    content: '';
    transform: rotate(-47deg);
    border-radius: 0 0 0 80%;
}

.leftFoot {
    position: absolute;
    top: 840px;
    left: 80px;
    width: 250px;
    height: 250px;
    border-radius: 50%;
    background: #000;
}

.leftFoot:after {
    position: absolute;
    z-index: 0;
    content: '';
    background: #000;
    height: 250px;
    width: 250px;
    left: 30px;
    top: -125px;
    transform: rotate(10deg);
    border-radius: 0% 50% 50% 0%;
}

.rightFoot {
    background: #000;
    width: 250px;
    height: 250px;
    position: absolute;
    top: 840px;
    right: 80px;
    border-radius: 50%;
}

.rightFoot:after {
    content: '';
    width: 250px;
    height: 250px;
    position: absolute;
    top: -125px;
    right: 28px;
    z-index: 0;
    background: #000;
    transform: rotate(-12deg);
    border-radius: 0% 0% 0% 50%;
}

.heart {
    width: 140px;
    height: 140px;
    position: absolute;
    top: 350px;
    left: -90px;
    z-index: 2;
}

.heart:before,
.heart:after {
    content: '';
    position: absolute;
    top: 0;
    width: 33px;
    height: 55px;
    background: red;
    border-radius: 55px 55px 0% 0%;
}

.heart:after {
    transform: rotate(45deg);
    right: 90px;
}

.heart:before {
    transform: rotate(-45deg);
    left: 0;
}

.greenFace {
    width: 661px;
    height: 517px;
    border: 10px solid #6cf078;
    border-radius: 60% 60% 50% 50% /70% 70% 50% 50%;
    position: absolute;
    top: 95px;
    left: 83px;
    z-index: 1;
}

.blueFace {
    width: 642px;
    height: 501px;
    border: 10px solid yellow;
    border-radius: 60% 60% 50% 50% /70% 70% 50% 50%;
    position: absolute;
    top: 103px;
    left: 92px;
    z-index: 1;
}

.pinkFace {
    width: 619px;
    height: 480px;
    border: 10px solid red;
    border-radius: 60% 60% 50% 50% /70% 70% 50% 50%;
    position: absolute;
    top: 113px;
    left: 104px;
    z-index: 1;
}

.yellowFace {
    width: 591px;
    height: 451px;
    border: 13px solid #335fe6;
    border-radius: 60% 60% 50% 50% /70% 70% 50% 50%;
    position: absolute;
    top: 125px;
    left: 115px;
    z-index: 1;
}

.blackFace {
    width: 567px;
    height: 422px;
    border: 13px solid #000;
    border-radius: 60% 60% 50% 50% /70% 70% 50% 50%;
    position: absolute;
    top: 137px;
    left: 126px;
    z-index: 1;
}

.leftEye {
    width: 168px;
    height: 222px;
    background: #000;
    border-radius: 50%;
    z-index: 2;
    transform: rotate(45deg);
    position: absolute;
    top: 222px;
    left: 180px;
}

.rightEye {
    width: 168px;
    height: 222px;
    background: #000;
    border-radius: 50%;
    z-index: 2;
    transform: rotate(-45deg);
    position: absolute;
    top: 222px;
    right: 180px;
}

.rightEye:after,
.leftEye:after {
    position: absolute;
    width: 84px;
    height: 84px;
    border: 8px solid #fff;
    border-radius: 50%;
    content: '';
    top: 28px;
    left: 35px;
}

.rightEye:after {
    left: auto;
    right: 35px;
}

.rightEye:before,
.leftEye:before {
    position: absolute;
    top: 64px;
    left: 64px;
    background: #fff;
    border-radius: 50%;
    content: '';
    width: 28px;
    height: 28px;
}

.rightEye:before {
    left: 70px;
    top: 56px;
}

.nose {
    width: 84px;
    height: 84px;
    background: #000;
    position: absolute;
    left: 50%;
    margin-left: -42px;
    top: 350px;
    z-index: 1;
    border-radius: 30%;
    transform: rotate(50deg) skewY(-10deg);
}

.nose:after {
    content: '';
    width: 103px;
    height: 108px;
    border-radius: 50%;
    border-top: 28px solid #fff;
    position: absolute;
    top: -17px;
    left: 0px;
    transform: rotate(-45deg) skewY(0deg);
}

.mouth {
    width: 265px;
    height: 120px;
    border: 14px solid #000;
    position: absolute;
    top: 400px;
    left: 50%;
    z-index: 1;
    margin-left: -140px;
    border-radius: 0% 0% 50% 50% / 0% 0% 100% 100%;
    border-top: none;
}

.mouth:after,
.mouth:before {
    content: '';
    position: absolute;
    width: 140px;
    height: 140px;
    background: #fff;
    top: -30px;
    transform: rotate(45deg);
}

.mouth:after {
    left: -60px;
}

.mouth:before {
    right: -60px;
}

.belly {
    width: 150px;
    height: 150px;
    position: absolute;
    top: 72%;
    left: 45%;
    margin-left: -25px;
    z-index: 1;
}

.belly img {
    width: 150px;
    height: 150px;
}

js

(() => {
    "use strict";
    const module = {
        138: (exports, module) => {
            class Snowflake {
                constructor(options = {}) {
                    this.isRain = options.isRain || false;
                    this.el = null;
                    this.dir = options.dir || "r";
                    this.width = 0;
                    this.maxWidth = options.maxWidth || 80;
                    this.minWidth = options.minWidth || 2;
                    this.opacity = 0;
                    this.x = 0;
                    this.y = 0;
                    this.z = 0;
                    this.sx = 0;
                    this.isSwing = false;
                    this.stepSx = 0.02;
                    this.swingRadian = 1;
                    this.swingStep = 0.01;
                    this.sy = 0;
                    this.maxSpeed = options.maxSpeed || 4;
                    this.minSpeed = options.minSpeed || 1;
                    this.quickMaxSpeed = options.quickMaxSpeed || 10;
                    this.quickMinSpeed = options.quickMinSpeed || 8;
                    this.quickWidth = options.quickWidth || 80;
                    this.quickOpacity = options.quickOpacity || 0.2;
                    this.windowWidth = window.innerWidth;
                    this.windowHeight = window.innerHeight;
                    this.init();
                }

                init(initOptions) {
                    let isQuick = Math.random() > 0.8;
                    this.isSwing = Math.random() > 0.8;
                    this.width = isQuick ? this.quickWidth : Math.floor(Math.random() * this.maxWidth + this.minWidth);
                    this.opacity = isQuick ? this.quickOpacity : Math.random();
                    this.x = Math.floor(Math.random() * (this.windowWidth - this.width));
                    this.y = Math.floor(Math.random() * (this.windowHeight - this.width));
                    if (initOptions && Math.random() > 0.8) {
                        this.x = -this.width;
                    } else if (initOptions) {
                        this.y = -this.width;
                    }
                    this.sy = isQuick ? Math.random() * this.quickMaxSpeed + this.quickMinSpeed : Math.random() * this.maxSpeed + this.minSpeed;
                    this.sx = "r" === this.dir ? this.sy : -this.sy;
                    this.z = isQuick ? 300 * Math.random() + 200 : 0;
                    this.swingStep = 0.01 * Math.random();
                    this.swingRadian = Math.random() * (1.1 - 0.9) + 0.9;
                }

                setStyle() {
                    this.el.style.cssText = `
                      position: fixed;
                      left: 0;
                      top: 0;
                      display: block;
                      width: ${this.isRain ? 1 : this.width}px;
                      height: ${this.width}px;
                      opacity: ${this.opacity};
                      background-image: radial-gradient(#fff 0%, rgba(255, 255, 255, 0) 60%);
                      border-radius: 50%;
                      z-index: 9999999999999;
                      pointer-events: none;
                      transform: translate(${this.x}px, ${this.y}px) ${this.getRotate(this.sy, this.sx)};
                  `;
                }

                render() {
                    this.el = document.createElement("div");
                    this.setStyle();
                    document.body.appendChild(this.el);
                }

                move() {
                    if (this.isSwing) {
                        if (this.swingRadian > 1.1 || this.swingRadian < 0.9) {
                            this.swingStep = -this.swingStep;
                        }
                        this.swingRadian += this.swingStep;
                        this.isRain ? this.x += this.sx : this.x += this.sx * Math.sin(this.swingRadian * Math.PI);
                        this.y -= this.sy * Math.cos(this.swingRadian * Math.PI);
                    } else {
                        this.x += this.sx;
                        this.y += this.sy;
                    }
                    if (this.x < -this.width || this.x > this.windowWidth || this.y > this.windowHeight) {
                        this.init(true);
                        this.setStyle();
                    }
                    this.el.style.transform = `translate3d(${this.x}px, ${this.y}px, ${this.z}px) ${this.getRotate(this.sy, this.sx)}`;
                }

                getRotate(sy, sx) {
                    return this.isRain ? `rotate(${0 === sx ? 0 : 90 + Math.atan(sy / sx) * (180 / Math.PI)}deg)` : "";
                }
            }

            class Snowfall {
                constructor(options = {}) {
                    this.num = options.num || 100;
                    this.opt = options;
                    this.snowList = [];
                    this.createSnows();
                    this.moveSnow();
                }

                createSnows() {
                    this.snowList = [];
                    for (let i = 0; i < this.num; i++) {
                        let snowflake = new Snowflake(this.opt);
                        snowflake.render();
                        this.snowList.push(snowflake);
                    }
                }

                moveSnow() {
                    window.requestAnimationFrame(() => {
                        this.snowList.forEach(snowflake => {
                            snowflake.move();
                        });
                        this.moveSnow();
                    });
                }
            }

            new Snowfall({
                isRain: true,
                num: 300,
                maxSpeed: 15
            });
            new Snowfall({
                isRain: false,
                num: 150
            });
        }
    };

    function extend(target, source) {
        for (let key in source) {
            if (source.hasOwnProperty(key) && !target.hasOwnProperty(key)) {
                target[key] = source[key];
            }
        }
        return target;
    }

    module[138].exports = module[138]({}, module[138]);
})();

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部