iT邦幫忙

2023 iThome 鐵人賽

DAY 5
0
SideProject30

30 天用 Rust 打造 QR Code 製造機系列 第 5

Day 5 - 加入顏色選擇功能

  • 分享至 

  • xImage
  •  

目前專案的後端 API 已經能夠根據使用者的輸入產生客製化的 QR Code。不過,QR Code 不只能展示資料,它的外觀也可以根據使用者的喜好進行調整。所以今天,我們要來實作一個新的功能,可以讓使用者自行選擇 QR Code 的前景和背景色。

結構增加顏色參數

為了實現這個功能,我們需要先擴充 Info 結構,這樣就可以接收顏色的資訊:

#[derive(serde::Deserialize)]
struct Info {
    url: String,
    foreground: Option<String>,
    background: Option<String>,
}

其中的 foregroundbackground 參數是選填的,使用者如果不輸入,我們可以使用預設的顏色。

增加一個 API 來改變顏色

由於 qrcode 這個套件中,對於 image 似乎沒有修改顏色的方法,但是有針對修改顏色這部分,用在了 svg 上,所以我們先從 qrcode 中取出 svg。

然後預想這個新的 API 會使用 POST 來處理,所以也要從 actix_web 中取出 post

use actix_web::{get, post, web, App, HttpResponse, HttpServer};
use image::{DynamicImage, Luma};
use qrcode::render::svg;
use qrcode::QrCode;

接著來到今天的主軸,新增一個使用 post 的函式:

#[post("/generate_qr_svg")]
async fn generate_svg(data: web::Json<Info>) -> HttpResponse {
    let fg_color_str = match &data.foreground {
        Some(color) => color,
        None => "#000000",
    };

    let bg_color_str = match &data.background {
        Some(color) => color,
        None => "#FFFFFF",
    };

    let code = match QrCode::new(data.url.as_bytes()) {
        Ok(c) => c,
        Err(_) => return HttpResponse::BadRequest().body("你輸入的字串無法處理"),
    };

    let image = code
        .render()
        .min_dimensions(200, 200)
        .dark_color(svg::Color(fg_color_str))
        .light_color(svg::Color(bg_color_str))
        .build();

    HttpResponse::Ok().content_type("image/svg+xml").body(image)
}

然後在 main() 新增一個 service

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(index).service(generate_svg))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

在 Postman 測試

然後接下來由於要使用 POST 來呼叫 API,所以我們使用 Postman 來測試。

URL 傳入 http://127.0.0.1:8080/generate_qr_svg,然後 Body 傳入 JSON 格式,例如:

{
    "url": "https://buckychu.im",
    "foreground": "#0375a6",
    "background": "#ffff80"
}

就可以得到以下的結果:

https://ithelp.ithome.com.tw/upload/images/20230922/20120293TK1SoRwSBi.png

顏色沒輸入遇到的問題

前面提到顏色的部分是選填,所以我們也測試一下如果沒加上顏色會怎麼樣:

https://ithelp.ithome.com.tw/upload/images/20230922/20120293rnEtPQJeSs.png

看起來好像沒問題,不過如果傳入的 JSON 格式是這樣的話:

{
    "url": "https://buckychu.im",
    "foreground": "",
    "background": ""
}

所得到的結果會是一團黑的圖片:

https://ithelp.ithome.com.tw/upload/images/20230922/20120293cJewFNzOxc.png

雖然說我們可以在前端幫忙處理,不過這樣總是不夠完整。

修正顏色沒輸入的問題

針對這個問題,我們可以使用正則表達式來驗證輸入的顏色字符串。

首先在 Terminal 安裝 regex 這個套件:

cargo add regex

並且引入 regex:

use regex::Regex;

然後新增一個函式來幫助我們驗證:

fn is_valid_color(color: &str) -> bool {
    let re = Regex::new(r"^#[0-9a-fA-F]{6}$").unwrap();
    re.is_match(color)
}

接下來來驗證一下輸入的顏色是否符合:

#[post("/generate_qr_svg")]
async fn generate_svg(data: web::Json<Info>) -> HttpResponse {
    let fg_color_str = match &data.foreground {
        Some(color) if is_valid_color(color) => color,
        _ => "#000000",
    };

    let bg_color_str = match &data.background {
        Some(color) if is_valid_color(color) => color,
        _ => "#FFFFFF",
    };

// 以下省略

重新啟動專案後,再測試一下應該就沒問題了。

https://ithelp.ithome.com.tw/upload/images/20230922/20120293y9SLAw8UhH.png

結語

今天增加了顏色自訂功能,讓使用者可以根據自己的喜好進行調整。明天我們將繼續優化這個專案,加入更多實用功能,敬請期待!


上一篇
Day 4 - 加強使用者互動
下一篇
Day 6 - 為 QR Code 新增圖片大小縮放功能
系列文
30 天用 Rust 打造 QR Code 製造機30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

我要留言

立即登入留言