前端外描边完美实现

背景

最近在公司做画布相关的内容,涉及到了字体描边的方案选择,在三种方案对比和尝试下,最终选用了 SVG 作为字体描边的方案,今天就来讲讲这些方案的优缺点。

字体描边方案对比

text-stroke

优点: 实现效果好

缺点:

  • 兼容性一般,尤其是市面上的截图库都不支持这个属性,也就是截图后描边效果会丢失(尝试过 html2canvas、html-to-image、dom-to-image,以及公司内部的一些截图库)
  • 有描边吞字的现象:描边宽度变大时,描边会向内扩展把文本覆盖,
  • 宽度为0px的时候也依旧存在描边

效果:

text-shadow

优点: 兼容性好

缺点: 实现效果不好,怎么说呢,很难评,有种锯齿的美,毕竟人家不是干这行的 😅

效果:

SVG

优点: 兼容性好、实现效果好,整体上看比 text-stroke 效果还要好

缺点: iOS 上同样存在描边吞字的现象,但是它的缺点都可以解决,还请看下文

效果:

Canvas

优点: 兼容性好

缺点:

  • 字体整体比较模糊
  • 有描边吞字的现象
  • 需要通过 canvas api 来进行绘制

效果:

调试

上面四种方案都可以在 CodeSandBox 中自行尝试一下:

codesandbox.io/p/sandbox/s...

SVG 实现字体描边

通过 svg 的 paint-order 来实现字体描边,兼容性最好,并且实现效果也很不错,基本支持市面上所有浏览器,下面就来讲讲 SVG 字体描边方案的实现:

ini 复制代码
<svg 
    xmlns="http://www.w3.org/2000/svg" 
    width="400" height="200" 
    alignment-baseline="text-before-edge" 
    text-anchor="start"
>
  <text 
      x="0" 
      y="0" 
      alignment-baseline="text-before-edge" 
      text-anchor="start"
  >
      字体描边
  </text>
</svg>

text {
  font-size: 50px;
  font-weight: bold;
  stroke: red;
  stroke-width: 4px;
  paint-order: stroke;
}

通过 stroke-linejoin 属性,可以 对 svg 的描边有更灵活的控制:

但是在 iOS 中,使用 paint-order 有一个坑,会出现一种诡异的情况:当 stroke-width 被设置成不同值的时候,描边有可能向文字内部扩展,导致字体被吞没,最终字体的颜色变成跟描边的颜色一致。

解决这个问题当然也有一个办法:使用 svg 的 tspan

tspan 可以控制一个 text 标签中多行文本的展示,通过设置 dxdy 属性来控制与上一个 tspan 的距离。那么对于 iOS 描边展示异常这个问题,我们就有了一个解决办法:

  1. text 内添加两个 tspan
  2. 第一个 tspan 用来控制描边展示,设置 stroke-width
  3. 第二个 tspan 用户展示字体主体,覆盖在第一个 tspan 上面(设置 dx="0" dy="0"
html 复制代码
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="200">
  <text>
    <tspan x="0" y="0" style="stroke-width: 5px">
        文本
    </tspan>
    <tspan dx="0" dy="0">
        文本
    </tspan>
  </text>
</svg>

兼容性如下:

总结

  • 整体上来看,通过 SVG 实现字体描边比其他三种方案效果都要好,并且兼容性也不错;
  • 同时,tspan 可以控制 text 中的文本换行,通过 tspan 可以解决字体被描边覆盖的问题
相关推荐
小杨升级打怪中20 分钟前
前端面经-webpack篇--定义、配置、构建流程、 Loader、Tree Shaking、懒加载与预加载、代码分割、 Plugin 机制
前端·webpack·node.js
Yvonne爱编码34 分钟前
CSS- 4.4 固定定位(fixed)& 咖啡售卖官网实例
前端·css·html·状态模式·hbuilder
SuperherRo1 小时前
Web开发-JavaEE应用&SpringBoot栈&SnakeYaml反序列化链&JAR&WAR&构建打包
前端·java-ee·jar·反序列化·war·snakeyaml
大帅不是我1 小时前
Python多进程编程执行任务
java·前端·python
前端怎么个事1 小时前
框架的源码理解——V3中的ref和reactive
前端·javascript·vue.js
Ciito1 小时前
将 Element UI 表格元素导出为 Excel 文件(处理了多级表头和固定列导出的问题)
前端·vue.js·elementui·excel
不爱吃饭爱吃菜2 小时前
uniapp微信小程序一键授权登录
前端·javascript·vue.js·微信小程序·uni-app
heart000_12 小时前
从零开始打造个人主页:HTML/CSS/JS实战教程
javascript·css·html
90后小陈老师3 小时前
3D个人简历网站 5.天空、鸟、飞机
前端·javascript·3d
不爱吃糖的程序媛7 小时前
浅谈前端架构设计与工程化
前端·前端架构设计