实战Header组件:换一换动画实现

174 阅读2分钟

Icon的使用复习

首先,我们需要加入一个新的图标。具体过程与之前相似,需要重新下载项目并将文件替换,注意不需要全部替换js文件。将以下部分从解压文件中的js文件复制到代码中:

import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSync } from '@fortawesome/free-solid-svg-icons'

library.add(faSync)

同时,在所有iconFont样式中,加上./前缀,除了base64那一行。

@font-face {
  font-family: 'iconfont';  /* project id 937491 */
  src: url('./iconfont.eot');
  src: url('./iconfont.eot?#iefix') format('embedded-opentype'),
  url('./iconfont.woff2') format('woff2'),
  url('./iconfont.woff') format('woff'),
  url('./iconfont.ttf') format('truetype'),
  url('./iconfont.svg#iconfont') format('svg');
}

修改布局

我们发现布局存在冲突,导致图标位置不正确。由于对所有iconFont样式进行了规定,导致图标距离右侧和底部的距离都有问题。我们只需要给放大镜Class加上一个标签即可。

.iconfont.search-icon {
  position: absolute;
  right: 5px;
  bottom: 5px;
  width: 30px;
  line-height: 30px;
  border-radius: 15px;
  text-align: center;
  &.focused {
    background: #777;
    color: #fff;
  }
}

然后,我们将换一换图标缩小。

export const SearchInfoSwitch = styled.span`
  float: right;
  font-size: 13px;
  cursor: pointer;
  .iconfont.spin {
    font-size: 12px;
    margin-right: 2px;
    transition: all .2s ease-in;
    transform-origin: center center;
  }
`;

实现动画

为了实现搜索结果的换一换功能,我们需要添加一些动画效果来提高用户体验。这里我们将不使用之前的 CSS Transition Group 组件,而是采用另一种方法来实现动画效果。

首先,我们需要添加一个样式类来定义搜索结果切换的图标和动画:

export const SearchInfoSwitch = styled.span`
  float: right;
  font-size: 13px;
  .spin {
    display: block;
    float: left;
    font-size: 12px;
    margin-right: 2px;
    transition: all 0.2s ease-in;
    transform-origin: center center;
  }
`;

在定义样式类之后,我们可以在组件中使用它,并通过 ref 获取到图标的原始 DOM 节点。当用户点击换一批按钮时,我们可以通过修改节点的 style 属性来实现动画效果:

<SearchInfoSwitch onClick={() => handleChangePage(page, totalPage, this.spinIcon)}>
  <i ref={(icon) => { this.spinIcon = icon; }} className='iconfont spin'>&#xe851;</i>
  换一批
</SearchInfoSwitch>

handleChangePage(page, totalPage, spin) {
  // 获取上一次的旋转角度
  let originalAngle = spin.style.transform.replace(/[^0-9]/ig, '');
  if (originalAngle) {
    originalAngle = parseInt(originalAngle, 10);
  } else {
    originalAngle = 0;
  }
  // 在上一次的旋转角度上增加 360 度来实现旋转效果
  spin.style.transform = `rotate(${originalAngle + 360}deg)`;
  if (page < totalPage) {
    dispatch(actionCreators.changePage(page + 1));
  } else {
    dispatch(actionCreators.changePage(1));
  }
}

需要注意的是,由于旋转角度写死会导致重复点击按钮时报错,因此我们需要获取上一次的旋转角度,并在此基础上增加 360 度来实现动画效果。

最后,为了提高用户体验,我们可以添加鼠标悬停时的样式,让鼠标在移动到换一批按钮上时变成手型图标。代码如下:

export const SearchInfoSwitch = styled.span`
  float: right;
  font-size: 13px;
  cursor: pointer;
  .spin {
    display: block;
    float: left;
    font-size: 12px;
    margin-right: 2px;
    transition: all 0.2s ease-in;
    transform-origin: center center;
  }
  &:hover {
    color: #f60;
  }
`;

这样,我们就通过 ref 和 CSS 样式来实现搜索结果的换一换功能,并添加了悬停样式,提高了用户体验。