[ 青训营 X 码上掘金 | 青训营笔记]

146 阅读4分钟

这是我参与「第五届青训营」笔记创作活动的第十一天
当青训营遇上码上掘金

主题 :我的名片

名片是向人介绍自我的重要工具,作为一名程序员用代码做自我介绍是一件非常酷炫的事情。请大家围绕“我的名片”这个主题进行代码创作。

想法

我想做一个有夜间模式精简模式,和生成图片(方便分享)功能的名片

草图

设计图.jpg

  • 点击 太阳|月亮 可以切换夜间模式日间模式
  • 点击 减号|加号 可以切换精简模式细节模式 (精简模式下只显示最基本的信息)
  • 点击 相机 可以生成当前名片的图片并自动下载
  • 鼠标悬浮在图标上可以弹出功能提示
  • 其余部分分别为 头像(可以是个人照片等),昵称 | 姓名, 个人简介等
最终效果

演示.gif

实现

夜间|日间模式切换

使用元素类名上分别绑定夜间模式与日间模式的类名,通过太阳|月亮图标控制一个公共的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格式来实现,解决了跨域问题,当然实现的也是很不优雅🫤

生成的名片例子

生成的名片.jpeg

最后

详细的代码放在了码上掘金上了,欢迎一起来交流,由于引用了第三方库,所以使用了webpack进行了打包,所以可读性较差,抱歉🙈名片 - 码上掘金 (juejin.cn)

可以优化的地方
  • 布局使用了vw对不同尺寸进行了适配,但较大尺寸和较小尺寸的体验仍然较差
  • 皮肤切换的实现方式较为繁琐,优化空间好大!!!大家有更好的主意的话,请一定要告诉我,拜托拜托🙏
  • 图片的跨域问题,使用base64存储会使该web的静态文件变大很多,不是个好的解决方法,也可以优化
想加的功能
  • 名片可以加上二维码,方便大家添加好友
  • 提供可选的功能来展示信息,比如说我只想展示名字和基本信息,那我就不必勾选头像
目前只想到这么多啦,谢谢你看到这里!祝大家新春愉快!😆