3d翻转动画css3_带有CSS3的动画3D条形图

本文详细介绍了如何使用CSS3创建一个3D动态条形图,包括实现可移动的内块、自适应布局和可扩展性。通过使用transform: skew()和transform: rotate()创建3D效果,利用:before和:after伪类生成元素,以及使用nth-last-child()选择器定位特定列表项。此外,还讨论了如何通过调整颜色、尺寸和比例来定制图表。
摘要由CSDN通过智能技术生成
3d翻转动画css3

3d翻转动画css3

Animated 3D Bar Chart with CSS3

It all began with a small experiment that was inspired by a tutorial from Nettuts+ which shows a way how to embed a 3D bar chart into HTML pages using CSS, images and JavaScript. After reading the tutorial I challenged myself to turn this idea into pure CSS and see how far I can take it. The initial challenge was to create a classic semi-transparent 3D box with 6 sides. The final challenge was to create a complete 3D bar chart which we will create in this tutorial.

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

You can check out what I have done before here.

您可以在这里查看我的工作。

Please note: the result of this tutorial will only work as intended in browsers that support the respective CSS properties. 请注意:本教程的结果只能在支持各自CSS属性的浏览器中按预期工作。

Let’s write down some key requirements. The chart should be

让我们写下一些关键要求。 图表应为

  • background-independent

    与背景无关
  • adaptive (independent of the number of bars)

    自适应的(与柱数无关)
  • scalable (just like vector graphics)

    可扩展的(就像矢量图形一样)
  • easily customizable (colors, sizes and proportions)

    易于定制(颜色,大小和比例)

The planning phase is the most important part of any project. So let’s make a plan.

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

Before actually coding, I usually write down all potential challenges with solutions I can think of in a specific project and repeat this process until I get something that looks like a strategy that can be executed. Here is the list of challenges with solutions I came up with for this project:

在进行实际编码之前,我通常会写下我可以在特定项目中想到的解决方案的所有潜在挑战,然后重复此过程,直到获得看起来像可以执行的策略为止。 以下是我为此项目提出的解决方案所面临的挑战:

挑战1 –带有可移动内块的杠 (Challenge #1 – A bar with movable inner block)

What we know:

我们所知道的:

  • A bar should be represented as 3D box consisting of 6 sides

    条形图应表示为由6个面组成的3D框
  • Inner block should be vertically movable in motion. There should be an option to hide the block.

    内块应可垂直移动。 应该有一个隐藏块的选项。

What we’ll need:

我们需要的是:

  • 1 div for back casing consisting of 3 sides (back side, bottom side, left side)

    1格,用于后壳,由3个侧面(背面,底面,左侧)组成
  • 1 div for front casing consisting of 3 sides (front side, top side, right side)

    1格,用于前壳体,由3个侧面(正面,顶面,右侧)组成
  • 1 div for inner block consisting of 3 sides exactly as Front casing but with lower z-index

    1格用于内块,由与前壳体完全相同的3个侧面组成,但Z指数较低
  • 1 div container to position all three pieces relatively and apply a solid background patch in the bottom right corner

    1 div容器,将所有三个块相对放置,并在右下角应用纯色背景补丁
  • 1 div container with overflow: hidden to hide the inner block under the bar when it goes down to zero

    1个带溢出的div容器:隐藏以将其降至零时隐藏在栏下方的内部块

That makes a total of 5 divs.

总共5格。

You may wonder why would we need two containers? Well, it may be a tricky part but I will try to explain. We need at least one container per bar (to hold front casing, back casing and inner block relatively to it). We know that our bar should be scalable, so we use percentages to manipulate the bar’s fill value, which requires our container’s height to be equal to the height of one of the bar’s sides.

您可能想知道为什么我们需要两个容器? 好吧,这可能是一个棘手的部分,但我会尽力解释。 每个杆至少需要一个容器(用于相对于前壳体,后壳体和内部块体进行固定)。 我们知道钢筋应该是可伸缩的,因此我们使用百分比来操纵钢筋的填充值,这要求容器的高度等于钢筋一侧的高度。

Seems fine, but wait, looks like there is another problem – there should be an option to hide the inner block in motion, which means it should go “below the bar” and be hidden there. You may say we have a solution for that – overflow: hidden, right? Yes, but not for that container as its height is shorter than the actual height of the bar. That is why we add another container over it and apply overflow: hidden to it. Hope this makes sense. Let’s move on.

看起来不错,但请稍等,似乎还有另一个问题–应该有一个选项可以隐藏运动中的内部块,这意味着它应该“位于栏下方”并隐藏在其中。 您可能会说我们有解决方案–溢出:隐藏,对不对? 是的,但不适用于该容器,因为其高度比钢筋的实际高度短。 这就是为什么我们在其上添加另一个容器并对其应用溢出:隐藏的原因。 希望这是有道理的。 让我们继续前进。

挑战2 –图形持有人 (Challenge #2 – The Graph Holder)

The graph holder should

图持有人应

  • be represented in 3D with axes and with 3 sides (background, bottom, left)

    用3D轴和3面(背景,底部,左侧)表示
  • be background-independent

    与背景无关
  • be adaptive to the number of bars and their attributes (height, width etc.)

    适应条的数量及其属性(高度,宽度等)
  • have X and Y axis labels from outside

    从外面有X和Y轴标签

What we’ll need:

我们需要的是:

  • 1 unordered list

    1个无序列表
  • 1 element inside each list item for the X axis labels

    X轴标签的每个列表项内有1个元素
  • 1 bar inside each list item

    每个列表项内有1条
  • 1 list item with an unordered list inside it for the Y axis labels

    1个列表项,其中的Y轴标签中包含无序列表

Hmm, unordered list? Isn’t it more semantic to use a definition list for a bar chart? Well, it is probably more semantic, but we can’t use it because we have to wrap every bar and its own X axis label in one container in order to position them relatively.

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

All right, but why wouldn’t we use a list item instead of the bar’s second container then? Well, we can’t do that because we have to place the X axis labels outside the graph and since we know that the bar’s second container hides any content that overflows it, we will use list items just to make sure all elements are positioned properly.

好的,但是为什么我们不使用列表项而不是栏的第二个容器呢? 好吧,我们不能这样做,因为我们必须将X轴标签放置在图形之外,并且由于我们知道条形图的第二个容器隐藏了溢出它的所有内容,因此我们将使用列表项来确保所有元素都正确放置。

实施 (The Implementation)

Now that we have a strategy, let’s convert it into code.

现在我们有了一个策略,让我们将其转换为代码。

Please note that no vendor prefixes will be used in this tutorial. You can, of course, find them in the CSS files of the demo.

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

挑战1 –带有可移动内块的杠 (Challenge #1 – A bar with movable inner block)
<div class="bar-wrapper">
  <div class="bar-container">
    <div class="bar-background"></div>
    <div class="bar-inner">50</div>
    <div class="bar-foreground"></div>
  </div>
</div>

Let’s go over the purpose of each element once again:

让我们再次遍历每个元素的目的:

  • bar-wrapper – hides .bar-inner when it slides down below the bar

    bar- wrapper-当它向下滑动到栏下方时,隐藏.bar-inner

  • bar-container – positions .bar-foreground, .bar-inner, .bar-foreground relatively and places patch for background in a bottom corner

    bar容器–相对放置.bar-foreground,.bar-inner,.bar-foreground并在底角放置背景色块

  • bar-background – creates 3 sides of casing: back, bottom, left

    条形背景–创建外壳的3面:背面,底部,左侧

  • bar-inner – the most important part probably – inner block

    吧台内部–最重要的部分–内部块

  • bar-foreground – creates 3 sides of casing: front, top, right

    bar-foreground –创建套管的3个侧面:正面,顶部,右侧

First, let’s style the containers.

首先,让我们对容器进行样式设置。


/* 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);
}

Note that we set .bar-container‘s width to 12.5em. This number is a sum of the bar’s front and right sides widths – in our example it’s 10 + 2.5 = 12.5

请注意,我们将.bar-container的宽度设置为12.5em。 此数字是钢筋的前后宽度的总和–在我们的示例中为10 + 2.5 = 12.5

We also use borders to shape the triangle and place it in the bottom right corner of .bar-container to make sure the inner bar’s side is “cut” when it moves vertically. We use the :before pseudo class to generate this element; we will use :before and :after pseudo classes a lot in this tutorial.

我们还使用边框来塑造三角形的形状,并将其放置在.bar容器的右下角,以确保当垂直移动时,内部钢筋的一侧被“切掉”。 我们使用:before伪类生成此元素; 在本教程中,我们将大量使用:before和:after伪类。

Now let’s style the back casing:

现在让我们设计后壳的样式:


/* 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);
}

As you can see we move the casing 2.5em up and right. And sure enough, we skew the left and bottom sides 45 degrees. Notice that we set the first skew value to 0deg, and the second one to -45deg which allows us to skew this element vertically.

如您所见,我们将外壳向上和向右移动2.5em。 确实,我们将左右两侧倾斜了45度。 请注意,我们将第一个偏斜值设置为0deg,第二个偏斜值设置为-45deg,这使我们可以垂直偏斜此元素。

It’s time to style the front casing.

是时候对前机壳进行样式了。


/* 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);
}

Nothing new here, everything is the same as in the back casing styles, we just use different directions. The good part is that we applied those styles to both front casing and the inner block. Why not? They are exactly the same thing in terms of their shape.

这里没有新内容,所有内容与后壳样式相同,只是使用了不同的方向。 好消息是我们将这些样式应用于前壳体和内块。 为什么不? 就形状而言,它们是完全相同的东西。

All right, and now the styles for the inner block that we have not yet applied.

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


.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);
}

Great! The bars are all set. Let’s move on to the graph holder.

大! 条已全部设置。 让我们继续图持有人。

挑战2 –图形持有人(带有轴标签) (Challenge #2 – The Graph Holder (with axis labels))
<ul class="graph-container">
  <li>
    <span>2011</span>
    <-- HTML markup of a bar goes here -->
  </li>
  <li>
    <span>2012</span>
    <-- HTML markup of a bar goes here -->
  </li>
  <li>
    <ul class="graph-marker-container">
      <li><span>25%</span></li>
      <li><span>50%</span></li>
      <li><span>75%</span></li>
      <li><span>100%</span></li>
    </ul>
  </li>
</ul>

As you can see we use an unordered list and span elements inside the items to position the X- and Y- axis labels.

如您所见,我们在项目内部使用了无序列表并跨越了元素来放置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 <ul> 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;
}

The tricky part here is the background. We use a linear gradient to fill the graph container and lift it up by 2.5em. Why? Because our graph holder’s bottom side (which we will style next) is 2.5em high and is skewed by 45 degrees so there is an empty space in the right bottom corner.

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

Let’s style the bottom side now.

现在让我们对底部进行样式设置。


/* 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);
}

We skew it by 45 degrees and move it a bit to the left just to make sure it is positioned properly.

我们将其倾斜45度,然后将其向左移动一点,以确保其正确定位。

Now let’s style left the side of our graph holder:

现在,让我们在图形持有人的一侧添加样式:

/* 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);
}

Nothing special here. Just skewed the element by 45 degrees as usual and pushed it down a bit in order to position it properly.

这里没什么特别的。 只需像往常一样将元素倾斜45度,然后将其向下推一点以正确定位。

We’re done with the graph holder. Now let’s add some magic to the list items that hold our bars:

我们已经完成了图形持有人。 现在,让我们为保存栏的列表项添加一些魔术:

/* 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);
}

A few things happened here. First of all, we float our bars next to each other. Usually, I’m trying to be very careful with using floats, but in this case it fits perfectly in my opinion.

这里发生了几件事。 首先,我们将酒吧彼此浮动。 通常,我在使用浮点数时要非常小心,但是在这种情况下,它非常适合我的观点。

Secondly, we add some right margin to the last bar. That way we make sure we give enough space to the graph holder’s bottom side to show up in the right bottom corner. Try to remove it and you will see what I mean.

其次,我们在最后一个小节上添加一些右边距。 这样,我们可以确保为图形持有者的底部留出足够的空间以显示在右下角。 尝试将其删除,您将明白我的意思。

OK, we’re almost there. The last thing left is to add Y-axis markers..

好,我们快到了。 最后剩下的就是添加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;
}

As you can see, we set 100% width to our markers holder in order to be able to draw throughout the whole graph, use a dotted border to style our Y-axis lines and position the span element so that the Y-axis label is outside of the graph. With the help of :before and :after we could keep our HTML pretty clean.

如您所见,我们为标记持有人设置了100%的宽度,以便能够绘制整个图形,使用虚线边框为Y轴线设置样式,并定位span元素,以使Y轴标签在图表之外。 在:before和:after的帮助下,我们可以使我们HTML保持整洁。

Well, we finished setting up all the styles for our graph, however we didn’t set some vital variables – sizes, colors and bars fill values! We said that our graph will be customizable, right? So, I decided not to mix variables with the rest of the code so that you can play with them..

好了,我们完成了图形的所有样式设置,但是我们没有设置一些重要的变量-大小,颜色和条形填充值! 我们说过我们的图形将是可定制的,对吧? 因此,我决定不将变量与其余代码混合使用,以便您可以使用它们。


/****************
 * 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; }

In the demo provided with this tutorial you will not find this part as it is here, because I did something even more interesting there – I used radio buttons to let you play with the variables without modifying the code. Feel free to check out its source code. But if you just need to customize a static graph grab the code snippet from above and customize it to your preference.

在本教程提供的演示中,您将无法找到本部分的内容,因为在那儿我做了一些更有趣的事情–我使用单选按钮让您无需修改​​代码即可使用变量。 随时检查其源代码。 但是,如果您只需要自定义静态图形,请从上方抓取代码段,然后根据自己的喜好对其进行自定义。

结论 (Conclusion)

Let’s go over some featured CSS specifications/techniques we covered in this tutorial. So, we’ve used

让我们看一下本教程中介绍的一些特色CSS规范/技术。 因此,我们已经使用

  • transform: skew() and transform: rotate() in order to transform our elements so that together they generate an illusion of a 3D object

    transform:skew()transform:rotation()以便变换我们的元素,以便它们一起产生3D对象的错觉

  • :before and :after pseudo classes to generate elements with CSS and keep our HTML markup relatively clean

    :before:after伪类以使用CSS生成元素并保持我们HTML标记相对干净

  • :nth-last-child() and :not pseudo classes to target specific list items and avoid adding extra classes/ids to the markup

    :nth-​​last-child():not伪类,以特定列表项为目标,并避免向标记添加额外的类/ id

  • linear-gradient together with background-position to partially fill an element with a background

    线性渐变以及背景位置,以部分填充背景

  • rgba() for colors with alpha-transparency

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

  • borders to create shapes like a triangle

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

I really hope that this tutorial was useful to you. If you have any questions regarding this tutorial, let me know in the comments below.

我真的希望本教程对您有用。 如果您对本教程有任何疑问,请在下面的评论中告诉我。

翻译自: https://tympanus.net/codrops/2012/05/21/animated-3d-bar-chart-with-css3/

3d翻转动画css3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值