将新的CSS技术引入到生产中
特别声明:小站已开通年费VIP通道,年费价格为 ¥365.00元。如果您喜欢小站的内容,可以点击开通会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!(^_^)
时间如梭,又一年双11圆满收官了。作为技术宅男除了买买买之外还能和大家聊的就是前端技术了。
"淘宝盖楼"上热搜了,我想你应该也参加了双十一淘宝盖楼吧,是不是觉得特别的酸爽。今年有幸参与盖楼的互动活动的开发中备感荣幸,因为我们的努力让全民都爽了。在开始之前要先感谢一下曾经努力的自己!
楼盖完了,我们回过头来聊聊这次多人互动PK在开发的时候用了哪些有意思的前端技术。感兴趣的同学,请继续往下阅读。
去年双十一能量PK互动项目中我们用了些有意思的前端技术,要是你感兴趣的话,可以阅读《聊聊双11互动主动法中前端技术亮点》一文。
SVG运用和优势
先来说图标(Icon)的使用。整套视觉下来,页面上的图标(或类似图标)的场景还是蛮多的,比如:
仔细分析一下,有些图标是具有共性的,或者说只有一点点差异:
别的图标暂且不表,有两个地方是有共性的:
- 箭头图标是相同的,如果说差异,就是箭头有没有带容器和箭头容器的颜色有差异
- 微标(票房状态的图标,比如“平局”、“获胜”等),在不同的地方仅仅是颜色和大小的差异
自有Web技术到现在,Web上使用图标的技术也随着时代的变迁在改变:
<img>
引用独立的Icon图片文件background-image
替代<img>
标签,引用独立的Icon图片文件- 将众多Icon图片合并在一起(俗称Sprites),使用
background-image
和background-position
来控制Icon图标的显示和位置 - Icon Font的使用,比如阿里IconFont和Font 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的fill
或strock
属性,不管SVG标签行内添加样式,还是在CSS样式表中添加样式,可以将fill
和strock
设置为currentColor
。
currentColor
是CSS中第一个变量属性值,最大的特性就是可以根据当前color
来决定值。
如果你对currentColor
感兴趣的话,还可以阅读:
箭头容器就很好控制了,通过CSS很好的设置。
该方案最大的优势,我们只需要一个箭头的矢量图(SVG的path
就可以很好解决)。第二种思路要比上面这种略差一点,因为需要两个SVG的代码(两个不同的.svg
)文件。一个是像上面所示的代码,不带容器;另外一个就是像下面这样的SVG代码,带圆形容器:
代码如下,也是用SVG的path
绘制出来,同样的fill
或strock
设置为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
如需转载,烦请注明出处:https://www.w3cplus.com/css/bringing-new-css-techniques-to-production.html
如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!