PHP thuần: tạo một progress bar(thanh tiến trình) trên command line

Tình cờ thấy một số thanh progress bar trên nodejs khá hay ho, hôm nay tôi sẽ hướng dẫn mọi người viết một cái progress bar màu mè bằng php. Tạo class ProgressBar <?php final class ProgressBar { /**Ký tự dùng phần hoàn thành của progress bar */ const FILL_CHAR ="▓";/**Ký tự dùng phần còn

Tình cờ thấy một số thanh progress bar trên nodejs khá hay ho, hôm nay tôi sẽ hướng dẫn mọi người viết một cái progress bar màu mè bằng php.

Tạo class ProgressBar

<?php
final class ProgressBar
{
    /**Ký tự dùng phần hoàn thành của progress bar */
    const FILL_CHAR ="▓";/**Ký tự dùng phần còn lại chưa hoàn thành của progress bar */
    const NOT_FILL_CHAR ="░";/** Độ dài tối đa của thanh progress bar */
    const BAR_LENGTH =50;/** @var int Số bứớc nhảy tối đa của  progress bar, mặc định ban đầu là 0*/
    private $maxProcess =0;/** @var int Bứớc nhảy hiện tại của  progress bar, mặc định ban đầu là 0 */
    private $currenProcess =0;/** @var bool Trạng thái kết thúc của thanh tiến trình */
    private $endProgress =false;/** @var string Nơi lưu toàn bộ progress bar */
    private  $progressBar ="";/** Danh sách màu của progress bar, cái này chỉ để cho thanh progress bar trông màu mè hơn xíu :)) */
    private $colors =[];
}

Tạo constructor để khởi tạo số bước nhảy tối đa của progress bar, tiếp đó là khởi tạo các mã màu để sử dụng cho việc biến đổi màu sắc theo số % của thanh tiến trình.

public function __construct($max){$this->maxProcess =$max;$this->initColorCode();}

private function initColorCode(){for($i=196;$i<=231;$i++){$this->colors[]=$i;}for($i=123;$i>=119;$i--){for($j=0;$j<3;$j++){$this->colors[]=$i-36*$j;}}}

Hàm tạo color code theo số %:

privatefunctiongetColorCode($percent){$code=floor($percent/2);if(!isset($this->colors[$code])){$code=$this->colors[count($this->colors)-1];}else{$code=$this->colors[$code];}return"e[38;5;{$code}m";}

Mỗi lần progress bar thay đổi, các ký tự đã show ra console trước đó phải được replace, hàm getBackward sẽ nhận vào số % hiện tại và trả về ký tự thoát tương ứng để relpace lại các ký tự đã in ra trước đó:

private function getBackward($percent){$backward=(strlen($this->progressBar)+2);if($percent<10){$backward++;}return"33[{$backward}D ";}

Ui chao nghe lan man quá, rồi cái thanh tiến trình của tôi đâu. Thôi thì mình sẽ show code chính trước, hàm bổ trợ mình để ở dưới và giải thích sau nhé 😃)

publicfunctionstart(){echo"n33[?25l";// show break line and hide cursor$this->showProcess(0);}

Hàm start ẩn con trỏ trên console và gọi hàm showProcess với đầu vào ban đầu là 0%(sẽ viết bên dưới)

publicfunctionadvance($step=1){$this->currenProcess+=$step;// Mỗi lần gọi hàm thì tăng current process lên $percent=floor($this->currenProcess*100/$this->maxProcess);// tính toán số phần trăm tương ứng với process hiện tại$this->showProcess($percent);// gọi hàm để show progress barif($percent>=100&&!$this->endProgress){// nếu số phần trăm đã vượt ngưỡng 100%, đánh dấu là end progress để không tăng thêm độ dài cho progress bar$this->endProgress=true;}}

Hàm advance cho phép truyền vào 1 tham số int, là bước nhảy của progress bar. Nếu không truyền vào thì mặc định mỗi lần gọi sẽ tăng step lên 1 đơn vị.

publicfunction__destruct(){$this->endProgress=true;echo"33[?25hn";//show cursor and break line}

Sau khi chạy xong thì destructor sẽ được gọi và hiển thị con trỏ trở lại.

Còn thiếu 2 hàm createProgress và showProcess, ngay đây thôi 😃)

private function createProgress($percent){$bar='';if($percent>=100){// Nếu số phần trăm quá 100, gán lại bằng 100 để không tăng thêm độ dài cho progress bar
        $percent = 100;
    }
    $fillPoint = floor($percent / (floor(100 / static::BAR_LENGTH))); // tính toán xem cần fill bao nhiêu % hoàn thành vào progress bar
    for ($i = 0; $i < $fillPoint; $i++) {
        $bar .= static::FILL_CHAR;
    }
    $notFill = static::BAR_LENGTH - $fillPoint; // tính toán xem cần fill bao nhiêu % chưa hoàn thành vào progress bar
    for ($i = 0; $i < $notFill - 1; $i++) {
        $bar .= static::NOT_FILL_CHAR;
    }

    return $bar; // trả về 1 chuỗi thanh tiến trình
}
private function showProcess($percent)
{
    $backward = $this->getBackward($percent); // get backward code để replace lại progress bar
    $bar=$this->createProgress($percent);// tạo progress bar string

    $colorCode=$this->getColorCode($percent);// get mã màu tương ứng với thanh tiến trình hiện tại

    $total="{$this->currenProcess}/".($this->currenProcess >$this->maxProcess ?$this->currenProcess :$this->maxProcess);// tính tổng số step
    echo $this->progressBar ="{$backward}{$colorCode} {$total} "// show progress bar
        . Formater::ESCAPE
        ." [{$colorCode}{$bar}". Formater::ESCAPE
        ."] {$colorCode}{$percent} %". Formater::ESCAPE;}
private function getColorCode($percent){$code= floor($percent/2);if(!isset($this->colors[$code])){$code=$this->colors[count($this->colors)-1];}else{$code=$this->colors[$code];}return"e[38;5;{$code}m";}

Cuối cùng là khởi tạo instance của ProgressBar để test thôi nào

$command = new Command;
$command->progressStart(1000);
for($i = 0; $i < 1000; $i++) {
    $command->progressAdvance();
    usleep(50000);// sleep nửa giây cho mỗi step để xem thanh tiến trình thay đổi từ từ :))
}

Full code tại đây

Tham khảo mã màu cho console tại đây

Thank for watching ;p

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ