Canvas Draws Dynamic Progress Bar Ring

Time:2019-8-24

Final effect

Canvas Draws Dynamic Progress Bar Ring

Definition of initial variables

Let radius = 140 // outer ring radius
Let thickness = 20 // ring thickness
Let innerRadius = radius - thickness // inner ring radius
Let start Angle = 90 // start angle
Let endAngle = 180// End Angle
Let x = 0 // center x coordinates
Let y = 0 // center y coordinates
let canvas = document.getElementById('tutorial');
canvas.width = 300;
canvas.height = 300;

let ctx = canvas.getContext('2d');
Ctx.translate (canvas.width/2, canvas.height/2); //Move the drawing origin to the center of the canvas
Ctx. rotate (angle2Radian (225)// Rotate the canvas 225 degrees
Ctx.fillStyle = " f2d7d7";//Initial fill color

II. Tool Approach

// Calculating the coordinates of points on a ring
function calcRingPoint(x, y, radius, angle) {
    let res = {}
    res.x = x + radius * Math.cos(angle * Math.PI / 180)
    res.y = y + radius * Math.sin(angle * Math.PI / 180)
    return res
}

// radian rotation angle
function radian2Angle(radian) {
    return 180 * radian / Math.PI
}

// angular radian
function angle2Radian(angle) {
    return angle * Math.PI / 180
}

3. Rendering methods

// Rendering function
function renderRing(startAngle, endAngle) {
     ctx.beginPath();

    // Drawing Outer Ring
    ctx.arc(x, y, radius, angle2Radian(startAngle), angle2Radian(endAngle))

    // Calculate the central coordinates of the first connection between the outer ring and the inner ring
    let oneCtrlPoint = calcRingPoint(x, y, innerRadius + thickness / 2, endAngle)

    // Drawing Outer Ring与内环第一个连接处的圆环
    ctx.arc(oneCtrlPoint.x, oneCtrlPoint.y, thickness / 2, angle2Radian(-90), angle2Radian(270))

    // Drawing inner rings
    ctx.arc(x, y, innerRadius, angle2Radian(endAngle), angle2Radian(startAngle), true)

    // Calculate the central coordinates of the second connection between the outer ring and the inner ring
    let twoCtrlPoint = calcRingPoint(x, y, innerRadius + thickness / 2, startAngle)

    // Drawing Outer Ring与内环第二个连接处的圆环
    ctx.arc(twoCtrlPoint.x, twoCtrlPoint.y, thickness / 2, angle2Radian(-90), angle2Radian(270))

    ctx.fill()
    // ctx.stroke()
}

Specific ideas:

For convenience, all places where radians are used in code change from angles to radians.

1. Draw the outer ring:

Canvas Draws Dynamic Progress Bar Ring

This step is the simplest and can be used directly according to the official usage method.

2. Draw the first ring at the junction of the outer ring and the inner ring.

Canvas Draws Dynamic Progress Bar Ring

First, the coordinates of the middle point at the end of the outer ring and the beginning of the inner ring are calculated.

Canvas Draws Dynamic Progress Bar Ring

The coordinate formulas for calculating points on a ring are as follows:

x = x + radius Math.cos(angle Math.PI / 180)
y = y + radius Math.sin(angle Math.PI / 180)

By substituting the above formulas, the coordinates of any point on the ring can be calculated, and then the ring can be drawn with the center of the ring and the thickness of the ring/2 as the radius.

3. Drawing inner rings

Canvas Draws Dynamic Progress Bar Ring

This step only needs to shorten the radius and change the starting and ending angles of the drawing outer ring.

4. Draw the second ring at the junction of the inner ring and the outer ring.

Canvas Draws Dynamic Progress Bar Ring

In the same way as the second step, the coordinates of the middle point at the beginning of the outer ring and the end of the inner ring are calculated, and then the circle is drawn with the center of the circle and the thickness of the circle/2 as the radius.

5. Complete filling
At this point, the circle is finished.

IV. Dynamic Progress Bar

// Progress Bar Animation
ctx.fillStyle = "#e87c7c";
let tempAngle = startAngle
let twoEndAngle = 0
let step = (twoEndAngle - startAngle) / 100
let numberSpan = document.querySelector('.number')
let count = 0
let inter = setInterval(() => {
    if (tempAngle > twoEndAngle) {
        clearInterval(inter)
    } else {
        count++
        numberSpan.innerText = count
        tempAngle += step
    }
    renderRing(startAngle, tempAngle)
}, 16.7)

The end angle is calculated dynamically, and then a counter is set to repeat the rendering method.

V. Complete Code

<!DOCTYPE html>
<html lang="cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>canvas</title>
    <style>
        .ring {
            width: 300px;
            height: 300px;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            position: relative;
        }

        .fraction {
            position: absolute;
            font-size: 30px;
            font-weight: bold;
            color: red;
        }

        .small {
            font-size: 12px;
            font-weight: lighter;
        }

        .title {
            font-size: 20px;
            color: red;
            bottom: 40px;
            position: absolute;
        }
    </style>
</head>

<body>
    <div class="ring">
        <canvas id="tutorial"></canvas>
        <span class="fraction">span class="number">0</span> <span class="small">score</span></span>
        <span class="title">service score</span>
    </div>

    <script>
        Let radius = 140 // outer ring radius
        Let thickness = 20 // ring thickness
        Let innerRadius = radius - thickness // inner ring radius
        Let start Angle = 90 // start angle
        Let endAngle = 180// End Angle
        Let x = 0 // center x coordinates
        Let y = 0 // center y coordinates
        let canvas = document.getElementById('tutorial');
        canvas.width = 300;
        canvas.height = 300;

        let ctx = canvas.getContext('2d');
        Ctx.translate (canvas.width/2, canvas.height/2); //Move the drawing origin to the center of the canvas
        Ctx. rotate (angle2Radian (225)// Rotate the canvas 225 degrees
        Ctx.fillStyle = " f2d7d7";//Initial fill color

        renderRing(startAngle, endAngle)

        // Progress Bar Animation
        ctx.fillStyle = "#e87c7c";
        let tempAngle = startAngle
        let twoEndAngle = 0
        let step = (twoEndAngle - startAngle) / 100
        let numberSpan = document.querySelector('.number')
        let count = 0
        let inter = setInterval(() => {
            if (tempAngle > twoEndAngle) {
                clearInterval(inter)
            } else {
                count++
                numberSpan.innerText = count
                tempAngle += step
            }
            renderRing(startAngle, tempAngle)
        }, 16.7)


        // Rendering function
        function renderRing(startAngle, endAngle) {
            ctx.beginPath();

            // Drawing Outer Ring
            ctx.arc(x, y, radius, angle2Radian(startAngle), angle2Radian(endAngle))

            // Calculate the central coordinates of the first connection between the outer ring and the inner ring
            let oneCtrlPoint = calcRingPoint(x, y, innerRadius + thickness / 2, endAngle)

            // Drawing Outer Ring与内环第一个连接处的圆环
            ctx.arc(oneCtrlPoint.x, oneCtrlPoint.y, thickness / 2, angle2Radian(-90), angle2Radian(270))

            //// Drawing inner rings
            ctx.arc(x, y, innerRadius, angle2Radian(endAngle), angle2Radian(startAngle), true)

            // Calculate the central coordinates of the second connection between the outer ring and the inner ring
            let twoCtrlPoint = calcRingPoint(x, y, innerRadius + thickness / 2, startAngle)

            // Drawing Outer Ring与内环第二个连接处的圆环
            ctx.arc(twoCtrlPoint.x, twoCtrlPoint.y, thickness / 2, angle2Radian(-90), angle2Radian(270))

            ctx.fill()
            // ctx.stroke()
        }

        // Calculating the coordinates of points on a ring
        function calcRingPoint(x, y, radius, angle) {
            let res = {}
            res.x = x + radius * Math.cos(angle * Math.PI / 180)
            res.y = y + radius * Math.sin(angle * Math.PI / 180)
            return res
        }

        // radian rotation angle
        function radian2Angle(radian) {
            return 180 * radian / Math.PI
        }

        // angular radian
        function angle2Radian(angle) {
            return angle * Math.PI / 180
        }
    </script>
</body>

</html>

Recommended Today

Hadoop MapReduce Spark Configuration Item

Scope of application The configuration items covered in this article are mainly for Hadoop 2.x and Spark 2.x. MapReduce Official documents https://hadoop.apache.org/doc…Lower left corner: mapred-default.xml Examples of configuration items name value description mapreduce.job.reduce.slowstart.completedmaps 0.05 Resource requests for Reduce Task will not be made until the percentage of Map Task completed reaches that value. mapreduce.output.fileoutputformat.compress false […]