文章目录
先写个打字特效
借助Vue完成变量的替换
因为之前觉得这个打字特效很好玩,但是字数不一样就要重写或者改代码,麻烦,之前就看到网上有一些自动生成代码的工具,很好奇怎么实现的?于是我就想能不能自己也写一个自动生成代码的网页,别光想,戴上耳机,音乐陪伴,行动起来,30分钟,完成了下面的300行代码,实现了这个功能,通过这个,你大概就能理解一些所谓简单复杂的工具,其实也不过如此,你也可以🏄🏼
先写个打字特效
首先先写一个固定字长的打字特效,这就很easy了,思路就是使用 ch单位,1ch表示一个字长,再借助等宽字体,开局宽度 0ch ,动画过渡到字长,借助伪元素实现打字时的小横杠,这里使用了 css 变量,因为方便后期对变量的替换以及维护,推荐👍🏼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>typora</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="shortcut icon" href="https://img.fy6b.com/2022/04/26/f8fd03d60efd6.png" type="image/x-icon"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } :root { --Length: 6ch; --num: 6; --Time: 3s; } body { display: flex; align-items: center; justify-content: center; min-height: 100vh; } p { position: relative; font-size: 60px; font-family: monospace; width: 0ch; overflow: hidden; white-space: nowrap; animation: Lengthen var(--Time) steps(var(--num)) forwards; } p::after { content: ""; position: absolute; right: 0; width: 2px; height: 100%; background-color: #454545; animation: Flash 1s infinite; } @keyframes Lengthen { to { width: var(--Length); } } @keyframes Flash { 50% { background-color: transparent; } } </style> </head> <body> <p>typora</p> </body> </html>
借助Vue完成变量的替换
接下来就是重点了,这里我使用了Vue框架,更快速点,原生js一样的,重点是获取css变量,根据输入的length为css变量从新赋值,然后通过字符串拼接,完成代码的重用,可能很笨,但说起来只能这样,哈哈,还有就是点击复制这个实现,通过input框,这里切记不要使用display隐藏input,而是使用opacity = 进行隐藏
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>在线生成打字特效</title> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="shortcut icon" href="http://zhouql.vip/images/ali/键盘,打字.png" type="image/x-icon"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { min-height: 100vh; } :root { --Length: 24ch; --num: 24; --Time: 4s; } #app { display: flex; flex-direction: column; align-items: center; justify-content: center; } .inputText { display: flex; align-items: center; justify-content: center; width: 90%; margin: 15px auto; } input { outline: none; width: calc(100% - 90px); height: 40px; text-indent: .3em; font-size: 14px; font-family: "Microsoft YaHei UI Light"; letter-spacing: .1em; border: 1px solid #69F; border-right: transparent; border-radius: 5px 0 0 5px; } button { border: none; background-color: #69F; height: 40px; width: 90px; color: #FFF; letter-spacing: .1em; padding: 5px; font-size: 16px; border-radius: 0 5px 5px 0; cursor: pointer; outline: none; font-family: "Microsoft YaHei UI Light"; } .code { position: relative; width: 90%; height: 30px; background-color: transparent; overflow: auto; } p { position: relative; font-size: 20px; font-family: monospace; width: 0ch; overflow: hidden; white-space: nowrap; animation: Lengthen var(--Time) steps(var(--num)) forwards; } p::after { content: ""; position: absolute; right: 0; width: 2px; height: 100%; background-color: #454545; animation: Flash 1s infinite; } @keyframes Lengthen { to { width: var(--Length); } } @keyframes Flash { 50% { background-color: transparent; } } .co { position: relative; width: 90%; height: calc(100vh - 250px); overflow: auto; border: 1px solid pink; } .co .copyButton { position: absolute; width: 80px; height: 30px; border-radius: 0px; top: 5px; right: 8px; font-size: 13px; } .preView { width: 90%; display: inline-block; text-align: left; padding: 10px 1px; font-size: 15px; color: #555; } footer { position: absolute; bottom: 0px; width: 100%; height: 30px; background-color: #f3f3f3; display: flex; align-items: center; justify-content: center; } footer span { font-size: 12px; color: #999; } footer span a { text-decoration: none; color: #008600; } [v-clock] { display: none; } </style> </head> <body> <div id="app"> <div class="inputText"> <input autofocus @input="cleanCode" maxlength="28" type="text" placeholder="输入字" v-model="typing"> <button @click="generateCode">生成代码</button> </div> <span class="preView" v-show="flag">预览</span> <div class="code" v-show="flag"> <p>{{zi}}</p> </div> <span class="preView viewCode" v-show="flag">源码</span> <div class="co" v-show="flag"> <button class="copyButton" @click="copyCode">点击复制</button> <pre> <code v-cloak id="copyCodeAll"> {{daziCode}} </code> </pre> </div> <input type="text" class="preCopyCode" style="opacity: 0;"> <footer> <span>学习使用,豫备案号 <a href="https://seo.chinaz.com/zhouql.vip">zhouql.vip</a></span> </footer> </div> <!--引入Vue2--> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <!--创建Vue实例对象--> <script> const vm = new Vue({ el: '#app', data: { //要打的字 typing: 'I Love You zhang yu miao', //决定显示还是隐藏 flag:false, zi: '', //待复制的代码 preCopyCode:'' }, computed: { daziCode() { return '\n' + '<!DOCTYPE html>\n' + '<html lang="en">\n' + '<head>\n' + ' <meta charset="UTF-8">\n' + ' <title>'+this.typing+'</title>\n' + ' <meta http-equiv="X-UA-Compatible" content="IE=edge">\n' + ' <meta name="viewport" content="width=device-width, initial-scale=1.0">\n' + ' <link rel="shortcut icon" href="https://img.fy6b.com/2022/04/26/f8fd03d60efd6.png" type="image/x-icon">\n' + ' <style>\n' + ' * {\n' + ' margin: 0;\n' + ' padding: 0;\n' + ' box-sizing: border-box;\n' + ' }\n' + '\n' + ' :root {\n' + ' --Length: '+this.typing.length+'ch;\n' + ' --num: '+this.typing.length+';\n' + ' --Time: '+(this.typing.length * 0.5)+'s;\n' + ' }\n' + '\n' + ' body {\n' + ' display: flex;\n' + ' align-items: center;\n' + ' justify-content: center;\n' + ' min-height: 100vh;\n' + ' }\n' + '\n' + ' p {\n' + ' position: relative;\n' + ' font-size: 60px;\n' + ' font-family: monospace;\n' + ' width: 0ch;\n' + ' overflow: hidden;\n' + ' white-space: nowrap;\n' + ' animation: Lengthen var(--Time) steps(var(--num)) forwards;\n' + ' }\n' + '\n' + ' p::after {\n' + ' content: "";\n' + ' position: absolute;\n' + ' right: 0;\n' + ' width: 2px;\n' + ' height: 100%;\n' + ' background-color: #454545;\n' + ' animation: Flash 1s infinite;\n' + ' }\n' + '\n' + ' @keyframes Lengthen {\n' + ' to {\n' + ' width: var(--Length);\n' + ' }\n' + ' }\n' + '\n' + ' @keyframes Flash {\n' + ' 50% {\n' + ' background-color: transparent;\n' + ' }\n' + ' }\n' + ' </style>\n' + '</head>\n' + '<body>\n' + '<p>'+this.typing+'</p>\n' + '</body>\n' + '</html>\n' } }, methods: { generateCode() { this.zi = this.typing; document.documentElement.style.setProperty("--Length", (this.typing.length) + 'ch'); document.documentElement.style.setProperty("--num", this.typing.length + ""); document.documentElement.style.setProperty("--Time", this.typing.length * 0.4 + "s"); if (this.typing.length != 0) { this.flag = true; } }, cleanCode() { this.flag = false; this.typing = this.typing.replace(/[^a-zA-Z .() 0-9;:""?{}=+-]/g, ''); }, copyCode() { let code = document.querySelector(".preCopyCode"); code.value = this.daziCode; code.select(); document.execCommand("Copy"); alert("复制成功") } } }) </script> </body> </html>