这是我参与「第五届青训营」笔记创作活动的第十一天
当青训营遇上码上掘金
主题 :我的名片
名片是向人介绍自我的重要工具,作为一名程序员用代码做自我介绍是一件非常酷炫的事情。请大家围绕“我的名片”这个主题进行代码创作。
想法
我想做一个有夜间模式,精简模式,和生成图片(方便分享)功能的名片
草图
- 点击 太阳|月亮 可以切换夜间模式与日间模式
- 点击 减号|加号 可以切换精简模式与细节模式 (精简模式下只显示最基本的信息)
- 点击 相机 可以生成当前名片的图片并自动下载
- 鼠标悬浮在图标上可以弹出功能提示
- 其余部分分别为 头像(可以是个人照片等),昵称 | 姓名, 个人简介等
最终效果
实现
夜间|日间模式切换
使用元素类名上分别绑定夜间模式与日间模式的类名,通过太阳|月亮图标控制一个公共的flag来决定,当前使用哪个模式对应的样式表
- HTML
<div id="infoCard"
:class="{ infoCard: true, infoCardDay: dayclass.value, infoCardNight: !dayclass.value }">
</div>
- CSS
infoCard对应的是基础的样式;infoCardDay 与 infoCardNight 对应的是两种模式下不同的样式
.infoCardDay {
background-color: #ABCBF1;
}
.infoCardNight {
background-color: #0F1931;
}
- JavaScript
const dayclass = reactive({
value: true,
switchFn: () => {
dayclass.value = !dayclass.value;
}
})
精简|细节模式切换
实现的思路 与夜间|日间模式的实现类似,也是通过 加|减图标控制一个公共的flag来决定,当前使用哪个模式对应的样式表
- HTML
<div id="infoCard"
:class="{ infoCard: true, infoCardDay: dayclass.value, infoCardNight: !dayclass.value, infoCardExpand: expandclass.value, infoCardSimple: !expandclass.value }">
</div>
- CSS
infoCard对应的是基础的样式;infoCardExpand 与 infoCardSimple 对应的是两种模式下不同的样式
.infoCardExpand {
display: flex;
}
.infoCardSimple {
display: block;
}
- JavaScript
const expandclass = reactive({
value: true,
switchFn: () => {
expandclass.value = !expandclass.value;
}
})
碰到的问题
切换至精简模式时,头像后的背景颜色需要改变成整个名片的背景颜色,我想通过使头像后的背景变为透明来实现
opacity: 0=> 可以使背景变为透明,但同时也会影响到里面的头像和用户名,使它们也变为透明,且对头像和用户名设置opacity: 1也不会使头像和用户名显示,故无法使用该方法rgba(x, x, x, 0)=> 可以使背景变为透明,且不会影响到内部的元素,但会带来另外一个问题,除了透明度,我们还需要知道当前的背景的rgb值,这个问题是有夜间|日间模式切换所带来的
最后选择了 方法二 ,尽管写的很不优雅😿
- HTML
<div :class="{ avatarName: true, avatarNameDay: dayclass.value, avatarNameNight: !dayclass.value, avatarNameDayExpand: expandclass.value && dayclass.value, avatarNameNightExpand: expandclass.value && !dayclass.value, avatarNameDaySimple: !expandclass.value && dayclass.value, avatarNameNightSimple: !expandclass.value && !dayclass.value }">
</div>
- CSS
.avatarNameDayExpand {
display: flex;
background-color: #CDDEF3;
}
.avatarNameNightExpand {
display: flex;
background-color: #1E2E55;
}
.avatarNameDaySimple {
display: block;
background-color: #ABCBF1;
}
.avatarNameNightSimple {
display: block;
background-color: #0F1931;
}
生成名片图片
使用了库dom-to-image来实现
const downloadInfoCard = () => {
domtoimage.toJpeg(document.getElementById('infoCard') as HTMLElement, { quality: 0.95 })
.then(function (dataUrl) {
var link = document.createElement('a');
link.download = '名片.jpeg';
link.href = dataUrl;
link.click();
});
}
碰到的问题
名片中的引用的图片都是放在图床上,<image>标签不会遇到跨域问题,而当使用dom-to-image生成图片时则会遇到跨域问题,想到了两个解决方案
- 起一个代理服务器做中转,绕过浏览器的安全策略
- 将图片保存在本地,项目中
权衡后,由于图片较少,方法一的实现较重,所以选择了方法二,通过字符串保存图片的Base64格式来实现,解决了跨域问题,当然实现的也是很不优雅🫤
生成的名片例子
最后
详细的代码放在了码上掘金上了,欢迎一起来交流,由于引用了第三方库,所以使用了webpack进行了打包,所以可读性较差,抱歉🙈名片 - 码上掘金 (juejin.cn)
可以优化的地方
- 布局使用了vw对不同尺寸进行了适配,但较大尺寸和较小尺寸的体验仍然较差
- 皮肤切换的实现方式较为繁琐,优化空间好大!!!大家有更好的主意的话,请一定要告诉我,拜托拜托🙏
- 图片的跨域问题,使用base64存储会使该web的静态文件变大很多,不是个好的解决方法,也可以优化
想加的功能
- 名片可以加上二维码,方便大家添加好友
- 提供可选的功能来展示信息,比如说我只想展示名字和基本信息,那我就不必勾选头像