「青训营 X 码上掘金」MagicCard

167 阅读4分钟

当青训营遇上码上掘金

我的名片

名片是向人介绍自我的重要工具,作为一名程序员用代码做自我介绍是一件非常酷炫的事情。做为一名前端程序员,可实现的方式很多很多,本次设计思路主要走酷炫风,那怎么做到足够酷炫呢?本次MagicCard主要以重CSS形式来实现,着重使用animation、transition提升交互体验。

效果预览

effect.gif

代码分析

技术栈

  1. React
  2. Less

主要以CSS实现效果为主

源码-userInfo

userInfo中可以去填写一些自己的信息,对应渲染到MagicCard

/**
 * your information
 */
const userInfo: {
  name: string;
  url: string;
  avatar: string;
} = {
  name: 'Whiskeyi',
  url: 'https://github.com/Whiskeyi',
  // 此链接为自己图床上传cdn配置云存储服务
  avatar: 'https://cloud.zhuchj.com/avatar.jpg'
}

源码-DOM

DOM节点主要以div.card为主,card中包括展示个人nameavatar

const MagicCard: FC = () => {
  return (
    <>
      <div className="card">
        <a 
          className="name" 
          href={userInfo.url} target="_blank">
          Hi,&nbsp;I&nbsp;am&nbsp;
          {userInfo.name}
        </a>
        <img 
          className="avatar" 
          src={userInfo.avatar} 
        />
      </div>
      <span className="tips">
        ⬆️&nbsp;please hover this
      </span>
    </>)
};

源码-Less

定义旋转动画

// animation define
@keyframes spin {
  0% {
    rotate: 0deg;
  }
  100% {
    rotate: 360deg;
  }
}

定义body

使得内部元素垂直水平居中

body {
  height: 100vh;
  background: #212534;
  display: flex;
  align-items: center;
  justify-content: center;
}

定义card

card中包括了name和avatar,分别定义他们的样式

注意的是:

  1. name和avatar在初始情况不可见,这里做了color: transparent;,opacity: 0;的处理
  2. name过长时会超出布局,这里做了省略处理max-width: 180px;,overflow: hidden;,white-space: nowrap;,text-overflow: ellipsis;
  3. card需要有悬浮手势提示cursor: pointer;
  4. name由于在a标签嵌套下,有固定样式需要清除text-decoration:none;
  5. 为了实现avatar动画,动画初始值为transform: rotate(-45deg);
.card {
  width: 200px;
  height: 200px;
  background-color: #191c29;
  padding: 3px;
  border-radius: 50%;
  flex-direction: column;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;

  .name {
    font-size: 20px;
    color: transparent;
    text-decoration:none;
    margin-bottom: 15px;
    font-weight: 500;
    // exceeding ellipsis
    max-width: 180px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  
  .avatar {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    opacity: 0;
    transform: rotate(-30deg);
  }
}

定义card:hover

  1. 多次使用transition动画属性, transition可以使用,间隔传多个css属性
  2. card样式由圆形转为方型border-radius: 50%;=>border-radius: 8px;
  3. name对应颜色变化,avatar对应透明度和旋转角度变化
.card:hover {
  border-radius: 8px;
  transition: border-radius 1s;

  .name {
    color: rgb(88 199 250 / 100%);
    transition: color 1s;
  }

  .avatar {
    transform: rotate(0deg);
    opacity: 1;
    transition: opacity, transform 1s;
  }
}

定义card::after

此主要实现动态背景光环

image.png

  1. 使用::after伪元素选择器对应在card样式附加属性
  2. 定义animation循环旋转animation: spin 2.5s linear infinite;
  3. 添加高斯模糊filter: blur(50px);
  4. 背景颜色使用渐变linear-gradient
  5. z-index: -1;使得在card之下呈现,你也可更改此值使得能够清晰看见此伪元素效果
.card::after {
  position: absolute;
  content: "";
  left: 0;
  right: 0;
  // you can change z-index to show
  z-index: -1;
  height: 100%;
  width: 100%;
  margin: 0 auto;
  transform: scale(0.8);
  filter: blur(50px);
  background-image: linear-gradient(0deg ,#5ddcff, #3c67e3 43%, #4e00c2);
  opacity: 1;
  transition: opacity .5s;
  animation: spin 2.5s linear infinite;
}

定义card::before

此主要实现动态条状带(实际为一个圆球在不停旋转)

image.png

  1. 使用::before伪元素选择器对应在card样式附加属性
  2. 定义animation循环旋转animation: spin 2.5s linear infinite;
  3. 定义width和height比100%大一点,使得圆形超出原来的范围,被圆球遮住后即展示条状带的样式。(注意的是这里的width和height两个百分比不同,因为我希望条状带有粗细变化的情况)
  4. 背景颜色使用渐变linear-gradient
  5. z-index: -1;使得在card之下呈现,你也可更改此值使得能够清晰看见此伪元素效果
.card::before {
  content: "";
  width: 103%;
  height: 102%;
  border-radius: 50%;
  background-image: linear-gradient(0deg, #5ddcff, #3c67e3 43%, hsl(264, 100%, 38%));
  position: absolute;
  // you can change z-index to show
  z-index: -1;
  animation: spin 2.5s linear infinite;
}

定义.card:hover::befor, .card:hover::after

期望悬浮后对card伪元素样式做清除

  1. 清除动画animation: none;
  2. 对原样式做隐藏opacity: 0;
.card:hover::before, .card:hover::after {
  animation: none;
  opacity: 0;
}

思考总结

在本次实现卡片展示时主要是重CSS的方式实现,利用:hover来替代addEventListenerjs代码,另外使用::after::before来拓展原card样式,使用animationtranstition提升总体交互部分。

实现过程中,也考虑到一些细节问题,如name过长时使用...省略等等。