将新的CSS技术引入到生产中

特别声明:如果您喜欢小站的内容,可以点击年卡¥199.00元(原价: ¥598元)季卡¥78.00元(原价: ¥168元)月卡¥28.00元(原价: ¥68元)进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!(^_^)

时间如梭,又一年双11圆满收官了。作为技术宅男除了买买买之外还能和大家聊的就是前端技术了。

"淘宝盖楼"上热搜了,我想你应该也参加了双十一淘宝盖楼吧,是不是觉得特别的酸爽。今年有幸参与盖楼的互动活动的开发中备感荣幸,因为我们的努力让全民都爽了。在开始之前要先感谢一下曾经努力的自己

楼盖完了,我们回过头来聊聊这次多人互动PK在开发的时候用了哪些有意思的前端技术。感兴趣的同学,请继续往下阅读。

去年双十一能量PK互动项目中我们用了些有意思的前端技术,要是你感兴趣的话,可以阅读《聊聊双11互动主动法中前端技术亮点》一文。

SVG运用和优势

先来说图标(Icon)的使用。整套视觉下来,页面上的图标(或类似图标)的场景还是蛮多的,比如:

仔细分析一下,有些图标是具有共性的,或者说只有一点点差异:

别的图标暂且不表,有两个地方是有共性的:

  • 箭头图标是相同的,如果说差异,就是箭头有没有带容器箭头容器的颜色有差异
  • 微标(票房状态的图标,比如“平局”、“获胜”等),在不同的地方仅仅是颜色大小的差异

自有Web技术到现在,Web上使用图标的技术也随着时代的变迁在改变:

  • <img>引用独立的Icon图片文件
  • background-image替代<img>标签,引用独立的Icon图片文件
  • 将众多Icon图片合并在一起(俗称Sprites),使用background-imagebackground-position来控制Icon图标的显示和位置
  • Icon Font的使用,比如阿里IconFontFont Awesome
  • 内联SVG和SVG Sprites

有关于上述技术方案的差异性和利弊,这里不做过多的阐述,如果你对这方面的讨论感兴趣的话,我建议你移步阅读以前整理的《Web中的图标》一文。

在这次的项目中,我采用了SVG Sprites相关的技术。在聊为什么采用SVG Sprites技术之前,先来对上面提到的两个典型的图标做一个简单的分析。

直接用下图来描述箭头图标的构造(一图胜过千言万语):

从上图中我们可以看出来,最共用的是箭头部分对应的SVG代码:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">  
<svg t="1568275614301" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2246" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
    <path d="M448 672c-6.4 0-19.2 0-25.6-6.4-12.8-12.8-12.8-32 0-44.8L531.2 512 422.4 409.6c-12.8-12.8-12.8-32 0-44.8s32-12.8 44.8 0l128 128c12.8 12.8 12.8 32 0 44.8l-128 128C467.2 672 454.4 672 448 672z" p-id="2247"></path>
</svg>

你可能发现了,在上图中箭头有不同的颜色,比如#FF1545#fff,可以借助SVG的fillstrock属性,不管SVG标签行内添加样式,还是在CSS样式表中添加样式,可以将fillstrock设置为currentColor

currentColor是CSS中第一个变量属性值,最大的特性就是可以根据当前color来决定值。

如果你对currentColor感兴趣的话,还可以阅读:

箭头容器就很好控制了,通过CSS很好的设置。

该方案最大的优势,我们只需要一个箭头的矢量图(SVG的path就可以很好解决)。第二种思路要比上面这种略差一点,因为需要两个SVG的代码(两个不同的.svg)文件。一个是像上面所示的代码,不带容器;另外一个就是像下面这样的SVG代码,带圆形容器:

代码如下,也是用SVG的path绘制出来,同样的fillstrock设置为currentColor

<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 1024 1024">
    <path d="M512 64C264.96 64 64 264.96 64 512s200.96 448 448 448 448-200.96 448-448S759.04 64 512 64zm149.76 471.968L501.504 694.464c-6.24 6.144-14.368 9.248-22.496 9.248-8.256 0-16.512-3.168-22.752-9.504-12.416-12.576-12.32-32.8.256-45.248L593.92 513.056 457.632 376.384c-12.48-12.512-12.448-32.768.064-45.248 12.512-12.512 32.768-12.448 45.248.064l158.912 159.36c.032.032.032.064.064.096s.064.032.096.064c2.944 2.976 5.056 6.432 6.592 10.048.064.128.224.256.256.384 4.736 11.616 2.368 25.44-7.104 34.816z"/>
</svg>

不管采用哪种方式,都可以达到我们内联使用SVG。只不过上面这种方式是属于人肉方式。这种方式除了人肉处理之外,还有另一个弊端:在不同的地方引用同一个箭头(SVG代码)会生具有同样的代码,让你的代码变得冗余

随着工程化越来越强大,我们很多重复性的事情可以交给工程来处理。比如说,在工程中配置相关的事项,工程会帮我们处理SVG的代码。比如,将项目中的特定文件夹(比如/icons/)下的所有.svg文件合并在一起,并以SVG Sprites的方式将SVG代码内联到index.html

这样做的最大优势是“开发者无需关注内联的SVG Sprites代码是如何生成的,只需要将被使用的.svg文件存入到指定的文件目录中”。然后在调用的时候通过SVG的<use href="#id">调用SVG Sprites中<symbol id>即可。在React或Vue这样的JavaScript框架中,我们还可以创建一个独立的组件,比如Icon组件:

interface IconProps {
    type: string;
    width?: string;
    height?: string;
    className?: string;
    styleName?: string;
}

const defaultProps: IconProps = {
    type: '',
    width: '1em',
    height: '1em',
};

function Icon(props: IconProps) {
    const { type, width, height, ...rest } = {
        ...defaultProps,
        ...props,
    };

    return (
        <svg
            width={width}
            height={height}
            fill="currentColor"
            {...rest}
            xmlns="http://www.w3.org/2000/svg"
            dangerouslySetInnerHTML={{
                __html: `<use xlink:href="#icon-${type}" href="#icon-${type}"></use>`,
            }}>
                {/* <use href={`#icon-${type}`}></use> */}
        </svg>
    );
}

export default Icon;

如此一来,使用的时候也会变得简单:

<Icon type="rightarrow" />

就是这么的简单。对于在工程中如何配置自动生成SVG Sprites,可以查阅读《如何在Vue项目中使用SVG Icon》一文。这里不做更多的阐述。

这次在使用SVG Sprites踩了一个坑,那就是使用<use href="#idname">调用SVG的<symbol id="name">时在部分移动终端不能正常的渲染SVG图标,后来查阅相关文档发现是JSX引起的。所以在构建Icon组件的时候使用:

dangerouslySetInnerHTML={{__html: `<use xlink:href="#icon-${type}" href="#icon-${type}"></use>` }}

来替代

<use href={`#icon-${type}`}></use>

接下来再来说“徽标”的使用:

正如上图所示,他们之间有很多共性,不同是“颜色”和“文本内容”。用内联的SVG非常的有益,或者说,我们可以构建一个独立的组件,比如IconBadge

interface IconBadgeProps {
    text?: string;
}

const IconBadge = (props: IconBadgeProps) => {
    const { text } = props;

    return (
        <svg xmlns="https://www.w3.org/2000/svg" width="70" height="70" viewBox="0 0 70 70">
            <g fill="none" fillRule="evenodd">
                <circle cx="35" cy="35" r="34.3236486" stroke="currentColor" strokeWidth="1.3527027" />
                <circle cx="35" cy="35" r="31.739062" stroke="currentColor" strokeWidth="0.52187604" />
                <g fill="currentColor">
                    <path d="M35.18046574 13.08946812l-1.9177418 1.00821657.3662561-2.13543695-1.5514858-1.51232485 2.1441006-.31155606.9588709-1.94288472.958871 1.94288472 2.1441005.31155606-1.5514857 1.51232485.3662561 2.13543695zM47.1029719 16.08946832l-1.9177418 1.0082165.3662561-2.1354369-1.5514858-1.5123249 2.1441006-.311556.9588709-1.94288476.958871 1.94288476 2.1441006.311556-1.5514858 1.5123249.3662561 2.1354369zM23.10297162 16.08946814l-1.91774187 1.00821657.3662561-2.13543695-1.55148576-1.51232485 2.14410059-.31155606.95887094-1.94288472.95887093 1.94288472 2.14410059.31155606-1.55148576 1.51232485.36625611 2.13543695z" />
                </g>
                <g fill="currentColor">
                    <path d="M35.56785426 58.10022588l1.9177418-1.00821657-.3662561 2.13543695 1.5514858 1.51232485-2.1441006.31155606-.9588709 1.94288472-.958871-1.94288472-2.1441005-.31155606 1.5514857-1.5123
剩余80%内容付费后可查看

如需转载,烦请注明出处:https://www.w3cplus.com/css/bringing-new-css-techniques-to-production.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部