效果演示
HTML
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
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
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]);
})();