This is the fifth day of my participation in the Novembermore Challenge.The final text challenge in 2021

introduce

This issue will explain to you how to use SVG to develop a circular vue2 component. The common rectangular progress bar can be easily realized by div+ CSS, while the circular progress bar is a bit troublesome. Of course, it can also be realized by div+ CSS through background attribute or clip attribute and CSS3 variable. But it’s too complex and cumbersome to implement and control, so for best results we’ll use SVG instead.

Let’s take a look at the final effect of kangkang:

The advantage of developing your own components is that you can expand the size, color, thickness, animation, etc. Ready to start

The body of the

1. Participate in the calculation

<script> export default { name: "CircleProgress", data() { return { now: 0 }; }, props: {// Props: value: {type: [String, Number], default: 0}, // Size: {type: [String, Number], default: StrokeWidth :{type: [String, Number], default: 10}, // Progress bar color: {type: String, default: 10} "Rgba (153,202,251,1)"}, // animation execution time duration:{type: [String, Number], default: 1000}}, computed: { percentage() { return this.value; }, countDown() { return this.now; }, // cx() {return this.size / 2; }, // cy() {return this.size / 2; }, // radius() {return (this.size - this.strokewidth) / 2; }, // circumference() {return 2 * math.pi * this.radius; }, // progress length progress() {return (1 - this.now / 100) * this.circumference; }}}; </script>Copy the code

We can set the size, border thickness, progress bar color, and how long it takes to animate the progress value from 0. As for calculating attributes, we will use annotations to make it easy to see the purpose when drawing SVG later.

2. Structure and style

<template> <div class="circle-main"> <div class="circle-main-box" :style="[{ 'width': size+'px','height': size+'px'}]"> <svg :width="size" :height="size" class="circle"> <circle :r="radius" :cx="cx" :cy="cy" fill="transparent"  stroke="#EEEEEE" :stroke-width="strokeWidth" /> <circle :r="radius" :cx="cx" :cy="cy" fill="transparent" :stroke="color" :stroke-width="strokeWidth" stroke-linecap="round" :stroke-dasharray="circumference" :stroke-dashoffset="progress" /> </svg> <span class="count-num" :style="[{ 'font-size': size*.3+'px'}]">{{countDown}}%</span> </div> </div> </template>Copy the code

In fact, this is very simple to write two circles in SVG, the first is the gray bottom circle, the second is our progress bar, set the size of the center radius border color, and we want to change the fill color to the same name, the remaining two items strope-dasharray and strope-dashoffset, I believe everyone will guess that the core of the SVG progress bar change is these two attributes, which are the circumference of the ring and the length of the current progress respectively. We use the current progress value to calculate the percentage of the current length, to achieve the change of the circular progress bar, that is so simple.

Then we have to write a bit of CSS, and we have to, because the SVG circle does not start at what we thought was 0 degrees, but is offset by 90 degrees.

So we’re going to use CSS and turn it another 90 degrees!

.circle {
  transform: rotate(-90deg);
}
Copy the code

Then we write the text and some styles for the main box.

.circle-main-box {
  position: relative;
  display: block;
  margin: 0 auto;
}
.count-num {
  width: 100px;
  height: 100px;
  position: absolute;
  left: 50%;
  top: 50%;
  margin-left: -50px;
  margin-top: -50px;
  align-items: center;
  justify-content: center;
  display: flex;
  font-family: fantasy;
  font-size: 30px;
  color: # 333;
  user-select: none;
}
Copy the code

Now we have a static circular progress bar.

3. Animation and use

<script> export default { name: "CircleProgress", // ... mounted() { this.run(); }, methods: { run() { if (this.value == 0) return; let t = this.duration / this.value this.timer = setInterval(() => { if (this.now >= this.value) { return clearInterval(this.timer); } this.now++; }, t); }}};Copy the code

We will calculate the time of each quantity +1 execution using the current animation execution time and the current value, and then execute through setInterval until the progress value is reached. Finally, we are ready to use this component

<div id="app">
    <CircleProgress :value="60" :size="150" :color="'#d36'"  :duration="3000" />
</div>
Copy the code

conclusion

You learn to waste it, do similar to the completion of such loader is not a new idea, with the round as the foundation, but also afraid of other graphics, see more, say more, it is better to try, quick action, everyone refuelling duck ~~