preface

Let’s first learn about the development history of front-end icon.

When the front end was first developed, most ICONS were implemented using IMG. Gradually, I found that img images occupied most of the requested resources on a page, so in order to optimize the image Sprite image, which is to combine multiple images into one image and display different icon ICONS by using CSS background position. But this also has a big pain point, maintenance difficulty. Every time you add a new icon, you need to change the original image, and you may accidentally make an error that affects the previously positioned image. Moreover, once you change the Sprite image, the image cache will become invalid, and over time you will not know how to maintain.

Font library Gradually a project will not use any native images at all, and some font library will be used to implement the page ICONS. Common examples are Font Awesome iconfont.

For iconfont ICONS and gestures, see Iconfont

Create the Icon component

Now that we have the icon icon, the next step is to create an Icon component in your project.

Before encapsulation, the icon would look something like this

<text class="crab crab-gou" style="font-size: 28rpx; color: #333;" >Copy the code

We end up encapsulating the component, which looks something like this

<ca-icon name="crab-gou" />
Copy the code

The general idea of implementation

  • The introduction oficonfontIcon style
  • In passing the size name and style
<template> <text @tap.stop="handleClick" class="ca-icon" :class="[classPrefix_, name]" :style="[iconStyle_]" ></text> </template> <script> import { defineComponent, toRefs, computed } from 'vue' export default defineComponent({ props: { name: { type: String, default: '', }, size: { type: [String, Number], default: '28', }, color: { type: [String, Boolean], default: 'inherit', }, size: { type: [Number, String], default: 28, }, }, setup(props, { emit }) { const handleClick = (e) => { emit('click', E)} const iconStyle_ = computed(() => {// Component style const obj = {fontSize: String(props. Size).indexof ('px')! = = 1? props.size : uni.upx2px(props.size) + 'px', } // icon name const classPrefix_ = computed(() => {const prevName = functions.name.split ('-')[0] const name = prevName === 'icon' ? 'iconfont' : prevName return name }) String(props.color) ! == 'false' && (obj['color'] = props.color) return obj }) return { iconStyle_, classPrefix_, handleClick, ... toRefs(props), } }, }) </script> <style lang="scss" scoped> @import './font.css'; .ca-icon { font-size: 0; @include tst(transform); vertical-align: middle; position: relative; display: inline-block; font-size: inherit; // How the browser rendering engine renders the font. Browsers make trade-offs between speed, clarity, and geometric precision. text-rendering: auto; -webkit-font-smoothing: antialiased; } </style>Copy the code

Well, a simple icon component is wrapped. Vant functions have, in addition to the little bit, do not want to write, is to play, feel useless.

Further modification

Is that it? Is that it?

Colleague development project used to feel dissatisfied, raised new requirements.

  • I want the icon to be able to rotate, go all the way around, and adjust the speed of the rotation.
  • I want the icon to be able to rotate at a certain Angle.

All right, arrange

So I add a few lines of code, as follows

<template> <text @tap.stop="handleClick" class="ca-icon" :class="[classPrefix_, name]" :style="[iconStyle_]" ></text> </template> <script > import { defineComponent, toRefs, computed } from 'vue' export default defineComponent({ props: { name: { type: String, default: '', }, size: { type: [String, Number], default: '28', }, color: { type: [String, Boolean], default: 'inherit', }, size: { type: [Number, String], default: 28, }, spin: { type: Boolean, default: false, }, spinGap: { type: [Number, String], default: Rotate: {type: [Number, String, Boolean], default: false, }, }, setup(props, { emit }) { const handleClick = (e) => { emit('click', e) } const rotate_ = computed(() => { return String(props.rotate) === 'false' ? false : props.rotate }) // class-prefix const classPrefix_ = computed(() => { const prevName = props.name.split('-')[0] const name = prevName === 'icon' ? 'iconfont' : PrevName return Name}) const iconStyle_ = computed(() => {// Component style const obj = {fontSize: String(props.size).indexOf('px') ! = = 1? props.size : uni.upx2px(props.size) + 'px', } String(props.color) ! == 'false' && (obj['color'] = props. Color) rotate_. Value (obj. Transform = isNaN(props. `rotate(${props.rotate})` : `rotate(${props.rotate}deg)`) if (props.spin) { obj.animation = `ca-spin ${props.spinGap}s linear infinite` } return obj  }) return { iconStyle_, classPrefix_, handleClick, ... toRefs(props), } }, }) </script> <style lang="scss" scoped> @import './font.css'; .ca-icon { font-size: 0; @include tst(transform); vertical-align: middle; position: relative; display: inline-block; font-size: inherit; // How the browser rendering engine renders the font. Browsers make trade-offs between speed, clarity, and geometric precision. text-rendering: auto; -webkit-font-smoothing: antialiased; } </style>Copy the code

SCSS animation

@keyframes ca-spin {from {transform: rotate(0deg); } to { transform: rotate(360deg); }}Copy the code

The effect

    // used in code
    <view class="p-30"> icon </view>
    <ca-icon name="crab-gou" />
    <ca-icon name="crab-modal" color="# 888" />
    <ca-icon name="crab-shijian1" size="60" />
    <ca-icon name="crab-aixin1" rotate="45" />
    <ca-icon name="crab-shoucang1" spin />
    <ca-icon name="crab-shoucang1" spin spinGap="5" />
Copy the code

As is shown in

reference

  • Juejin. Cn/post / 684490…
  • Vant – contrib. Gitee. IO/vant / # / useful – C…