Step3、绘制眼睛

XHTML

<circle cx=“40″ cy=”60″ r=”2.5″ style=”fill: #fff;” /> <circle
cx=”60″ cy=”60″ r=”2.5″ style=”fill: #fff;” />

1
2
<circle cx=“40" cy="60" r="2.5" style="fill: #fff;" />
<circle cx="60" cy="60" r="2.5" style="fill: #fff;" />

使用基础形状,画两个个小圆点。四个属性分别是位置坐标、半径和填充颜色。
图片 1

基于SVG的解决方案


SVG使得很多图形工作变得更加简单,饼图也不例外。但是,用path路径创建饼图,需要复杂的数学计算,我们可以使用一点小技巧来代替。

我们从一个圆开始:

<svg width=”100″ height=”100″> <circle r=”30″ cx=”50″ cy=”50″
/> </svg>

1
2
3
<svg width="100" height="100">
<circle r="30" cx="50" cy="50" />
</svg>

现在,给它应用一些基础的样式:

CSS

circle { fill: yellowgreen; stroke: #655; stroke-width: 30; }

1
2
3
4
5
circle {
  fill: yellowgreen;
  stroke: #655;
  stroke-width: 30;
}

注意:你可能知道,这些CSS属性也可以作为SVG元素的属性使用,如果把可移植性考虑在内的话这可能挺方便的。

图片 2

图9:从一个绿色的SVG圆形,带一个胖胖的#655描边开始

你可以在图9中看到我们绘制的加了描边的圆。SVG描边不止有strokestroke-width属性。还有很多不是特别流行的描边相关的属性可以用于对描边进行微调。其中一个是stroke-dasharray,用于创建虚线描边。例如,我们可以使用如下:

CSS

stroke-dasharray: 20 10;

1
stroke-dasharray: 20 10;

图片 3

图10:一个简单的虚线描边,通过stroke-dasharray属性创建

这行代码的意思是我们的虚线是20的长度加上10的边距,如图10所示。在这里,你可能会好奇这个SVG描边属性和饼图究竟有什么关系呢。如果我们给描边应用一个值为0的虚线宽度,和一个大于或等于我们当前圆的周长的边距,它可能就清晰一些了(计算周长:
C = 2πr , 所以在这里  C = 2π × 30 ≈ 189 ):

CSS

stroke-dasharray: 0 189;

1
stroke-dasharray: 0 189;

图片 4

图11:不同stroke-dasharray值对应的效果;从左到右: 0 189; 40 189; 95 189; 150 189 

如图11中的第一个圆所示,它的描边的都被移除了,只剩下一个绿色的圆。但是,当我们开始增大第一个值的时候,有趣的事情发生了(图11):因为边距太长,我们就没有虚线描边了,只有一个描边覆盖了我们指定的圆的周长的百分比。

你可能已经开始弄清楚了这是怎么回事:如果我们把圆的半径减小到一定程度,它可能就会完全被它的描边覆盖,最后得到的是一个非常类似于饼图的东西。例如,你可以在图12中看到:当给圆应用一个25的半径和一个50stroke-width,像下面的效果:

图片 5

图12:我们的SVG图像开始像一个饼图了O(∩_∩)O

记住:SVG描边总是相对于元素边缘一半在内一半在外的(居中的)。将来应该可以控制这一行为。

<svg width=”100″ height=”100″> <circle r=”25″ cx=”50″ cy=”50″
/> </svg> circle { fill: yellowgreen; stroke: #655;
stroke-width: 50; stroke-dasharray: 60 158; /* 2π × 25 ≈ 158 */ }

1
2
3
4
5
6
7
8
9
10
<svg width="100" height="100">
  <circle r="25" cx="50" cy="50" />
</svg>
 
circle {
  fill: yellowgreen;
  stroke: #655;
  stroke-width: 50;
  stroke-dasharray: 60 158; /* 2π × 25 ≈ 158 */
}

现在,把它变成我们在上一个解决方案中制作的饼图的样子是非常容易的:我们只需要在描边下面添加一个更大的绿色圆形,然后逆时针旋转90°,这样它的起点就在顶部中间。因为<svg>元素也是HTML元素,我们可以给它添加样式:

CSS

svg { transform: rotate(-90deg); background: yellowgreen; border-radius:
50%; }

1
2
3
4
5
svg {
  transform: rotate(-90deg);
  background: yellowgreen;
  border-radius: 50%;
}

图片 6

图13:最后的SVG饼图

你可以在图13中看到最终结果。这种技术可以让饼图更容易实现从0%100%变化的动画。我们只需要创建一个CSS动画,让stroke-dasharray
0 158 变成 158 158 :

CSS

@keyframes fillup { to { stroke-dasharray: 158 158; } } circle { fill:
yellowgreen; stroke: #655; stroke-width: 50; stroke-dasharray: 0 158;
animation: fillup 5s linear infinite; }

1
2
3
4
5
6
7
8
9
10
11
@keyframes fillup {
  to { stroke-dasharray: 158 158; }
}
 
circle {
  fill: yellowgreen;
  stroke: #655;
  stroke-width: 50;
  stroke-dasharray: 0 158;
  animation: fillup 5s linear infinite;
}

作为一个额外的改进,我们可以在圆上指定一个特定半径,使其周长无限接近100,这样我们可以用百分比指定stroke-dasharray的长度,而不需要做计算。因为周长是2πr,我们的半径则是100 ÷ 2π ≈ 15.915494309,约等于16。我们还可以用viewBox特性指定SVG的尺寸,可以让它自动调整为容器的大小,不要使用widthheight属性。

经过以上调整,图13的饼图的HTML标签如下:

<svg viewBox=”0 0 32 32″> <circle r=”16″ cx=”16″ cy=”16″ />
</svg>

1
2
3
<svg viewBox="0 0 32 32">
  <circle r="16" cx="16" cy="16" />
</svg>

CSS如下:

CSS

svg { width: 100px; height: 100px; transform: rotate(-90deg);
background: yellowgreen; border-radius: 50%; } circle { fill:
yellowgreen; stroke: #655; stroke-width: 32; stroke-dasharray: 38 100;
/* for 38% */ }

1
2
3
4
5
6
7
8
9
10
11
12
13
svg {
  width: 100px; height: 100px;
  transform: rotate(-90deg);
  background: yellowgreen;
  border-radius: 50%;
}
 
circle {
  fill: yellowgreen;
  stroke: #655;
  stroke-width: 32;
  stroke-dasharray: 38 100; /* for 38% */
}

注意现在百分比已经可以很方便地改变了。当然,即使已经简化了标签,我们还是不想在绘制每个饼图的时候都重复一遍所有这些SVG标签。这是时候拿出JavaScript来帮我们一把了。我们写一个简单的脚本,让我们的HTML标签直接简单地这样写:

<div class=”pie”>20%</div> <div
class=”pie”>60%</div>

1
2
<div class="pie">20%</div>
<div class="pie">60%</div>

然后在每个.pie元素里边添加一个内联SVG,包括所有需要的元素和属性。它还会添加一个<title>元素,为了增加可访问性,这样屏幕阅读器用户还可以知道当前的饼图表示的百分比。最后的脚本如下:

JavaScript

$$(‘.pie’).forEach(function(pie) { var p = parseFloat(pie.textContent);
var NS = “http://www.w3.org/2000/svg“; var svg =
document.createElementNS(NS, “svg”); var circle =
document.createElementNS(NS, “circle”); var title =
document.createElementNS(NS, “title”); circle.setAttribute(“r”, 16);
circle.setAttribute(“cx”, 16); circle.setAttribute(“cy”, 16);
circle.setAttribute(“stroke-dasharray”, p + ” 100″);
svg.setAttribute(“viewBox”, “0 0 32 32″); title.textContent =
pie.textContent; pie.textContent = ”; svg.appendChild(title);
svg.appendChild(circle); pie.appendChild(svg); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$$(‘.pie’).forEach(function(pie) {
  var p = parseFloat(pie.textContent);
  var NS = "http://www.w3.org/2000/svg";
  var svg = document.createElementNS(NS, "svg");
  var circle = document.createElementNS(NS, "circle");
  var title = document.createElementNS(NS, "title");
  circle.setAttribute("r", 16);
  circle.setAttribute("cx", 16);
  circle.setAttribute("cy", 16);
  circle.setAttribute("stroke-dasharray", p + " 100");
  svg.setAttribute("viewBox", "0 0 32 32");
  title.textContent = pie.textContent;
  pie.textContent = ”;
  svg.appendChild(title);
  svg.appendChild(circle);
  pie.appendChild(svg);
});

就是它了!你可能会觉得CSS方法比较好,因为它的代码比较简单而且更靠谱。但是,SVG方法相比纯CSS方案还是有一定的优势的:

  • 可以非常容易地添加第三种颜色:只需要添加另一个描边圆,然后使用stroke-dashoffset设置它的描边属性。然后,将它的描边长度添加到下方的圆的描边长度上。如果是前面那个CSS的方案,你要如何给饼图添加第三种颜色呢?
  • 我们不需要考虑打印的问题,因为SVG元素就像<img>元素一样,被默认为是内容的一部分,打印完全没有问题。第一种方案取决于背景,所以不会被打印。
  • 我们可以使用内联样式改变颜色,也就是说我们可以通过脚本就直接改变颜色(如,根据用户输入改变颜色)。第一种方案依赖于伪元素,除了通过继承,它没有其它办法可以添加内联样式,这很不方便。

See the Pen oXVBar by Airen
(@airen) on CodePen.

Step1、声明SVG视口

XHTML

<svg width=”100″ height=“100”></svg>

1
<svg width="100" height=“100”></svg>

指定一个宽高都为100像素的区域,width=”100”和width=”100px”是等价的,当然也可以使用其他的合法单位,例如cm、mm、em等

阅读器会设置一个默认的坐标系统,见图:左上角为原点,其中水平(x)坐标向右递增,垂直(y)坐标向下递增。

图片 7

在没有指定的情况下,所有的的数值默认单位都是像素。

用CSS和SVG制作饼图

2015/08/10 · CSS ·
SVG

原文出处: Lea
Verou
   译文出处:lulux的博客   

在涉及到CSS技术时,没有人会比Lea
Verou
更执着、但是又足够聪明,努力去找寻问题的各种解决方案。最近,Lea自己撰写、设计和出版了一本书——CSS
Secrets
,这本书非常有趣,包括一些CSS小技巧以及解决常见问题的技术。如果你觉得自己的CSS技术还不错,看看这本书,你会吃惊的。在这篇文章中,我们发布了书里的一些片段,这也被发表在Lea最近在SmashingConf
New
York的演讲内容中——用CSS设计简单的饼图。注意,因为浏览器的支持有限,有些demo可能不能正常运行。——编辑

饼图,即使是最简单的只有两种颜色的形式,用Web技术创建也并不简单,尽管都是一些常见的信息内容,从简单的统计到进度条指标还有计时器。通常是使用外部图像编辑器来分别为多个值创建多个图像来实现,或是使用大型的JavaScript框架来设计更复杂的图表。

尽管这个东西并不像它曾经看起来那么难以实现,但是也没有什么直接并且简单的方法。但是,现在已经有很多更好、更易于维护的方式来实现它。

Step7、将不同部位的动画组合到一起

  • 眼睛的动画是从嘴巴旋转完成开始,到嘴巴变形完成结束,因此和嘴巴的动画一样,我设置了四个对应的关键时间点。
  • 为了让衔接更顺畅,眼睛的动画开始比嘴巴变形开始稍微提前了一点点。

图片 8

参考:

图片 9

相关资源


Step4、绘制嘴巴

XHTML

<circle cx=”50″ cy=”70″ r=”15″ style=”fill: none; stroke: #fff;
stroke-width: 5; stroke-linecap: round;transform: rotate(280deg);
transform-origin: 50% 50%; stroke-dashoffset: -23; stroke-dasharray: 42,
95;”>

1
<circle cx="50" cy="70" r="15" style="fill: none; stroke: #fff; stroke-width: 5; stroke-linecap: round;transform: rotate(280deg); transform-origin: 50% 50%; stroke-dashoffset: -23; stroke-dasharray: 42, 95;”>

嘴巴是一段圆弧,我绘制了一个圆,然后描边了其中的一段,并且做了一个旋转,来让它的角度处于正确的位置。

  • stroke-linecap:用来定义开放路径的终结,可选round|butt|square
  • stroke-dasharray:用来创建虚线
  • stroke-dashoffset:设置虚线位置的起始偏移值,在下一步骤里,它会和stroke-dasharray一起用来实现动效。

图片 10

将来的饼图


圆锥形渐变在这里也可以非常有帮助。它只需要一个圆形元素,以及带有两个色标的锥形渐变即可做出饼图。例如,图5中表示40%的饼图可以这样完成:

图片 11

CSS

.pie { width: 100px; height: 100px; border-radius: 50%; background:
conic-gradient(#655 40%, yellowgreen 0); }

1
2
3
4
5
.pie {
  width: 100px; height: 100px;
  border-radius: 50%;
  background: conic-gradient(#655 40%, yellowgreen 0);
}

还有,一旦CSS Values Level
3
中定义的attr()函数更新后被广泛应用,你就可以用简单的HTML属性来控制百分比了:

CSS

background: conic-gradient(#655 attr(data-value %), yellowgreen 0);

1
background: conic-gradient(#655 attr(data-value %), yellowgreen 0);

要添加第三种颜色也非常容易。例如,对于上面展示的饼图,我们只需要再增加两个色标:

CSS

background: conic-gradient(deeppink 20%, #fb3 0, #fb3 30%, yellowgreen
0);

1
background: conic-gradient(deeppink 20%, #fb3 0, #fb3 30%, yellowgreen 0);

:多亏了Lea的锥形渐变polyfill,我们现在才可以使用锥形渐变,在她的SmashingConf演讲结束不久之后发表的。这可能就是你将来用CSS来设计饼图的方式!这里的三种方法你会使用什么哪种,以及为什么这样做?或者你已经想到了一个完全不同的解决方案?请在评论中留言~

1 赞 2 收藏
评论

图片 12

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图