带有CSS3的动画3D条形图

时间:2022-04-21
本文章向大家介绍带有CSS3的动画3D条形图,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

关于如何使用CSS创建动画三维条形图的教程。

这一切都是从一个小实验开始的,这个实验受到了来自Nettuts +的教程的启发,它展示了如何使用CSS,图像和JavaScript将3D条形图嵌入到HTML页面中。在阅读完教程之后,我挑战自己将这个想法变成纯粹的CSS,看看我能做多少。最初的挑战是创造一个经典的半透明的6方框3D盒子。最后的挑战是创建一个完整的三维条形图,我们将在本教程中创建。

你可以看看我以前做过这里。

请注意:本教程的结果只能在支持相应CSS属性的浏览器中按预期方式工作。

我们写下一些关键的要求。图表应该是

背景无关

自适应(独立于条数)

可扩展(就像矢量图形)

轻松定制(颜色,大小和比例)

规划阶段是任何项目中最重要的部分。所以让我们制定一个计划。

在实际编写代码之前,我通常会写下所有可能遇到的挑战,并在一个特定的项目中考虑我所能想到的解决方案,并重复这个过程直到我看到一个看起来像是可以执行的策略。下面是我为这个项目提出的解决方案的挑战列表:

挑战#1 - 一个可移动的内部块的酒吧

我们知道:

一个酒吧应该被表示为由六面组成的三维盒子

内块应能在运动中垂直移动。应该有一个选项来隐藏块。

我们需要什么:

1格,由三面组成(背面,底面,左边)

前部外壳1格,由3面组成(正面,顶部,右侧)

内部块为1格,由3个边组成,与前面的外壳完全一样,但Z值较低

1格容器,将所有三块相对放置,并在右下角应用一个坚实的背景补丁

1个带有溢出的容器:隐藏时,隐藏栏内的内部块,当它归零时

这总共有5个div。

你可能想知道为什么我们需要两个容器?那么,这可能是一个棘手的部分,但我会尽力解释。

我们每栏至少需要一个容器(相对于前面的壳体,后面的壳体和内部的模块)。我们知道我们的酒吧应该是可扩展的,所以我们用百分比来操纵酒吧的填充值,这就要求我们的酒吧的高度等于酒吧的一边的高度。

看起来不错,但是等一下,看起来还有另一个问题 - 应该有一个隐藏内部块的选项,这意味着它应该“在酒吧下面”并隐藏在那里。你可以说我们有一个解决方案 - 溢出:隐藏,对不对?是的,但不是那个容器,因为它的高度比杆的实际高度短。这就是为什么我们添加另一个容器,并应用溢出:隐藏。

希望这是有道理的。让我们继续。

挑战2 - 图表持有者

图表持有人应该

用三维轴和三面(背景,底部,左)

独立于后台

适应条数及其属性(高度,宽度等)

从外面有X和Y轴标签

我们需要什么:

1个无序列表

X轴标签的每个列表项中的1个元素

每个列表项目内部有1个栏

1个列表项,其中有一个无序列表,用于Y轴标签

嗯,无序列表?使用条形图的定义列表是否更有意义?那么,它可能更多的语义,但我们不能使用它,因为我们必须将每个酒吧和自己的X轴标签包装在一个容器中,以便相对定位它们。

好的,但为什么我们不使用列表项而不是第二个容器呢?嗯,我们不能这样做,因为我们必须将X轴标签放在图的外面,因为我们知道吧的第二个容器隐藏了溢出它的任何内容,我们将使用列表项来确保所有元素都被正确定位。

实施

现在我们有了一个策略,让我们把它转换成代码。

请注意,本教程中不会使用供应商前缀。当然,您可以在演示的CSS文件中找到它们。

挑战#1 - 一个可移动的内部块的酒吧

50

让我们再次回顾一下每个元素的目的:

酒吧包装 - 隐藏。酒吧内,当它滑落下面的酒吧

bar-container - 相对位置.bar-foreground,.bar-inner,.bar-foreground,并将补丁放置在底角

酒吧背景 - 创建三面的外壳:背部,底部,左侧

酒吧内 - 最重要的部分可能 - 内部块

酒吧前景 - 创建三面的外壳:前,上,右

首先,让我们风格的容器。

/* Bar wrapper - hides the inner bar when it goes below the bar, required */

.bar-wrapper {

overflow: hidden;

}

/* Bar container - this guy is a real parent of a bar's parts - they all are positioned relative to him */

.bar-container {

position: relative;

margin-top: 2.5em; /* should be at least equal to the top offset of background casing */

/* because back casing is positioned higher than actual bar */

width: 12.5em; /* required, we have to define the width of a bar */

}

/* right bottom patch - make sure inner bar's right bottom corner is "cut" when it slides down */

.bar-container:before {

content: "";

position: absolute;

z-index: 3; /* to be above .bar-inner */

bottom: 0;

right: 0;

/* Use bottom border to shape triangle */

width: 0;

height: 0;

border-style: solid;

border-width: 0 0 2.5em 2.5em;

border-color: transparent transparent rgba(183,183,183,1);

}

请注意,我们将.bar-container的宽度设置为12.5em。这个数字是酒吧的正面和右边宽度的总和 - 在我们的例子中是10 + 2.5 = 12.5

我们还使用边框来塑造三角形,并将其放置在.bar-container的右下角,以确保在竖直移动时内栏的“边”被切割。我们使用:before伪类生成这个元素; 我们将在本教程中使用:之前和之后:伪类很多。

现在让我们来设计背部外壳:

/* Back panel */

.bar-background {

width: 10em;

height: 100%;

position: absolute;

top: -2.5em;

left: 2.5em;

z-index: 1; /* just for reference */

}

.bar-background:before,

.bar-background:after {

content: "";

position: absolute;

}

/* Bottom panel */

.bar-background:before {

bottom: -2.5em;

right: 1.25em;

width: 10em;

height: 2.5em;

transform: skew(-45deg);

}

/* Left back panel */

.bar-background:after {

top: 1.25em;

right: 10em;

width: 2.5em;

height: 100%;

/* skew only the Y-axis */

transform: skew(0deg, -45deg);

}

正如你所看到的,我们把2.5em的套管向右移动。果然,我们歪斜了左右两边45度。请注意,我们将第一个偏移值设置为0deg,第二个偏移值设置为-45deg,这使我们能够垂直倾斜该元素。

现在是时候风格的前壳。

/* Front panel */

.bar-foreground {

z-index: 3; /* be above .bar-background and .bar-inner */

}

.bar-foreground,

.bar-inner {

position: absolute;

width: 10em;

height: 100%;

top: 0;

left: 0;

}

.bar-foreground:before,

.bar-foreground:after,

.bar-inner:before,

.bar-inner:after {

content: "";

position: absolute;

}

/* Right front panel */

.bar-foreground:before,

.bar-inner:before {

top: -1.25em;

right: -2.5em;

width: 2.5em;

height: 100%;

background-color: rgba(160, 160, 160, .27);

transform: skew(0deg, -45deg);

}

/* Top front panel */

.bar-foreground:after,

.bar-inner:after {

top: -2.5em;

right: -1.25em;

width: 100%;

height: 2.5em;

background-color: rgba(160, 160, 160, .2);

transform: skew(-45deg);

}

这里没有什么新东西,一切和后面的箱体样式一样,我们只是用不同的方向。

好的部分是,我们将这些样式应用于前部壳体和内部块体。为什么不?他们的形状完全一样。

好吧,现在我们还没有应用内部块的样式。

.bar-inner {

z-index: 2; /* to be above .bar-background */

top: auto; /* reset position top */

background-color: rgba(5, 62, 123, .6);

height: 0;

bottom: -2.5em;

color: transparent; /* hide text values */

transition: height 1s linear, bottom 1s linear;

}

/* Right panel */

.bar-inner:before {

background-color: rgba(5, 62, 123, .6);

}

/* Top panel */

.bar-inner:after {

background-color: rgba(47, 83, 122, .7);

}

大!酒吧都设置。让我们继续看图表。

挑战2 - 图表支架(带有轴标签)

2011

2012

25%

50%

75%

100%

正如您所看到的,我们使用无序列表和项目内的span元素来定位X轴和Y轴标签。

/** Graph Holder container **/

.graph-container {

position: relative; /* required Y axis stuff, Graph Holder's left and bottom sides to be positions properly */

display: inline-block; /* display: table may also work.. */

padding: 0; /* let the bars position themselves */

list-style: none; /* we don't want to see any default

markers */

/* Graph Holder's Background */

background-image: linear-gradient(left , rgba(255, 255, 255, .3) 100%, transparent 100%);

background-repeat: no-repeat;

background-position: 0 -2.5em;

}

这里棘手的部分是背景。我们使用线性渐变来填充图形容器,并将其提升2.5em。为什么?因为我们的图形持有人的底部(我们将下一个样式)是2.5em高,并倾斜了45度,所以在右下角有一个空的空间。

现在让我们设计底部。

/* Graph Holder bottom side */

.graph-container:before {

position: absolute;

content: "";

bottom: 0;

left: -1.25em; /* skew pushes it left, so we move it a bit in opposite direction */

width: 100%; /* make sure it is as wide as the whole graph */

height: 2.5em;

background-color: rgba(183, 183, 183, 1);

/* Make it look as if in perspective */

transform: skew(-45deg);

}

我们把它倾斜45度,稍微向左移一点,以确保它的位置正确。

现在,让我们的风格留在我们的图形持有者的一边:

/* Graph Holder left side*/

.graph-container:after {

position: absolute;

content: "";

top: 1.25em; /* skew pushes it up so we move it down a bit */

left: 0em;

width: 2.5em;

background-color: rgba(28, 29, 30, .4);

/* Make it look as if in perspective */

transform: skew(0deg, -45deg);

}

这里没什么特别的 就像往常一样将元件倾斜45度,并将其稍微推下,以便正确定位。

我们完成了图表的持有者。现在,让我们添加一些魔术到持有我们的酒吧的列表项目:

/* Bars and X-axis labels holder */

.graph-container > li {

float: left; /* Make sure bars are aligned one next to another*/

position: relative; /* Make sure X-axis labels are positioned relatively to this element */

}

/* A small hack to make Graph Holder's background side be wide enough

...because our bottom side is skewed and pushed to the right, we have to compensate it in the graph holder's background */

.graph-container > li:nth-last-child(2) {

margin-right: 2.5em;

}

/* X-axis labels */

.graph-container > li > span {

position: absolute;

left: 0;

bottom: -2em;

width: 80%; /* play with this one if you change perspective depth */

text-align: center;

font-size: 1.5em;

color: rgba(200, 200, 200, .4);

}

这里发生了一些事情。首先,我们把我们的酒吧放在一起。通常情况下,我试图使用浮动块非常小心,但在这种情况下,它完全符合我的意见。

其次,我们在最后一栏添加一些右边距。这样我们确保我们给图表底部的足够的空间显示在右下角。尝试删除它,你会明白我的意思。

好的,我们快到了。剩下的最后一件事是添加Y轴标记。

/* Markers container */

.graph-container > li:last-child {

width: 100%;

position: absolute;

left: 0;

bottom: 0;

}

/* Y-axis Markers list */

.graph-marker-container > li {

position: absolute;

left: -2.5em;

bottom: 0;

width: 100%;

margin-bottom: 2.5em;

list-style: none;

}

/* Y-axis lines general styles */

.graph-marker-container > li:before,

.graph-marker-container > li:after {

content: "";

position: absolute;

border-style: none none dotted;

border-color: rgba(100, 100, 100, .15);

border-width: 0 0 .15em;

background: rgba(133, 133, 133, .15);

}

/* Y-axis Side line */

.graph-marker-container > li:before {

width: 3.55em;

height: 0;

bottom: -1.22em;

left: -.55em;

z-index: 2; /* be above .graph-container:after */

transform: rotate(-45deg);

}

/* Y-axis Background line */

.graph-marker-container li:after {

width: 100%;

bottom: 0;

left: 2.5em;

}

/* Y-axis text Label */

.graph-marker-container span {

color: rgba(200, 200, 200, .4);

position: absolute;

top: 1em;

left: -3.5em; /* just to push it away from the graph.. */

width: 3.5em; /* give it absolute value of left offset */

font-size: 1.5em;

}

正如您所看到的,我们将100%的宽度设置到我们的标记支架上,以便能够在整个图形中绘制,使用虚线边框来设置我们的Y轴线并定位跨度元素,使得Y轴标签为在图表之外。借助:之前和之后:我们可以保持我们的HTML很干净。

那么,我们完成了图表的所有样式的设置,但是我们没有设置一些重要的变量 - 尺寸,颜色和条形填充值!我们说我们的图表是可定制的,对吗?所以,我决定不把变量和其余的代码混合在一起,这样你就可以和他们一起玩。

/****************

* SIZES *

****************/

/* Size of the Graph */

.graph-container,

.bar-container {

font-size: 8px;

}

/* Height of Bars */

.bar-container,

.graph-container:after,

.graph-container > li:last-child {

height: 40em;

}

/****************

* SPACING *

****************/

/* spacing between bars */

.graph-container > li .bar-container {

margin-right: 1.5em;

}

/* spacing before first bar */

.graph-container > li:first-child {

margin-left: 1.5em;

}

/* spacing after last bar */

.graph-container > li:nth-last-child(2) .bar-container {

margin-right: 1.5em;

}

/****************

* Colors *

****************/

/* Bar's Back side */

.bar-background {

background-color: rgba(160, 160, 160, .1);

}

/* Bar's Bottom side */

.bar-background:before {

background-color: rgba(160, 160, 160, .2);

}

/* Bar's Left Back side */

.bar-background:after {

background-color: rgba(160, 160, 160, .05);

}

/* Bar's Front side */

.bar-foreground {

background-color: rgba(160, 160, 160, .1);

}

/* Bar's inner block */

.bar-inner,

.bar-inner:before { background-color: rgba(5, 62, 123, .6); }

.bar-inner:after { background-color: rgba(47, 83, 122, .7); }

/*************************************

* Bars Fill *

* Just an example of filling 3 bars *

*************************************/

.graph-container > li:nth-child(1) .bar-inner { height: 25%; bottom: 0; }

.graph-container > li:nth-child(2) .bar-inner { height: 50%; bottom: 0; }

.graph-container > li:nth-child(3) .bar-inner { height: 75%; bottom: 0; }

在本教程提供的演示中,您不会找到这个部分,因为我在这里做了一些更有趣的事情 - 我使用单选按钮让您在不修改代码的情况下使用变量。随意查看它的源代码。但是,如果您只需要自定义静态图形,请从上方获取代码片段,然后根据您的偏好进行自定义。

结论

让我们来看看本教程中介绍的一些精选的CSS规范/技巧。所以,我们已经使用了

transform:skew()和transform:rotate()为了转换我们的元素,使它们一起产生一个3D对象的错觉

:之前和之后:伪类生成与CSS的元素,并保持我们的HTML标记相对干净

:nth-last-child()和:不是用于定位特定列表项的伪类,并避免向标记中添加额外的类/ ID

线性渐变连同background-position一起部分填充背景元素

rgba()用于alpha透明度的颜色

边界来创建像三角形的形状