Results demonstrate

Make ideas

Use an Item class member to represent each array, call window. RequestAnimationFrame to draw each frame

To make the Item class

For each member of the array, we need to know its value, width, height, color and position on the canvas, and set the number of pixels moved in each frame, using Vx and VY to represent the speed vector. The drawItem function is its drawing function.

// Item.js
class Item {
   constructor(value, width, heigth){
       this.value = value;
       this.width = width;
       this.heigth = heigth;
       // Lower left corner dot
       this.x = 0;
       this.y = 0;
       this.vx = 5;
       this.vy = 0;
       this.color = 'gray';
   }
   drawItem (ctx) {
       ctx.save();
       // Move the axis to the lower left corner
       ctx.translate(this.x, this.y);
       // Draw a rectangle
       ctx.fillStyle = this.color;
       ctx.beginPath();        
       ctx.moveTo(0.0);
       ctx.lineTo(this.width, 0);
       ctx.lineTo(this.width, -this.heigth);
       ctx.lineTo(0, -this.heigth);
       ctx.lineTo(0.0);
       ctx.closePath();
       ctx.stroke();
       ctx.fill();
       
       // Draw the numbers
       ctx.fillStyle = "black";
       ctx.font = `The ${this.width-20}px Arial`;
       ctx.fillText(this.value, 0.0); ctx.restore(); }}Copy the code

Since the time is mainly spent on the movement of two objects (the other is the process of comparing the size and color), if you need to set the multiple speed demonstration, you simply need to multiply the VX value by the corresponding multiplier in the later program.

Handle arrays

let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
// Randomly generate an ARR array
let arr = new Array(Math.ceil(Math.random()*15+1)).fill(0);
arr = arr.map(() = > Math.ceil(Math.random()*29+1));
// The arrHeigth array is stored at the corresponding height according to the arR member value (set maximum height to 400px).

//utils. Js sets a height return function arrHeigth
let arrHeigth = utils.arrHeigth(arr, 400);
let arrWidth = 50;
//Arr stores the corresponding Item member
let Arr = [];
let numArr = arr.length;
Copy the code
// utils.js
let utils = {};
// The height of the array member is proportional to the value
utils.arrHeigth = function (_array, maxheigth) {
    let max = Math.max(... _array);let pro = maxheigth / max;
    let _arrHeigth = _array.map((item, index) = > {
        return item * pro;
    });
    return _arrHeigth;  
}
Copy the code

The Arr holds the Item, and then you just loop through the Arr to draw each member

for (let item, i = 0; i < numArr; i++) {
     item = new Item(arr[i], arrWidth, arrHeigth[i]);
     item.x = Math.ceil((canvas.width - 60*numArr) / 2) + 60*i;
     item.y = 400;
     Arr.push(item);
}
Copy the code

Compare (color)

Since comparing the size (turning green and yellow at the same time) can be done in one frame, but moving requires many frames, if not processed, it will lead to instant coloring and fading, which is not consistent with the look and feel, as shown in the picture below.

So we define a variable to control how long the state stays, and here we define a frame. In the bubbleCompare function that compares the size, there is an array called compareArr, whose first value indicates whether the comparison is complete (frame%30 if you want the comparison to last 30 frames in green), and if not, no action is taken and the next frame continues; The second value represents whether positions need to be swapped, providing a judgment as to whether the swap process needs to be plotted later.

let frame = 0;
let compareArr = [0.0];

function bubbleCompare(array, j){
    frame++;
    compareArr = [0.0];
    array[j].color = 'green';
    array[j+1].color = 'yellow';
    if (frame%30= =0){
    frame = 0;
    compareArr[0] = 1;
    }
    if (array[j].value > array[j+1].value){
    compareArr[1] = 1; }}Copy the code

Draw the mobile

To determine whether the swap is complete, let drawBubble return a Boolean that can be used to determine whether the operation is performed (and swap the two Arr items and adjust the corresponding parameters).

function drawBubble(array, j){
    array[j].x += array[j].vx;
    array[j+1].x -= array[j+1].vx;
    if (array[j].x == (Math.ceil((canvas.width - 60*numArr) / 2) + 60*(j+1)))
    {
    return true;
    } else {
    return false; }}Copy the code

frame

Now you can start drawing each frame

Overall structure:

(function drawFrame() {
        let raf = window.requestAnimationFrame(drawFrame, canvas);
        ctx.clearRect(0.0, canvas.width, canvas.height);
        / /...
        // Make a comparison
        // Move object (change item.x)
        // Adjust parameters
        // Check whether it is complete
        // ...
        // Walk through the Arr and draw each Item:
        Arr.forEach((item) = >{ item.drawItem(ctx); }); } ());Copy the code

Complete code:

    let _i = 0,
        _j = 0.//compare_bool Determines whether the bubbleCompare comparison function needs to be executed
        compare_bool = 1;
    
    (function drawFrame() {
        let raf = window.requestAnimationFrame(drawFrame, canvas);
        ctx.clearRect(0.0, canvas.width, canvas.height);
        
        if (compare_bool){
            // Start comparing
            bubbleCompare(Arr, _j);
        }
        
        if (compareArr[0] = =1){
            
            compare_bool = 0;
            
            if(compareArr[1] = =1) {// Start moving (set item.x)
                if(drawBubble(Arr, _j)){
                    // The move is complete
                    let t = Arr[_j];
                    Arr[_j] = Arr[_j+1];
                    Arr[_j+1] = t;
                    Arr[_j].color = 'gray';
                    Arr[_j+1].color = 'gray';
                    _j++;
                    compare_bool = 1; }}if (compareArr[1] = =0){
                Arr[_j].color = 'gray';
                Arr[_j+1].color = 'gray';
                _j++;
                compare_bool = 1; }}// Adjust parameters
        if (_j == numArr-_i-1) {
            Arr[_j].color = 'red';
            _j = 0;
            _i++;
            // Determine whether all sorts are completed
            if (_i == numArr-1) {
                Arr[0].color = 'red';
                Arr[0].drawItem(ctx);
                window.cancelAnimationFrame(raf); }}/ / to draw
        Arr.forEach((item) = >{ item.drawItem(ctx); }); } ());Copy the code