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