<! DOCTYPE html >
< html lang = " en" >
< head>
< meta charset = " UTF-8" >
< title> 文本变形动画</ title>
< link rel = " stylesheet" href = " ./style.css" >
</ head>
< body>
< div id = " container" >
< span id = " text1" > </ span>
< span id = " text2" > </ span>
</ div>
< svg id = " filter" >
< defs>
< filter id = " threshold" >
< feColorMatrix in = " SourceGraphic"
type = " matrix"
values = " 1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 255 -140" />
</ filter>
</ defs>
</ svg>
< script src = " ./script.js" > </ script>
</ body>
</ html>
@import url ( 'https://fonts.googleapis.com/css?family=Raleway:900&display=swap' ) ;
body {
margin : 0px;
}
#container {
position : absolute;
margin : auto;
width : 100vw;
height : 80pt;
top : 0;
bottom : 0;
filter : url ( #threshold) blur ( 0.6px) ;
}
#text1, #text2 {
position : absolute;
width : 100%;
display : inline-block;
font-family : 'Raleway' , sans-serif;
font-size : 80pt;
text-align : center;
user-select : none;
}
const elts = {
text1 : document. getElementById ( "text1" ) ,
text2 : document. getElementById ( "text2" ) } ;
const texts = [
"Can" ,
"I" ,
"have" ,
"one" ,
"click" ,
"triple?"
] ;
const morphTime = 1 ;
const cooldownTime = 0.25 ;
let textIndex = texts. length - 1 ;
let time = new Date ( ) ;
let morph = 0 ;
let cooldown = cooldownTime;
elts. text1. textContent = texts[ textIndex % texts. length] ;
elts. text2. textContent = texts[ ( textIndex + 1 ) % texts. length] ;
function doMorph ( ) {
morph -= cooldown;
cooldown = 0 ;
let fraction = morph / morphTime;
if ( fraction > 1 ) {
cooldown = cooldownTime;
fraction = 1 ;
}
setMorph ( fraction) ;
}
function setMorph ( fraction ) {
elts. text2. style. filter = ` blur( ${ Math. min ( 8 / fraction - 8 , 100 ) } px) ` ;
elts. text2. style. opacity = ` ${ Math. pow ( fraction, 0.4 ) * 100 } % ` ;
fraction = 1 - fraction;
elts. text1. style. filter = ` blur( ${ Math. min ( 8 / fraction - 8 , 100 ) } px) ` ;
elts. text1. style. opacity = ` ${ Math. pow ( fraction, 0.4 ) * 100 } % ` ;
elts. text1. textContent = texts[ textIndex % texts. length] ;
elts. text2. textContent = texts[ ( textIndex + 1 ) % texts. length] ;
}
function doCooldown ( ) {
morph = 0 ;
elts. text2. style. filter = "" ;
elts. text2. style. opacity = "100%" ;
elts. text1. style. filter = "" ;
elts. text1. style. opacity = "0%" ;
}
function animate ( ) {
requestAnimationFrame ( animate) ;
let newTime = new Date ( ) ;
let shouldIncrementIndex = cooldown > 0 ;
let dt = ( newTime - time) / 1000 ;
time = newTime;
cooldown -= dt;
if ( cooldown <= 0 ) {
if ( shouldIncrementIndex) {
textIndex++ ;
}
doMorph ( ) ;
} else {
doCooldown ( ) ;
}
}
animate ( ) ;