CSS3 realizes the 3D animation effect of histogram

Insert picture description here

The realized histogram should be:

  • Background independence (that is, the histogram and the background do not affect each other)
  • Adaptive (the number of columns will not affect the layout)
  • Scalable (like a vector diagram)
  • Easy to customize (color, size and proportion)

Challenge 1-Pillar with a retractable core 

  • A histogram is a three-dimensional figure composed of 6 faces
  • The kernel of this histogram can be scaled vertically, and there is an option to hide it

Therefore, we need:

  • One div to generate the three faces of the histogram (back, bottom, left)
  • A div to generate the other three faces of the histogram (front, top, right)
  • A div, which generates the three faces of the core cylinder, is similar to the second div above, but its z-index value is smaller
  • A div, as a container, is used to position the above three components, and a solid-color background is implemented in the lower right corner
  • A div, a container with overflow: hidden, is used to hide it when the height of the core cylinder is 0.

There are five divs in total.

We need at least one container for each column (to ensure the position of the first three divs). Since our column core is scalable, we use percentages to manipulate the height of the core, which requires the height of the container to be equal to the bar The height of the Y-axis of the graph.

This looks good, but there is another problem. There should be an option to hide the moving core, which means it should be "below the cylinder" and hidden. You might say that there is a solution-overflow: hidden, yes, but it does not apply to the container here, because its height is shorter than the actual height of the column.

Challenge 2-Axis

The axis should be:

  • It is a three-dimensional coordinate axis, which contains 3 surfaces (background surface, X-axis surface, Y-axis surface)
  • Background independence
  • The number and attributes of adaptive cylinders (width, height, etc.)
  • X-axis and Y-axis text labels on the outside

Therefore, we need:

  • An unordered list
  • There is a span element in each list item of the X-axis label
  • There is a column in each list item
  • The Y-axis label contains an unordered list

achieve 

 Challenge 1-Pillar with a retractable core

<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>

Review the purpose of each element:

  • bar-wrapper-hide .bar-inner when it slides below the bar
  • bar-container-as a reference element for positioning .bar-foreground, .bar-inner, .bar-foreground, and set the background color of the bottom corner
  • bar-background – three sides of the bar graph (back, bottom, left)
  • bar-inner-the most important part-the column core
  • bar-foreground – generate the other three sides of the bar graph (front, top, right)

Set the style of the container: 

/* Bar wrapper容器 - 当内核低于柱体高度时隐藏内核,必需的 */
.bar-wrapper {
  overflow: hidden;
}
/* Bar container容器 - 这家伙是柱形图里真正的家长——子元素都是相对于它定位的。*/
.bar-container {
  position: relative;
  margin-top: 2.5em;
  width: 12.5em;
}
/* 右下角的小块 - 确保内核向下滑动时右下角被“切割” */
.bar-container:before {
  content: "";
  position: absolute;
  z-index: 3;

  bottom: 0;
  right: 0;

  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 the width of .bar-container to 12.5em. This number is the sum of the front and right side widths of the cylinder-in our example, it is 10+2.5=12.5.
We also use the border property to create a triangle and place it in the lower right corner of the .bar-container to ensure that the sides of the kernel can be "cut" when moving vertically. We use: before pseudo-class to generate this element. 

Set .bar-background: 

/* 背面 */
.bar-background {
  width: 10em;
  height: 100%;
  position: absolute;
  top: -2.5em;
  left: 2.5em;
  z-index: 1;
}

.bar-background:before,
.bar-background:after {
  content: "";
  position: absolute;
}

/* 底面 */
.bar-background:before {
  bottom: -2.5em;
  right: 1.25em;
  width: 10em;
  height: 2.5em;
  transform: skew(-45deg);
}

/* 左后面 */
.bar-background:after {
  top: 1.25em;
  right: 10em;
  width: 2.5em;
  height: 100%;

  /* 仅倾斜Y轴 */
  transform: skew(0deg, -45deg);
}

As you can see, we move the .bar-background up and to the right by 2.5em. Of course, we tilted the left back and the bottom 45 degrees. Please note that in the :after pseudo-element, the first tilt value is set to 0deg, and the second is set to -45 degrees, so that only the Y axis of the element is tilted.
Then let's set up .bar-foreground:

/* 前面 */
.bar-foreground {
    z-index: 3; /* 在 .bar-background 和.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;
}

/* 右前面 */
.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);
}

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

Everything is the same as the style of .bar-background, but the direction is different.
Among them, some of the styles are applied to the .bar-foreground and .bar-inner elements at the same time, because they look exactly the same.
Okay, let's continue to set the kernel style. 

.bar-inner {
  z-index: 2; /* 在.bar-background的上面 */
  top: auto; /* 重置 top属性 */
  background-color: rgba(5, 62, 123, .6);
  height: 0;
  bottom: -2.5em;
  color: transparent; /* 隐藏文字 */

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

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

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

The style of the cylinder is set, let's look at the coordinate axis next.

Challenge 2-Axis

<ul class="graph-container">
  <li>
    <span>2011</span>
    <!-- 此处显示柱状图图的HTML标记 -->
  </li>
  <li>
    <span>2012</span>
    <!-- 此处显示柱状图图的HTML标记 -->
  </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>

We use unordered lists and span elements in the project to locate the X-axis and Y-axis labels.

Here is a small point. We use a linear gradient to fill the container background and raise it by 2.5em. Why? Because the height of the bottom end of the coordinate axis (which we will set in the next style) is 2.5em. And the coordinate axis is tilted by 45 degrees, so there is a blank area in the lower right corner.
X-axis style of coordinate axis:

/* X轴 */
.graph-container:before {
  position: absolute;
  content: "";

  bottom: 0;
  left: -1.25em; /* 倾斜会将它向左推,所以我们将它向相反的方向移动一点。*/

  width: 100%; /* 确保它和整个组件一样宽 */

  height: 2.5em;
  background-color: rgba(183, 183, 183, 1);

  transform: skew(-45deg);
}

We tilted it 45 degrees and moved it a little to the left to make sure it was in the correct position.
Y-axis style of the coordinate axis:

/* Y轴 */
.graph-container:after {
  position: absolute;
  content: "";

  top: 1.25em; /* 倾斜会将其向上推,因此我们将其向下移动一点。*/
  left: 0em;

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

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

In the same way, tilt the element 45 degrees, and then push it down a bit to position it correctly.
The basic settings of the coordinate axis are these, then we continue to set the style in the list item:

.graph-container > li {
  float: left; /* 水平排列 */
  position: relative; 
}
.graph-container > li:nth-last-child(2) {
  margin-right: 2.5em;
}
/* X轴的文字标签 */
.graph-container > li > span {
  position: absolute;
  left: 0;
  bottom: -2em;
  width: 80%; 
  text-align: center;

  font-size: 1.5em;
  color: rgba(200, 200, 200, .4);
}

There are two points to note here. First, we use float to arrange the columns horizontally. Under normal circumstances, you should use float very carefully, it will cause layout problems such as height collapse. So, here you can try to set display:inline-block to achieve.
Second, we added some right margins to the last column. This way we can make sure to leave enough space at the bottom of the axis, try to remove it, and you will understand what I mean.
OK, we are almost done. The last thing to do is to add a text mark for the Y axis.

/* 文字标记的容器 */
.graph-container > li:last-child {
  width: 100%;
  position: absolute;
  left: 0;
  bottom: 0;
}

/* Y轴文字标记列表 */
.graph-marker-container > li {
  position: absolute;
  left: -2.5em;
  bottom: 0;
  width: 100%;
  margin-bottom: 2.5em;
  list-style: none;
}

/* Y轴线条常规样式 */
.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轴侧线 */
.graph-marker-container > li:before {
  width: 3.55em;
  height: 0;
  bottom: -1.22em;
  left: -.55em;
  z-index: 2; 
  transform: rotate(-45deg);
}

/* Y轴背景线 */
.graph-marker-container li:after {
  width: 100%;
  bottom: 0;
  left: 2.5em;
}

/* Y轴文本标签 */
.graph-marker-container span {
  color: rgba(200, 200, 200, .4);
  position: absolute;

  top: 1em;
  left: -3.5em; 
  width: 3.5em; 

  font-size: 1.5em;
}

As you can see, we set the width of the text label container to 100% so that the background line can cover the entire axis, use a dashed border to set the style of the Y axis bar and position the span element so that the text label is located outside the axis. Using the :before and :after pseudo-elements can reduce the amount of HTML code and keep the page clean.
At this point, we have completed all the style settings of the histogram, but we are missing some important variables-size, color, and bar fill value! As mentioned above, our charts are customizable, so I decided not to mix variables with other codes so that you can customize them more conveniently.

/****************
 * 尺寸        *
 ****************/
 /* 图表的整体大小 */
.graph-container,
.bar-container {
  font-size: 8px;
}
/* 柱体的高度 */
.bar-container,
.graph-container:after,
.graph-container > li:last-child {
  height: 40em;
}

/****************
 * 间距      *
 ****************/
/* 柱体的间距 */
.graph-container > li .bar-container {
  margin-right: 1.5em;
}
/* 第一个柱体的左边距 */
.graph-container > li:first-child {
  margin-left: 1.5em;
}
/* 最后一个柱体的右边距 */
.graph-container > li:nth-last-child(2) .bar-container {
  margin-right: 1.5em;
}

/****************
 *    颜色    *
 ****************/
/* 柱体的背面颜色 */
.bar-background {
  background-color: rgba(160, 160, 160, .1);
}
/* 柱体的底面颜色 */
.bar-background:before {
  background-color: rgba(160, 160, 160, .2);
}
/* 柱体的左后面颜色 */
.bar-background:after {
  background-color: rgba(160, 160, 160, .05);
}
/* 柱体的正面颜色 */
.bar-foreground {
  background-color: rgba(160, 160, 160, .1);
}
/* 内核的颜色 */
.bar-inner,
.bar-inner:before { background-color: rgba(5, 62, 123, .6); }
.bar-inner:after { background-color: rgba(47, 83, 122, .7); }

/*************************************
 *   内核的高度                      *
 *************************************/
.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; }

to sum up

Source code download address: https://download.csdn.net/download/yuan_jlj/13696000
Original: https://mp.weixin.qq.com/s/dy8SFN_Rb48z4vluYIgVMw
Let us review some of the CSS specifications/techniques introduced in the article.

  • transform:skew() and transform:rotate() are used to tilt and rotate the element, and they combine to make the element simulation produce a three-dimensional effect.
  • :before and :after pseudo-elements can keep HTML markup relatively clean
  • :nth-last-child() and :not are pseudo-classes for specific list items, which can avoid adding extra classes/id to HTML.
  • Linear-gradient and background-position can be used together to achieve partial filling of the background
  • rgba() can achieve color with transparency
  • The border property can create a triangular shape

 

Guess you like

Origin blog.csdn.net/yuan_jlj/article/details/111225794
Recommended