A Simple Attempt to Realize Gradient Dashboard with CSS

In the chapter " CSS Conical Gradient Realizes Circular Progress Bar ", some ideas for realizing the gradient progress bar are explained. Based on this idea, this chapter tries to use CSS to implement a simple gradient dashboard to provide you with some references. To realize the angular gradient, I have to mention the conic-gradient attribute, which is the key to realizing the angular gradient; secondly, in the development of data visualization, the data is displayed in the form of a chart, which is inseparable from the data processing, and the corresponding It is also an important task of visualization development to map the index data of the data to the chart. In addition, the display forms of the graphics are various, and the high degree of restoration of the designer's design draft requires us to have a certain spatial imagination for the graphics. As the saying goes, "all roads lead to Rome". For graphic design, there are various implementation methods. As long as the expected effect can be achieved, it is worth learning. The effect of this chapter is shown in the figure

 To realize the function of this case, the difficulty lies in drawing the scale line of the dial and the positioning of the digital scale. Here, the relevant knowledge points in transform in CSS are cleverly used to solve the positioning problem based on rotation. The gradient area of ​​the dial is calculated based on conic-gradient data. As shown, the dial pointer is also rotated based on transform, and a quarter of the blank area below is clipped by the clip-path attribute in CSS. It is said that the code is the best explanation of the principle, here combined with vue, simply encapsulate a component, and paste the specific implementation logic

<template>
  <div class="dash-box" :style="styObj">
    <!-- 外边框 -->
    <div class="outer-border">
      <div class="inner-wrapper">
        <!-- 内边框 -->
        <div class="inner-border">
          <!-- 中间边框 -->
          <div class="center-box"></div>
        </div>
      </div>
    </div>
    <!-- 中间白圆点 -->
    <div class="center-dot"></div>
    <!-- 中间指针 -->
    <div class="center-pointer-wrapper">
      <div class="center-pointer"></div>
    </div>
    <!-- 刻度线及刻度数字 -->
    <div class="line-tick line-tick1">
      <div class="tick"></div>
      <div class="num">0</div>
    </div>
    <div class="line-tick line-tick2">
      <div class="tick"></div>
      <div class="num">20</div>
    </div>
    <div class="line-tick line-tick3">
      <div class="tick"></div>
      <div class="num">40</div>
    </div>
    <div class="line-tick line-tick4">
      <div class="tick"></div>
      <div class="num">60</div>
    </div>
    <div class="line-tick line-tick5">
      <div class="tick"></div>
      <div class="num">80</div>
    </div>
    <div class="line-tick line-tick6">
      <div class="tick"></div>
      <div class="num">100</div>
    </div>
    <div class="slot-content">
      <slot></slot>
    </div>
  </div>
</template>
<script>
export default {
  name: "DashBoardDemo",
  props: {
    rate: {
      default: 0,
    },
  },
  computed: {
    styObj() {
      let rotateDeg = "";
      let conicDeg = "";
      if (this.rate <= 0) {
        rotateDeg = "rotate(0deg)";
        conicDeg = "0%";
      } else if (this.rate > 100) {
        rotateDeg = "rotate(270deg)";
        conicDeg = "0%";
      } else {
        rotateDeg = `rotate(${(this.rate / 100) * 270}deg)`;
        conicDeg = `${(this.rate / 100) * (270 / 360) * 100}%`;
      }
      return {
        "--pointer-rotate": rotateDeg,
        "--background-wrapper": `conic-gradient(#1c9df8 0%, #1c9df8 ${conicDeg}, transparent ${conicDeg})`,
        "--background-inner": `conic-gradient(#073358 0%, #12a2ff ${conicDeg}, transparent ${conicDeg})`,
      };
    },
  },
};
</script>
<style scoped>
.dash-box {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
.outer-border {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 80%;
  height: 80%;
  border-radius: 50%;
  border: 2px solid #178be2;
  clip-path: polygon(50% 50%, 0 100%, 0 0, 100% 0, 100% 100%);
}
.inner-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 90%;
  height: 90%;
  border-radius: 50%;
  background-image: var(--background-wrapper);
  transform: rotate(-135deg);
}
.inner-border {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 90%;
  height: 90%;
  border-radius: 50%;
  background-image: var(--background-inner);
}

.center-box {
  position: relative;
  width: 35%;
  height: 35%;
  background: #091629;
  border-radius: 50%;
}
.center-box::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 80%;
  height: 80%;
  border: 2px solid #188ff3;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}
.center-dot {
  position: absolute;
  width: 16px;
  height: 16px;
  left: 50%;
  top: 50%;
  background: #fff;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}
.center-pointer-wrapper {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 60%;
  height: 4px;
  transform: translate(-50%, -50%) rotate(-45deg);
}
.center-pointer {
  width: 50%;
  height: 100%;
  background: #fff;
  clip-path: polygon(0% 50%, 100% 0%, 100% 100%);
  transform-origin: right center;
  transform: var(--pointer-rotate);
}
.line-tick {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 80%;
  height: 2px;
}
.tick {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 8px;
  background: #5b6376;
}
.num {
  position: absolute;
  width: 30px;
  left: -32px;
  top: 50%;
  text-align: center;
  transform: translateY(-50%);
  color: #073a6f;
  font-size: 18px;
}
.line-tick1 {
  transform: translate(-50%, -50%) rotate(-45deg);
}
.line-tick2 {
  transform: translate(-50%, -50%) rotate(9deg);
}
.line-tick3 {
  transform: translate(-50%, -50%) rotate(63deg);
}
.line-tick4 {
  transform: translate(-50%, -50%) rotate(117deg);
}
.line-tick5 {
  transform: translate(-50%, -50%) rotate(171deg);
}
.line-tick6 {
  transform: translate(-50%, -50%) rotate(225deg);
}
.line-tick1 .num {
  transform: translateY(-50%) rotate(45deg);
}
.line-tick2 .num {
  transform: translateY(-50%) rotate(-10deg);
}
.line-tick3 .num {
  transform: translateY(-50%) rotate(-64deg);
}
.line-tick4 .num {
  transform: translateY(-50%) rotate(-115deg);
}
.line-tick5 .num {
  transform: translateY(-50%) rotate(-171deg);
}
.line-tick6 .num {
  transform: translateY(-50%) rotate(134deg);
}
.slot-content {
  position: absolute;
  bottom: 10%;
  left: 50%;
  transform: translateX(-50%);
}
</style>

For related implementation methods, you can refer to the source code. I will not explain it in depth here. I will post the reference logic of the component.

<template>
  <div class="container">
    <div class="module-box">
      <demo :rate="rate">
        <span class="slot-text">{
   
   { `${rate}%` }}</span>
      </demo>
    </div>
    <div class="module-box">
      <demo :rate="92.66">
        <span class="slot-text">{
   
   { `${92.66}%` }}</span>
      </demo>
    </div>
  </div>
</template>
<script>
import Demo from "./demo.vue";
export default {
  name: "DashBoard",
  components: {
    Demo,
  },
  data() {
    return {
      rate: 85.56,
    };
  },
};
</script>
<style scoped>
.container {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  height: 100%;
  background: #091629;
}
.module-box {
  width: 320px;
  height: 320px;
}
.slot-text {
  color: #fff;
  font-size: 24px;
  font-weight: bold;
}
</style>

In short, using CSS to implement a gradient dashboard is not complicated. In fact, it is a comprehensive application of commonly used CSS properties. For students who are solid in CSS, more complex and diverse charts can be realized. It has to be mentioned here that if a large number of dom nodes are used in the implementation of the chart, it will inevitably affect the rendering speed of the page and the smoothness of page operation. Therefore, you can use different techniques according to the actual situation. selection.

Guess you like

Origin blog.csdn.net/qq_40289557/article/details/128089457