使用postcss-write-svg在retina屏绘制1px细线

2,736 阅读3分钟

一、实现方式

本文章采用postcss-write-svg与border-image这个css3属性进行1px细线的绘制(仅适合直线,圆角建议用transform于伪类实现),其他的像border-shadow、transform与伪类的实现方式在这里就不说了,网上也搜得到。

具体代码在这webpack-esnext-cli,目录src/pages/test下有使用svg绘制1px线的全部例子。

二、border-image

简单介绍一下border-image的拆分:

border-image-source:url('bg.jpg'); // 用于设置背景源图片
border-image-slice: 1; // 用于设置九宫格上右下左四个方向的裁切比例(也可设置百分比)
border-image-repeat: stretch; // 图片在各边进行拉伸、平铺或重复
border-image-width: 1;  // 定义图像边框宽度假如border-image-width大于已指定的border-width,那么它将向内部(padding/content)扩展.
border-image-outset: 0; // 定义边框图像可超出边框盒的大小

原理可以看看CSS3 border-image详解,讲解的很清晰了。

三、postcss-write-svg使用

首先我们先配置好postcss-write-svg,这里我们选择生成base64编码图片

require("postcss-write-svg")({
  utf8: false
})

在css中写一个svg的生成函数

// 仓库的例子中,我是将svg函数写在assets/scss/svg.scss中了,通过webpack插件sass-resources-loader自动引用,所以在vue单文件中可以直接使用不需要再写一遍
@svg 1px-border {
  width: 4px;
  height: 4px;
  @rect {
    fill: transparent;  // content为透明
    width: 100%;  // 宽度为4px * 100%
    height: 100%;  // 高度为4px * 100%
    stroke-width: 25%;  // 边框宽度 4px * 25%(即1px)
    stroke: var(--color, black);  // 颜色
  }
}

上面的函数,可以让我们生成一个有1px边框,宽高为4px的矩形,下面是我运用此svg函数生成的1px线:

途中可以看到,我们使用普通的border: 1px solid red;生成的1px线是会粗一点的,这是由于retine屏幕导致的(原理可看大漠的一篇再谈Retina下1px的解决方案_CSS, mobile 教程_w3cplus)。下面是该函数的具体应用:

#real-1px {
  margin: 10px;
  height: 20px;
}

#real-1px {
  border: 1px solid;
  border-image: svg(1px-border param(--color red)) 1 stretch;
}

这里使用25%的裁切(即上右下左各做1px的裁切,获取裁切出来的部位给我们的border进行背景的设置),这里我们裁切出一个具有1px红边框与1px透明内边框的图片大概如下图所示

很多教程里面会这么使用,boder: 1px solid transparent,安卓高版本没问题(至少我的一加没有问题),但是安卓的部分低版本和iphone,border都不会出现,所以我们这里如果是四边,trasparent去除后可以解决该问题。

这里你会发现图中在低版本安卓和iphone中有个错误的上边框显示,三条1px边框是粗的,单边上边框却是细的。

下面是解决方法

// 仓库中代码编写了mixin去做这种兼容,比如设置顶部边框,则@include setSvgSingleBorder(top);
#real-top-1px {
  ...

  border: 0;    // 将其余三遍的border宽度设置成0
  border-top: 1px solid;   // 这里将单边覆盖上面border的宽度设置
  border-image: svg(1px-border param(--color red)) 1 stretch;
}

上面我们需要将border的其余三边不需要显示红线的设置为0,否则将会出现兼容问题,iphone与部分低端安卓无法正常显示。这样我们就可以在开发中愉快得使用svg去绘制自己想要的1px细线了。

最后,感谢网上这么多的文章,感谢公司UI小姐姐的火眼金睛。