背景#
今天想投稿幾篇文章到不同的網站,發現掘金要求提供文章 Banner 圖,創建掘金文章集合也需要提供圖片,提供圖片倒是沒啥,主要是尺寸都不一樣,我默認只有 1:1 的圖片。
奇奇怪怪的尺寸 + 重複勞動編輯 + 隨用隨棄無需保存的圖片 + 風格儘量統一 = 做一個模板圖片生成工具。
目前也不需要複雜的拖拽功能、多樣的素材,看起來簡單的圖片背景 + 文字 + 尺寸可調就滿足要求了。
那就順手做一個,先做一個簡單版本的,也積累一些常用代碼
目前實現的效果長這樣,訪問地址 https://ijust.cc/tools/canvas
製作思路#
- 固定一個常用的模板,文字要可以編輯
- 樣式可以使用 html2canvas (特意使用了一個其他方案) 生成圖片
- 避免樣式不同,背景可變
技術選型#
shadcn 樣式#
功能不複雜,寫個表單,堆個樣式,生成圖片就可以。對完成任務有信心,所以嘗試困難 i+1,我能不能順手學習的 tailwind 相關的組件庫。
博客的網站已經整體使用 tailwindcss + varlet 組件了,不想重新引入 element-plus/arco-design 相關的組件,看起來 tailwindcss 提供的組件,侵入性不大,打包體積應該影響不大。
翻閱筆記,之前就加入收藏夾的 shadcn 映入眼簾,目前 shadcn-vue 進展特別快,樣式比較簡約,背後依賴 radix 作為低級封裝,應該挺不錯的。後續 shadcn 模板庫起來了,應該也不錯。
這樣選擇 shadcn-vue 作為組件庫,開搞。
用起來稍微有別別扭,看了一會兒也就順眼了,風格很素,我選擇 gray 風格,也沒有特別傻黑。
html-to-image 生成圖片#
基於 html 生成圖片,大名鼎鼎的 html2canvas 就很不錯,我去 https://npmtrends.com/ 一搜,發現 https://github.com/bubkoo/html-to-image 還不錯,更新頻率高、文檔樣式現代,api 清晰,也拿來用。
動態顏色 hsl#
背景顏色這塊,我習慣稍微素一點的顏色,常規的 taiwindcss colors 感覺還不太夠,我想更自由一點,所以我把目光投向了相同飽和度、亮度,不同色相的思路。
這一點在 ps 上用的比較多,通過拖動色相,快速改變整體顏色。
這一塊用到的是 HSB 色彩模型,相同位置,只修改色相就可以。如下圖。
這樣 hsb 的後兩者就有值了,H 透過滑塊拖動就可以。
第一反應 filter,也就是 hub-rotate
.hue{
filter: hue-rotate(45deg);
}
實際寫出來不好使,部分元素比如人物形象不參與 filter,做不到,要逐一修改 background 和 text 還挺麻煩。
還是動態修改 css,但我發現 css 裡沒有 hsb 有個 hsl,問問軍師:
介紹 hsb 和 hsl 的區別
HSB (色相、飽和度、亮度) 和 HSL (色相、飽和度、亮度) 是兩種常用的顏色模型,它們在描述顏色的方式上有一些區別。巴拉巴拉
兩者如何轉換?
// HSB to HSL
function hsbToHsl(h, s, b) {
let l = (2 - s) * b / 2;
s = s * b / (l < 0.5 ? l * 2 : 2 - l * 2);
return [h, s, l];
}
// HSL to HSB
function hslToHsb(h, s, l) {
let v = l + s * (l < 0.5 ? l : 1 - l);
s = 2 * s / (v + l);
return [h, s, v];
}
// Example usage
const hsbColor = [0.5, 0.7, 0.8];
const hslColor = hsbToHsl(...hsbColor);
console.log(hslColor); // [0.5, 0.4666666666666667, 0.65]
const convertedHsbColor = hslToHsb(...hslColor);
console.log(convertedHsbColor); // [0.5, 0.7, 0.8]
function hslToRgb(h: number, s: number, l: number) {
// 將色調值轉換為 0 到 1 之間的小數
h = h / 360;
// 飽和度和亮度值為百分比,轉換為 0 到 1 之間的小數
s = s / 100;
l = l / 100;
let r, g, b;
if (s === 0) {
// 當飽和度為 0 時,顏色為灰色
r = g = b = l;
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
// 將 RGB 值轉換為整數,並將值限制在 0 到 255 之間
r = Math.round(r * 255);
g = Math.round(g * 255);
b = Math.round(b * 255);
// return { r, g, b };
return `rgb(${r},${g},${b})`;
}
懂了,有現成的方法,試了試好使,工具庫 + 1,學到了點東西。
一番操作,就實現了 css 動態修改 h 色相。
<div :style='{
background: 'hsl(' + config.hue[0] + ',48.1%,48.6%)',
}'>動態背景<div>
chrome 實際運行的時候,還是 rgb,但是用著舒服,拖拽滑塊顏色就改變了。
改變顏色時候順手加個 will-change 和 transition 舒服。
補充:後來順手加了一個 45 度傾斜的線性漸變,from A to B。這裡以色相顏色為 A,對應顏色加一點,+50 得到顏色 B,實際效果也挺不錯。
補充:後來順手加一個低維背景圖,也很好看,用的是
效果#
展望#
後續可以嘗試作為獨立服務,圖片自定義啥的。