在本教程中,我将介绍创建纯 css 动画“温度计”图表的过程;跟踪单个目标实现情况的完美方式。
我们正在建造什么
这是我们将要创建的图表(点击重新加载以查看动画):
See the Pen How to Build a CSS Thermometer Chart by Envato Tuts+ (@tutsplus) on CodePen.
1. 从数据开始
出于本演示的目的,我们需要一些数据。让我们与一些虚构的人物一起工作,这些人物描述了多年来对慈善组织的资助:
年 | 资金 |
---|---|
2018 | 95,000 欧 |
2016 | 72,000 欧 |
2015 | 50,000 欧 |
2012 | 35,000 欧 |
2010 | 15,000 欧 |
您可能已经猜到了,我们的挑战是在温度计图表中可视化这些数据。 我们将从中汲取视觉灵感 (如果你还没有听说过他们,看看他们在做什么!)。
2. 指定页面标记
我们将指定一个包含三个列表的包装器元素:
第一个列表设置 y 轴范围。如果您仔细查看上面的表格数据,您会发现第二列包含高达 95,000 的值。记住这一点,我们将定义从 0 到 100,000 的六个值,步长为 20,000。因此,y 轴的值将是 0、20,000、40,000、60,000、80,000 和 100,000。
第二个列表设置 x 轴数据。这些是从我们表的第一列中提取的,从最低到最高。但是它们的顺序并不重要,因为我们绝对会定位它们。不过请注意,在下面的标记中,一个列表项包含两次相同的年份。我们可以省略将年份设置为项目的文本节点。但重要的是将此值存储在data-year属性中。正如我们稍后会看到的,我们将把这个属性的值传递给相关的 ::before伪元素。
第三个列表对上述表格数据进行分组,从最高的资金价值到最低的资金价值。同样在这里,顺序并不重要。您也可以从最低到最高显示它们。这完全取决于您。
这是所需的标记:
<div class="chart-wrapper">
<ul class="chart-y">
<li>€100,000</li>
...
</ul>
<ul class="chart-x">
<li data-year="2010">2010</li>
...
</ul>
<ul class="chart-labels">
<li>2018 - €95,000</li>
...
</ul>
</div>
3. 定义一些基本样式
接下来,我们将设置一些 CSS 变量和一些常见的重置样式:
@font-face {
font-family: "Cheddar Gothic Sans";
src: url("cheddargothic-sans-webfont.woff2") format("woff2"),
url("cheddargothic-sans-webfont.woff") format("woff");
}
:root {
--brand-color: #21a73d;
--chart-bg-color: rgba(211, 211, 211, .3);
--chart-line-color: black;
--chart-x-color: white;
--line-color1: crimson;
--line-color2: gold;
--line-color3: firebrick;
--line-color4: orange;
--line-color5: darkblue;
--black: #2d2929;
--white: white;
--transition-delay: 0.6s;
--transition-delay-step: 0.6s;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
ul {
list-style: none;
}
a {
text-decoration: none;
color: inherit;
}
body {
font: 1rem/1.2 Georgia, serif;
padding-top: 70px;
background: var(--brand-color);
}
这里没有什么特别的事情发生,但也许需要注意的一点是,除了著名的“Georgia”系统衬线字体之外,我还使用了来自Envato Elements的优质“Cheddar Gothic”字体。
注意:为简单起见,我不会 在教程中介绍所有 CSS 规则。您可以通过单击 演示项目的CSS选项卡来检查其余部分。
4. 设置图表样式
图表包装器将是一个内容水平居中的网格容器。每列(列表)都有其默认宽度,它们之间有 4rem 的间隙。
这是相关的CSS:
.chart-wrapper {
display: grid;
justify-content: center;
grid-column-gap: 4rem;
grid-template-columns: auto auto auto;
}
y 轴
包含 y 轴数据的第一个列表也将充当网格容器。项目之间会有 3rem 的差距:
这是相关的CSS:
.chart-wrapper .chart-y {
display: grid;
grid-row-gap: 3rem;
}
x 轴
包含 x 轴数据的第二个列表将具有 50 像素的固定宽度。此外,我们会给它一些额外的样式,让它看起来像一个真正的温度计:
对应的样式如下:
/*CUSTOM VARIABLES HERE*/
.chart-wrapper .chart-x {
position: relative;
width: 50px;
border-radius: 25px;
border: 8px solid var(--chart-line-color);
background: var(--chart-bg-color);
overflow: hidden;
}
列表项将绝对定位,初始高度为 0——因此默认情况下,它们是不可见的。我们要做的另一件事是将它们的前景色设置为透明。在这种情况下,它们包含年份的文本将不可见:
/*CUSTOM VARIABLES HERE*/
.chart-wrapper .chart-x li {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 0;
color: transparent;
border-bottom-left-radius: inherit;
border-bottom-right-radius: inherit;
background: var(--chart-x-color);
transition: height 0.5s ease-out;
}
下一步,我们将为它们的 ::before伪元素指定一些样式。请记住,它的内容将包括相关data-year属性的值(参见上面的标记)。另外,它最初会被隐藏:
所需样式:
/*CUSTOM VARIABLES HERE*/
.chart-wrapper .chart-x li::before {
content: attr(data-year);
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 100;
border-top: 4px solid;
width: 20px;
opacity: 0;
padding-left: 3px;
color: var(--black);
font-size: 0.75rem;
transition: opacity 0.5s ease-out;
}
.chart-wrapper .chart-x li:nth-child(1)::before {
border-color: var(--line-color1);
}
.chart-wrapper .chart-x li:nth-child(2)::before {
border-color: var(--line-color2);
}
.chart-wrapper .chart-x li:nth-child(3)::before {
border-color: var(--line-color3);
}
.chart-wrapper .chart-x li:nth-child(4)::before {
border-color: var(--line-color4);
}
.chart-wrapper .chart-x li:nth-child(5)::before {
border-color: var(--line-color5);
}
动画项目
页面加载后,列表项的高度将被动画化并接收一个由相关资金值确定的值(见上表)。例如,值 15,000 对应于height: 15%。除了列表项之外,它们的::before伪元素也将被动画化,尽管动画不会同时运行。该项目将首先变得可见,然后是它的伪元素。
现在让我们把上面的所有需求都变成代码。
当页面加载时,我们首先将 loaded 类添加到 body:
window.addeventListener("load", () => {
document.body.classList.add("loaded");
});
此时可以按顺序对项目进行动画处理。为了实现这一点,我们将利用我之前的图表演示中使用的技术。我们将定义两个决定转换速度的 CSS 变量(如果需要,可以随意更改它们)并将它们与calc()函数结合起来。
以下是负责显示 x 轴项的 CSS 样式:
/*CUSTOM VARIABLES HERE*/
.loaded .chart-wrapper .chart-x li:nth-child(1) {
height: 15%; /*represents €15,000*/
transition-delay: var(--transition-delay);
}
.loaded .chart-wrapper .chart-x li:nth-child(2) {
height: 35%; /*represents €35,000*/
transition-delay: calc(
var(--transition-delay) + var(--transition-delay-step)
);
}
.loaded .chart-wrapper .chart-x li:nth-child(3) {
height: 50%; /*represents €50,000*/
transition-delay: calc(
var(--transition-delay) + var(--transition-delay-step) * 2
);
}
.loaded .chart-wrapper .chart-x li:nth-child(4) {
height: 72%; /*represents €72,000*/
transition-delay: calc(
var(--transition-delay) + var(--transition-delay-step) * 3
);
}
.loaded .chart-wrapper .chart-x li:nth-child(5) {
height: 95%; /*represents €95,000*/
transition-delay: calc(
var(--transition-delay) + var(--transition-delay-step) * 4
);
}
正如之前的图表演示中已经提到的,Microsoft Edge 不支持这些数学运算,因此如果您需要支持它,则必须改为传递一些静态值,如下所示:
.loaded .chart-wrapper .chart-x li:nth-child(2) {
height: 15%;
transition-delay: 1.2s;
}
.loaded .chart-wrapper .chart-x li:nth-child(3) {
height: 35%;
transition-delay: 1.8s;
}
注意:我可以 像这样在类transition-delay之外定义属性:loaded
.chart-wrapper .chart-x li:nth-child(1) {
transition-delay: var(--transition-delay);
}
无论哪种情况,结果都是一样的;动画在页面加载之前不会运行。我只选择在loaded类中包含该属性,因为我想限制 CSS 代码并将共享相同选择器的属性分组,例如这两个:
.loaded .chart-wrapper .chart-x li:nth-child(1) {
height: 15%; /*represents €15,000*/
}
.chart-wrapper .chart-x li:nth-child(1) {
transition-delay: var(--transition-delay);
}
正如前面步骤中已经讨论的那样,::before伪元素也应该出现在页面加载中:
.loaded .chart-wrapper .chart-x li::before {
opacity: 1;
}
但有更大的延迟:
/*CUSTOM VARIABLES HERE*/
.chart-wrapper .chart-x li:nth-child(1)::before {
transition-delay: calc(
var(--transition-delay) + var(--transition-delay-step)
);
}
.chart-wrapper .chart-x li:nth-child(2)::before {
transition-delay: calc(
var(--transition-delay) + var(--transition-delay-step) * 2
);
}
.chart-wrapper .chart-x li:nth-child(3)::before {
transition-delay: calc(
var(--transition-delay) + var(--transition-delay-step) * 3
);
}
.chart-wrapper .chart-x li:nth-child(4)::before {
transition-delay: calc(
var(--transition-delay) + var(--transition-delay-step) * 4
);
}
.chart-wrapper .chart-x li:nth-child(5)::before {
transition-delay: calc(
var(--transition-delay) + var(--transition-delay-step) * 5
);
}
标签
默认情况下,包含表格数据的第三个列表将被隐藏。
但是在图表动画完成的那一刻,它会出现:
.chart-wrapper .chart-labels {
opacity: 0;
transition: opacity .6s 3.8s;
}
.loaded .chart-wrapper .chart-labels {
opacity: 1;
}
注意transition-delay设置为 3.8s 的属性值。我们将使用这个值,因为x 轴transition-delay的最后一个元素的属性 设置为 3.6s:::before
最后,我们将使用::before其列表项的伪元素来创建出现在每个项目左角的彩色矩形:
以下是所需的样式:
/*CUSTOM VARIABLES HERE*/
.chart-wrapper .chart-labels li::before {
content: '';
display: inline-block;
vertical-align: middle;
width: 20px;
height: 20px;
margin-right: 10px;
}
.chart-wrapper .chart-labels li:nth-child(1)::before {
background: var(--line-color5);
}
.chart-wrapper .chart-labels li:nth-child(2)::before {
background: var(--line-color4);
}
.chart-wrapper .chart-labels li:nth-child(3)::before {
background: var(--line-color3);
}
.chart-wrapper .chart-labels li:nth-child(4)::before {
background: var(--line-color2);
}
.chart-wrapper .chart-labels li:nth-child(5)::before {
background: var(--line-color1);
}
我们的最终项目是这样的!
See the Pen How to Build a CSS Thermometer Chart by Envato Tuts+ (@tutsplus) on CodePen.
结论
就是这样的人!在本教程中,我们构建了一个纯 CSS 动画温度计图表。我希望你觉得这个练习很有趣,它会挑战你创建自己的 CSS 图表。
一如既往,感谢您的阅读!
- 我们正在建造什么
- y 轴
- x 轴
- 动画项目
- 标签