分类
前端

使用 SVG 制作扇形

有时候我们需要制作扇形,比如图形化数据生成饼图的时候。使用 HTML + CSS 做不到,必须借助 SVG 帮助。经过一些摸索,大概方式如下:

0. 创建 SVG

我们需要一个 SVG,然后在里面画一个园:

<svg xmlns="http://www.w3.org/2000/svg" height="600" width="600" viewBox="0 0 20 20">
  <circle r="5" cx="10" cy="10" />
</svg>

这里,我创建了一个 SVG,并且以 10,10 位圆心,画了一个半径为 5 的圆。SVG 的视窗只需要显示这个圆,所以是 0 0 20 20 的正方形。widthheight 用来定义网页中 SVG 的尺寸,SVG 是矢量图形,可以实现内容的无损缩放,所以即使显示尺寸比图形尺寸大很多,也不用担心出现锯齿。

1. 用边框画圆形

接下来,我们用给圆加边框的方式来做圆形。

<circle
  r="5"
  cx="10"
  cy="10"
  fill="transparent"
  stroke="tomato"
  stroke-linecap="butt"
  stroke-width="10"
></circle>

首先,我们用 fill="transparent" 清理掉圆形内部的颜色,然后用 stroke="tomato" 给边框加上橙色。接下来,我们通过 stroke-width="10" 设置边框宽度为 10,这也是矩形半径。

此时,屏幕上会出现一个橙色的正圆。

2. 画扇形

画扇形的方式有很多,比如画两条半径然后画弧形再填充颜色。但是利用边框画扇形最简单。

用边框画扇形说白了,其实是结合圆环和虚线,需要有扇形的地方,就填充颜色;不需要扇形的地方,就用虚线的空白。这里要用到 stroke-dasharray 属性,它的规则很简单,奇数为实偶数为虚,所以我们只要计算扇形所需的弧形长度,然后剩下的填充周长即可。

在我们这里,就是 stroke-dasharray=”calc(10 * 3.1415926 * 1/6) 31.415926",即取绘制一个 1/6 大小的扇形。

3. 修改位置

修改位置需要使用 stroke-dashoffset 属性,它会把图形从原来的位置移动若干距离,正的就往起点移动,负的就往终点移动。

在我们这里,就是 stroke-dashoffset="calc(-10 * 3.1415926 * 1/6)",将第二个扇形移到第一个扇形的旁边。

4. 其它+已知问题+扩展阅读

最终效果:https://codepen.io/meathill/pen/yLMQqBQ?editors=1000

这些属性,也可以使用 CSS 样式替换,效果一样。

Safari 问题比较多,首先半圆就不是半圆,其次偏移也不对,不知道是否只支持 CSS。

分类
前端

Bootstrap 发布图表库 Bootstrap Icons 1.0,该准备切换到 SVG 了

Bootstrap 团队一边开发 Bootstrap 5,一边发布了 Bootstrap Icons 1.0(以下简称 BI)。官方全文见此:Bootstrap Icons v1.0.0。这个版本里包含 1100 个图标,涵盖范围很广,全免费(MIT),可以自由使用、修改。

真正引起我注意的是,这个仓库不再使用 Webfont,而是全部使用 SVG。官方文档 介绍了三种使用方式:

  1. 直接嵌入 SVG 代码
  2. <svg> 中引用 BI 库并配合 <use> 使用
  3. 通过 bootstrap-icons/icons/*.svg 直接使用

如果你非常怀念 Webfont 方式,可以用(3)结合 CSS background-image 的方式近似的模拟。

其实,GitHub 很早以前就开始从 Webfont(Icon font) 向 SVG 切换了,他们还特地写了篇博客解释这件事情:Delivering Octicons with SVG,在里面列举了六个理由:

  1. Icon font 本身存在一些渲染问题,Webkit 内核的浏览器会使其边缘模糊,不利于辨识
  2. Icon font 一般会延后加载,而字体在完成加载之前无法判定大小,所以加载完成之后,需要重新计算布局并且重新进行渲染,造成不必要的性能损耗
  3. 可用性。参考这篇 Slide:Death to Icon Fonts,每十个人当中就有一个人存在阅读障碍,他们很难使用普通字体,必须使用专为他们设计的特殊字体,而这个时候,icon font 就会变成没有意义的方块。对使用阅读器的人更甚:icon font 是一种 hack,通常来说,我们并不会真的写文字进去,所以在他们看起来,图标会变得完全不可读。
  4. 合适的图标尺寸
  5. 方便重构字体文件
  6. 方便制作动画

所以,如今 Bootstrap 放弃 webfont,使用 SVG 作为主要格式,应该说是大势所趋。这几年使用 Webfont,的确很方便,给开发带来很大的效率提升,但与此同时,也存在不少问题:

  1. fontawesome 体积越来越大,现在一组字体要 1M+,加载很耗时,但是拆分非常困难,即使只用几个图标,也需要加载整个字体库
  2. 无法对图标进行稍微复杂的操作,比如双色,或者特定部位的动画
  3. 放大之后,图标比较丑,也不好加工
  4. 前面说过的那些问题

所以未来我和我厂也要慢慢从 webfont 切回 SVG。这样也有助于提升我厂产品的可用性。其实,互联网行业的可用性一直都做得不错,软件开发目前也算是残障人士最有机会获得体面收入的机会,所以,我辈仍需努力呀。

分类
js

用 SVG 画五角星

先上代码:

See the Pen draw a star by Meathill (@meathill) on CodePen.


话说前两日想起来填坑,需要用五角星做示例。正好前几天买了本 SVG 的书,就想试一下。这篇文章记录其中几个要点。

多边形 <polygon>

在 SVG 中,画多边形要用到 <polygon>,它有一个属性 points 可以用来定义各个点的座标。有了它我们就可以连点成线做出想要的多边形了。

创建 SVG 元素

以前直接使用 document.createElement() 就能创建出想要的元素,然而 SVG 并非普通的文档,所以要小小的变动一下,使用命名空间来创建合适的元素:

var svg = document.getElementById('svg')
  , ns = svg.namespaceURI
  , star = document.createElementNS(ns, 'polygon');

先取到页面中写好的 SVG 节点,然后取得它的命名空间,最后借由它创建需要的元素。

使用 JS 操作元素

SVG 元素都是 SVGElement,对他们进行操作是需要一点技巧的。

比如,向对变形增加顶点就需要

var point = svg.createSVGPoint();
point.x = 10;
point.y = 10;
star.points.appendItem(point);

总结

整体说来 SVG 操作还是蛮简单的,将来可能简单的绘图都直接用代码写了。