前端日常实战169#视频演示如何制作“数字单词”的交互动画(含2个视频)
时间:2023-04-02 19:37:41
HTML
效果预览点击右侧“点击预览”按钮可在当前页面进行预览,并单击链接以全屏预览。https://codepen.io/comehop??e/pen/byvRxB互动视频本视频为互动视频,您可以随时暂停视频,编辑视频中的代码。请使用chrome、safari、edge打开观看。视频1:https://scrimba.com/p/pEgDAM/cR4gpGsa视频2:https://scrimba.com/p/pEgDAM/czNp3MUZ源码下载每日前端实战系列全部源码请下载自github:https://scrimba.com/p/pEgDAM/czNp3MUZ://github.com/comehop??e/front-end-daily-challenges代码解读你见过像“i18n”和“a11y”这样的英文单词吗?它们其实是一些单词的缩写,“i18n”代表“internationalization”(国际化),“a11y”代表“accessibility”(可访问性),因为包含的字母太多,所以只保留缩写开头的字母和最后,然后在中间写下剩余的字符。这种写法叫做“Numeronym”,我把它翻译成“数字缩写”。据说最长的单词是“pneumonoultramicroscopicsilicovolcanoconiosis”,由45个字母组成,意思是肺部疾病。本项目将制作互动动画效果,使其可以在原词和“数字与缩写”之间切换。整个项目分两步开发。第一步是实现一个固定单词的交互动画,第二步是重写自动处理任意单词,然后扩展到多个单词。1、一个固定词的交互动画dom结构如下。最外层的容器名为.container,其中包含一个名为.word的
元素,代表一个单词,其子元素为4个
元素,分别代表单词的首字母、中间字符的个数(.middle.short),中间的几个字符(.middle.long),以及单词的最后一个字母。因为“中间的字符数”和“中间的字符数”在动画过程中会交替显示,所以为它们设置了特殊的类名,以便在后续的css代码中引用,当它们是要同时选中的共同类名中间,当你想分别选中时,指定它们各自的类名短和长:i
18
国际化n
使容器在页面居中:body{margin:0;高度:100vh;显示:弹性;对齐项目:居中;证明内容:居中;背景图像:线性渐变(浓汤,浅青色);}让4个
标签中包含的文本水平排列在容器中间:.container{width:100%;}.word{font-size:35px;字体系列:等宽;显示:弹性;justify-content:center;}为中间两个
元素的文本着色以突出显示它们:.middle{color:tomato;}接下来,创建一个交互式动画。先隐藏中间的一些字符,只显示中间的字符数,找到html代码中的.middle.long元素,给它添加一个隐藏样式类:在css中,添加.middle.hide元素的宽度设置为0,超出容器的部分不显示:.middle{overflow:hidden;}.middle.hide{width:0;}当鼠标悬停在word上,鼠标指针变成一只手,提示用户此时点击:.word:hover{cursor:pointer;}给.word元素添加鼠标点击事件。当点击单词时,中间的两个元素分别切换隐藏类,交替显示的两个元素,这些代码都写在一个叫做initWordElement()的方法中。init()方法在页面加载时执行,并在其中调用initWordElement()方法。initWordElement()方法并不是直接在window.onload上执行的,而是通过init()调用的,因为在页面初始化阶段还会做一些其他的操作,后面会逐步丰富init()方法:window.onload=initfunctioninit(){letel=document.querySelector('.word')initWordElement(el)}functioninitWordElement(el){letmiddles=el.querySelectorAll('.middle')el.onclick=()=>中间。forEach(m=>m.classList.toggle('hide'))}现在在页面中多次点击单词,可以看到单词的中间部分在不断切换,但是没有动画效果这个时候,再添加切换缓动效果。首先设置中间两个元素的宽度。这两个数值是通过人工测量得到的。这不是最终的写法。后面我们会把元素的宽度改为脚本自动测量,但是因为我们现在要解决的是动画效果,所以先暂时硬编码一下:添加easing:.middle{transition:1s;}.middle.short{width:42px;}.middle.long{width:378px;}设置缓动持续时间为1秒:.middle{transition:1s;}现在,点击单词时的过渡效果已经有了动画过程,并且接下来将细化动画效果。Transition可以理解为由2个action组成:一个中间元素消失,另一个中间元素出现。这种效果是通过增加缓动延迟来实现的:.middle{transition:1s;transition-delay:1s;}.middle.hide{transition:1s;}现在改变元素的宽度时,宽度是从元素的左侧开始改变的,不够美观。我们把它改成从中间点开始改变宽度,这样当元素变宽时,它会向两边的Extend移动,当元素变窄时会收缩到中间:.middle{position:relative;}.middle跨度{位置:绝对;转换:translateX(0);过渡:1s;过渡延迟:1s;}。middle.hidespan{变换:translateX(-50%);transition:1s;}接下来,将easingduration从1s修改为0.5s,即动画速度加倍。为了方便调试和维护,我们将时长的值定义为一个变量--t:.word{--t:0.5s;}.middle{transition:var(--t);transition-delay:var(--t);}.middlespan{transition:var(--t);transition-delay:var(--t);}.middle.hide{transition:var(--t);}.middle.hidespan{transition:var(--t);}至此,动画效果完成了。2.将应用扩展到多个单词“数字缩写”有很多。为了一次显示多个单词,我们将扩展现有程序。首先介绍lodash库,我们会使用它提供的一个模板函数来处理html模板:扩展了dom结构,.container容器将不仅仅包含一个.word元素,而是包含多个.word元素。创建一个html模板,内容为.word元素的代码,包括第一个字母,中间字符个数,中间几个字符,最后一个字母。这些内容分别通过变量first、middleLength、middle、last在模板中使用:和原来的.container元素中的内容必须删除动态填充:
写一个函数namedgetWordObject()获取一个word对象,输入是一个word,比如“internationalization”,输出是一个对象,其属性对应html模板中的变量:functiongetWordObject(w){return{first:w.slice(0,1),last:w.slice(-1),middle:w.slice(1,-1),middleLength:w.slice(1,-1).length,}}接下来写一个方法调用createWordElement()创建一个.word元素,该方法中使用了lodash的_.template()模板函数。这个方法的输入是一个单词,它会被传递给getWordObject()函数:)el.className='word'el.innerHTML=_.template(TEMPLATE)(getWordObject(word))returnel}在负责页面初始化的init()方法中调用createWordElement()方法。整个流程改为先创建一个元素,然后把元素添加到.container容器中,然后初始化元素:functioninit(){letword='internationalization'letel=createWordElement(word)document.querySelector('.container').appendChild(el)initWordElement(el)}现在,运行页面,虽然运行效果没有变化,但是css属性和页面元素都变成动态生成了。如果将init()方法中的单词变量值更改为其他单词,例如“accessibility”,页面上将显示“a11y”。但是单词改成“a11y”后,中间元素占用的宽度不正确。这是因为之前中间元素的宽度是硬编码的,需要通过脚本来赋值。先删除css中的这两行代码:/*.middle.short{width:42px;}.middle.long{width:378px;}*/然后给.middle元素设置width属性,属性值为named--wvariable:.middle{width:var(--w);}然后在initWordElement()方法中添加一行,给变量--w赋值:functioninitWordElement(el){letmiddles=el.querySelectorAll('.middle')middles.forEach(m=>m.style.setProperty('--w',window.getComputedStyle(m.querySelector('span')).width))el.onclick=()=>middles.forEach(m=>m.classList.toggle('hide'))}好了,现在无论替换成什么词,都可以正常显示了。至此,单个词的动态转换就完成了。接下来请孙大胜拔几根毳毛,帮我们把一个字变成多个字。修改init()方法,删除word变量,定义一个名为WORDS的数组,遍历数组,为数组中的每个单词创建一个.word元素:functioninit(){constWORDS=['localization','accessibility','internationalization','supercalifragilisticexpialidocious','pneumonoultramicroscopicsilicovolcanoconiosis']WORDS.forEach(word=>{letel=createWordElement(word)document.querySelector('.container').appendChild(el)initWordElement(el)}}现在页面上有5个字,点击那个“p43s”可以看到世界上最长的字。最后因为
元素的边距比较大,调整小一点,这样竖排的字排列得更紧凑:.wordp{margin:0.3em0;}大功告成!