Hello 小伙伴们早上、中午、下午、早晨和深夜好,这里是 jsliang~
新年新气象,让咱们耍一个兔飞猛进的祝愿吧:
这个是一个残缺的线上小实例,小伙伴们能够填写数据,服务器会用 Node.js 定期读取数据:
- 填写数据:https://kdocs.cn/l/cbmawranzvNL
- 成果查看:https://liangjunrong.github.io/
例如你填的用户名称是:abab
,那么你的链接就是:https://liangjunrong.github.io?username=abab
本期将和小伙伴们探讨:
- [x] 如何通过 HTML + 海量 CSS + 简略 JS,实现这个兔年祝愿实例
- [x] 如何通过 Node.js,开启无头浏览器读取「金山文档」的数据,同步到 GitHub Page 上
本实例的代码地址:
- Demo —— all for one
- 码上掘金 - 02 - 2023 兔年祝愿
一 前言
本 CSS 系列文章:
- 主推学以致用。联合面试题和工作实例,让小伙伴们深刻体验 61 个工作常见的 CSS 属性和各种 CSS 常识。
- 主推纯 CSS。尽可能应用 HTML + CSS 实现学习目标,但依然有 “一小部分” 性能须要用到 JavaScript 常识,适宜新人学习 + 大佬温习。
如果文章在一些细节上没写分明或者误导读者,欢送评论/吐槽/批评,你的点赞、珍藏和关注是我更新的能源 ❤
- 更多常识分享文章可见:jsliang 的文档库
二 前端实现
本实例的一些创意,参考自 Jamie Juviler 提供的 24 个 CSS 动画,从中失去启发创作了这封信,在此示意非常感谢:
- 24 Creative and Unique CSS Animation Examples to Inspire Your Own
参考成果:
- 鼠标 hover 文本成果:《CSS Mouse Hover Transition Effect》
- 三个点:《Three Dots Loading》
- 信封:《Opening Envelope》
OK,那么咱们对着文件划分以及最终渲染实例,「简明扼要」讲讲界面是如何实现的:
- 02 - 2023 兔飞猛进 - css —— 样式表 - heart.css —— 心脏款式 - index.css —— 次要款式 - letter-content.css —— 信封款式 - letter-image.css —— 函件款式 - tips.css —— 下方提醒款式 - js —— JS - index.js —— 次要援用 JSindex.html —— 首页 HTML
2.1 跳动的心脏
如何通过一个简略的 <div>
实现跳动的心脏?
<div class="heart"></div>
其实很简略:
- 先实现一个 200*200 大小的正方形,并旋转 45°
- 通过
::before
,实现一个 100*200 的矩形,并通过border-radius
设置圆角,做成右边的半圆,最初通过position
定位 - 通过
::after
,实现一个 200*300 的矩形(反过来),并通过border-radius
设置圆角,做成左边的长方形半圆,最初通过position
定位 - 增加动画,让它循环跳动起来
.heart { position: relative; width: 200px; height: 200px; background: deeppink; transform: rotate(45deg); /* 要害动画:让心跳动起来 */ /* animation: 动画名称 | 动画工夫 | 动画是否反向播放 | 动画运行的次数 */ animation: heartjump 0.5s alternate infinite;}@keyframes heartjump { 0% { transform: rotate(45deg) scale(0.5); } 100% { transform: rotate(45deg) scale(1); }}.heart::before, .heart::after { position: absolute; content: ''; background: deeppink;}.heart::before { left: -99px; width: 100px; height: 200px; border-radius: 100px 0 0 100px;}.heart::after { top: -99px; width: 200px; height: 300px; border-radius: 100px 100px 0 0; /* 要害暗影:让爱心有立体感 */ /* box-shadow: x 偏移量 | y 轴偏移量 | 暗影含糊半径 | 暗影扩散半径 | 暗影色彩 */ box-shadow: 10px -5px 10px 0 #ccc;}
这样,两头的心就实现啦:
2.2 滑动的文字
那么,底部的含滑动成果的文字如何实现呢?
其实也不难:
<p class="tips"> <!-- 提醒文本 --> <span class="tips-info"> <!-- TODO: 提醒 - 用户填充 --> </span> <!-- 三个点 --> <span class="three-dots"> <span class="three-dots-element"></span> <span class="three-dots-element"></span> <span class="three-dots-element"></span> </span></p>
这里看要害 CSS 的实现:
.tips { margin-top: 50px; position: relative; padding: 8px; border-radius: 8px; border: 1px solid deepskyblue; color: #000; cursor: pointer; /* 要害动画:色彩的扭转 */ transition: color .3s;}.tips:hover { color: #fff;}.tips:hover::before { /* 要害动画 - 从左下开始 */ transform: scaleX(1); transform-origin: bottom left;}.tips::before { content: ' '; display: block; position: absolute; /* https://developer.mozilla.org/en-US/docs/Web/CSS/inset */ inset: 0 0 0 0; background: deepskyblue; border-radius: 8px; z-index: -1; /* 要害动画 - 从右下开始 */ transition: transform 1s ease; transform: scaleX(0); transform-origin: bottom right;}
看完是不是恍然大悟:
- 原来只有通过
::before
设置好蓝色背景,而后增加transition
,让它从左往右「跑」起来
2.3 其余
其余成果就不一一介绍了。
感兴趣的小伙伴可自行返回代码仓库查看成果喔:
- Demo —— all for one
- 码上掘金 - 02 - 2023 兔年祝愿
三 服务端实现
OK,那么界面实现后,咱们如何让数据「动」起来呢?
- 通过
data.json
存储数据 - 通过
index.js
,读取url
参数,并匹配json
上的数据 - 将数据渲染到界面
这样,咱们是不是就可能动静更换数据了?
3.1 前后端数据对接
假如咱们有个 json
文件来存储数据:
data.json
[ { "username": "jsliang", "tipsInfo": "Hello 小伙伴们,点击 ❤ 查看我给你们的信", "letterContentTitle": "给 2022 的你们", "letterContentMain": "☆ 2022 随风飘逝,2023,咱们来啦!\n☆ 在新春佳节到来之际,祝您全家身体健康,万事如意!\n☆ 兔年的祝愿短信飞雪迎春到,玉兔捧福来。\n☆ 元旦的钟声扣响你高兴的心扉,新年礼炮奏响你幸福华章,缤纷焰火编织你闪亮生存,八仙给力保你万事胜意。\n☆ 祝您一帆风顺,四季安全,八方进财!\n☆ 兔年祝福天下敌人:工作舒心,薪水合心,被窝暖心,敌人知心,爱人同心,所有都顺心,永远都开心,事事都满意!\n", "letterContentButton": "加油 2023!" }]
在 index.js
上进行读取,看用户输出了什么:
// 获取节点const tipsInfo = document.querySelector('.tips-info');const letterContentTitle = document.querySelector('.letter-content-title');const letterContentMain = document.querySelector('.letter-content-main');const letterContentButton = document.querySelector('.letter-content-button');// 获取 URL 参数let query;const getQuery = (info) => { if (query) { return query.get(info); } query = new URLSearchParams(window.location.search); return query.get(info);};// 读取 JSON 数据const data = await fetch('./data.json');const userinfo = await data.json();console.log('data: ', userinfo);const username = getQuery('username') || 'jsliang';// 匹配并渲染数据for (let i = 0; i < userinfo.length; i++) { const item = userinfo[i]; if (item.username === username) { tipsInfo.innerText = item.tipsInfo; letterContentTitle.innerText = item.letterContentTitle; letterContentMain.innerText = item.letterContentMain; letterContentButton.innerText = item.letterContentButton; break; }}
这样,咱们根底数据构思就实现了!
接下来只须要通过 Node.js,将数据填充到 data.json
即可,简简单单~
3.2 Node.js 服务搭建
OK,接下来咱们须要思考的是,从哪里 白嫖 做收费的数据存储,并且可能抓下来。
这次咱们思考的是应用「金山文档」的线上「表格」,因为它不仅能够满足 用户共享填写数据,并且不便咱们 通过无头浏览器抓取数据。
这里就须要利用 Node.js + Puppeteer 来下载数据了。
当然,前置知识点是存在的,然而篇幅无限,「孩子没娘,说来话长」,jsliang 举荐小伙伴看之前的文章:
- jsliang - Node 工具库
上面是逐渐搭建步骤,具体的解释能够在下面工具库系列文章查看,这里就不一一介绍啦:
- [x] 下载安装 Node.js
- [x] 下载安装 Visio Studio Code
- [x] 初始化仓库:
npm init --yes
- [x] 装置初始化包:
pnpm i @types/node typescript ts-node -D
- [x] 初始化 TypeScript 配置:
tsc --init
- [x] 装置 ESLint:
pnpm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin -D
- [x] 装置 Commander:
pnpm i commander@14.3.0
- [x] 批改 package.json,可运行
npm run 2023
OK,到这一步,根底的 Node.js 服务就搭起来了。
它的目录构造如下:
- 02 - 2023 兔年祝愿 - LiangJunrong.github.io —— GitHub Page 仓库 - src —— 我的项目主代码 - dist —— Excel 下载地址 - index.ts —— 主入口 - .gitignore —— Git 疏忽配置 - package.json —— npm 包治理 - pnpm-lock.yaml —— npm 包治理 - tsconfig.json —— TSLint
3.3 下载数据
上面咱们开始下载数据,这里的指标是将数据下载到 src/dist
目录中:
- [x] 装置 Puppeteer:
pnpm i puppeteer
以后(2023-01-15)最新版是 19.5.2,然而执行会报错,须要指定版本。参考文献:https://github.com/berstend/p...
通过 Node.js + Puppeteer 下载数据分 10 个小步骤:
- 启动无头浏览器
- 操作浏览器关上
https://kdocs.cn/l/cbmawranzvNL
- 睡眠 6.66s(确保浏览器关上链接并加载页面)
- 如果有遮罩弹窗,须要触发【x】按钮敞开掉
- 触发【更多菜单】按钮的点击
- 睡眠 2s(确保更多菜单按钮点击到)
- 设置下载门路(确保 Puppeteer 下载门路,防止【另存为】弹窗后不好解决)
- 触发【下载】按钮的点击
- 睡眠 6.66s(确保资源下载到)
- 敞开窗口
惟一要关注的点是第 5 点,因为咱们 Windows 点击下载是会有弹窗的(并不是默认下载)
它的实现代码如下:
// 步骤一:下载 Excelconst downloadExcel = async() => { // 1. 启动无头浏览器 const browser = await puppeteer.launch({ // 是否关上实体浏览器 headless: false, // 关上开发模式 devtools: true, }); // 2. 操作浏览器关上 `https://kdocs.cn/l/cbmawranzvNL` const page = await browser.newPage(); await page.goto('https://kdocs.cn/l/cbmawranzvNL'); // 3. 睡眠 6.66s(确保浏览器关上链接并加载页面) await page.waitForTimeout(6666); // 4. 如果有遮罩弹窗,须要触发【x】按钮敞开掉 const closeBtn = await page.$('.modal-wrap .icons-16-close'); closeBtn?.click(); // 5. 触发【更多菜单】按钮的点击 const moreBtn = await page.$('.header-more-btn'); moreBtn?.click(); // 6. 睡眠 2s(确保更多菜单按钮点击到) await page.waitForTimeout(2000); // 7. 设置下载门路(确保 Puppeteer 下载门路,防止【另存为】弹窗后不好解决) const dist = path.join(__dirname, './dist'); if (!fs.existsSync(dist)) { fs.mkdirSync(dist); } // 如果报错,请批改 Puppeteer 为 14.3.0:https://github.com/berstend/puppeteer-extra/issues/651 await (page as any)._client?.send('Page.setDownloadBehavior', { behavior: 'allow', downloadPath: dist, }); // 8. 触发【下载】按钮的点击 // @ts-ignore const downloadBtn = await page.$('div[data-key=Download]'); downloadBtn?.click(); // 9. 睡眠 6.66s(确保资源下载到) await page.waitForTimeout(6666); // 10. 敞开窗口 await browser.close();}
3.4 读取数据
接着,咱们须要通过 node-xlsx
来读取下载后的数据:
- 装置 Excel 读取模块:
pnpm i node-xlsx -S
+pnpm i @types/node-xlsx -D
它分为 3 个小步骤:
- 以
buffer
模式导入数据 - 读取无效的数据(后面几行为阐明数据,且前面须要判断数据是否冗余)
- 将数据以
JSON
的模式存储到 GitHub Page 仓库
// 步骤二:读取 Excel 并存储 JSON 数据const readExcel = async() => { // 1. 以 buffer 模式导入数据 const workSheetsFromBuffer = xlsx.parse(fs.readFileSync(`${__dirname}/dist/「新春贺词 - 兔飞猛进」.xlsx`)); // 含图片等数据的时候,第 1 条才是文本数据 const stringifyData: any = JSON.parse(JSON.stringify(workSheetsFromBuffer, null, 2)); const data = stringifyData[0]?.data; // 2. 读取无效的数据(后面几行为阐明数据,且前面须要判断数据是否冗余) const result = []; for (let i = 3; i < data.length; i++) { const item = data[i]; const [ username, tipsInfo = '点击 ❤ 查看我给你的信', letterContentTitle = 'A Letter for you', letterContentMain, letterContentButton = 'Love ❤ you', ] = item; // 如果没数据了,则不填写 if (!username || !letterContentMain) { continue; } result.push({ username, tipsInfo, letterContentTitle, letterContentMain, letterContentButton, }); } // 3. 将数据以 JSON 的模式存储到 GitHub Page 仓库 const GPCatalog = path.join(process.cwd(), './LiangJunrong.github.io/data.json'); fs.writeFileSync(GPCatalog, JSON.stringify(result));};
3.5 上传代码
接下来只须要将代码上传到 GitHub Page 即可:
- 装置 shell 模块:
pnpm i shelljs
+pnpm i @types/shelljs -D
它分 3 个小步骤:
- 返回 GitHub Page 仓库
- 执行批改命令
- 推送到线上仓库
- 回退上一层(不便下一次执行的时候目录层级统一)
// 步骤三:上传代码到 GitHub Pageconst uploadCode = async() => { // 1. 返回 GitHub Page 仓库 await shell.cd(`LiangJunrong.github.io`); // 2. 执行批改命令 await shell.exec(`git add .`); await shell.exec(`git commit -m "fix: 更新线上数据"`); // 3. 推送到线上仓库 await shell.exec('git push'); // 4. 回退上一层(不便下一次执行的时候目录层级统一) await shell.cd(`../`);};
3.6 设置定时工作
最初,咱们只须要设置电脑定时工作,让它能够定时读取线上数据并上传就好啦!
- 装置 node-schedule 模块:
pnpm i node-schedule
+pnpm i @types/node-schedule -D
只须要简略一步代码:
import puppeteer from 'puppeteer';import path from 'path';import fs from 'fs';import xlsx from 'node-xlsx';import shell from 'shelljs';import schedule from 'node-schedule';// 步骤四:设置定时器,定时上传代码const runCode = async() => { console.log('Hello 2023~'); // scheduleJob: 秒 分 时 日 月 周几 schedule.scheduleJob('*/10 * * * *', async() => { console.log('开始操作'); // 步骤一:下载 Excel await downloadExcel(); // 步骤二:读取 Excel 并存储 JSON 数据 await readExcel(); // 步骤三:上传代码到 GitHub Page await uploadCode(); });};const program = require('commander');program .version('1.0.0') .description('2023 兔年祝愿') .command('2023') .action(async() => { // 步骤四:设置定时器,定时上传代码 await runCode(); });program.parse(process.argv);
3.7 小结
通过下面操作,咱们能够看到:
- 通过
node-schedule
定期执行工作 - 通过
puppeteer
下载线上数据 - 通过
node-xlsx
读取下载下来的 Excel 文件 - 通过
shell
操作 Shell,上传数据 - 通过 JavaScript 读取 JSON 文件,将数据渲染到 HTML
这样,咱们就实现了本次的祝愿实例!
OK,完事,出工~
四 参考文献
- 24 Creative and Unique CSS Animation Examples to Inspire Your Own
- 掘金 - KevinQ - 纯CSS制作跳动的心
- 博客园 - whys - CSS 画一个心
不折腾的前端,和咸鱼有什么区别!
感觉文章不错的小伙伴欢送点赞/点 Star。
如果小伙伴须要分割 jsliang:
- Github
- 掘金
集体联系方式寄存在 Github 首页,欢送一起折腾~
争取打造本人成为一个充斥摸索欲,喜爱折腾,乐于扩大本人知识面的一生学习斜杠程序员。
jsliang 的文档库由 梁峻荣 采纳 常识共享 署名-非商业性应用-雷同形式共享 4.0 国内 许可协定 进行许可。<br/>基于 https://github.com/LiangJunrong/document-library 上的作品创作。<br/>本许可协定受权之外的应用权限能够从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处取得。