🐛 修复颜色解析错误,采用 wcag 标准

This commit is contained in:
BTMuli
2023-09-04 19:04:18 +08:00
parent 477201bfb3
commit 27bf6bdc41
3 changed files with 37 additions and 35 deletions

View File

@@ -50,6 +50,7 @@
"@mdi/font": "7.2.96", "@mdi/font": "7.2.96",
"@tauri-apps/api": "^1.4.0", "@tauri-apps/api": "^1.4.0",
"clipboard": "^2.0.11", "clipboard": "^2.0.11",
"color-convert": "^2.0.1",
"echarts": "^5.4.3", "echarts": "^5.4.3",
"html2canvas": "^1.4.1", "html2canvas": "^1.4.1",
"js-md5": "^0.7.3", "js-md5": "^0.7.3",
@@ -61,10 +62,12 @@
"vue-echarts": "^6.6.1", "vue-echarts": "^6.6.1",
"vue-json-viewer": "^3.0.4", "vue-json-viewer": "^3.0.4",
"vue-router": "^4.2.4", "vue-router": "^4.2.4",
"vuetify": "^3.3.15" "vuetify": "^3.3.15",
"wcag-color": "^1.1.1"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "^1.4.0", "@tauri-apps/cli": "^1.4.0",
"@types/color-convert": "^2.0.0",
"@types/js-md5": "^0.7.0", "@types/js-md5": "^0.7.0",
"@types/node": "^20.5.7", "@types/node": "^20.5.7",
"@typescript-eslint/eslint-plugin": "^6.5.0", "@typescript-eslint/eslint-plugin": "^6.5.0",

25
pnpm-lock.yaml generated
View File

@@ -14,6 +14,9 @@ dependencies:
clipboard: clipboard:
specifier: ^2.0.11 specifier: ^2.0.11
version: 2.0.11 version: 2.0.11
color-convert:
specifier: ^2.0.1
version: 2.0.1
echarts: echarts:
specifier: ^5.4.3 specifier: ^5.4.3
version: 5.4.3 version: 5.4.3
@@ -50,11 +53,17 @@ dependencies:
vuetify: vuetify:
specifier: ^3.3.15 specifier: ^3.3.15
version: 3.3.15(typescript@5.2.2)(vite-plugin-vuetify@1.0.2)(vue@3.3.4) version: 3.3.15(typescript@5.2.2)(vite-plugin-vuetify@1.0.2)(vue@3.3.4)
wcag-color:
specifier: ^1.1.1
version: 1.1.1
devDependencies: devDependencies:
'@tauri-apps/cli': '@tauri-apps/cli':
specifier: ^1.4.0 specifier: ^1.4.0
version: 1.4.0 version: 1.4.0
'@types/color-convert':
specifier: ^2.0.0
version: 2.0.0
'@types/js-md5': '@types/js-md5':
specifier: ^0.7.0 specifier: ^0.7.0
version: 0.7.0 version: 0.7.0
@@ -651,6 +660,16 @@ packages:
'@tauri-apps/cli-win32-x64-msvc': 1.4.0 '@tauri-apps/cli-win32-x64-msvc': 1.4.0
dev: true dev: true
/@types/color-convert@2.0.0:
resolution: {integrity: sha512-m7GG7IKKGuJUXvkZ1qqG3ChccdIM/qBBo913z+Xft0nKCX4hAU/IxKwZBU4cpRZ7GS5kV4vOblUkILtSShCPXQ==}
dependencies:
'@types/color-name': 1.1.1
dev: true
/@types/color-name@1.1.1:
resolution: {integrity: sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==}
dev: true
/@types/cookie@0.4.1: /@types/cookie@0.4.1:
resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==}
dev: true dev: true
@@ -1318,7 +1337,6 @@ packages:
engines: {node: '>=7.0.0'} engines: {node: '>=7.0.0'}
dependencies: dependencies:
color-name: 1.1.4 color-name: 1.1.4
dev: true
/color-name@1.1.3: /color-name@1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
@@ -1326,7 +1344,6 @@ packages:
/color-name@1.1.4: /color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
dev: true
/colord@2.9.3: /colord@2.9.3:
resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
@@ -4873,6 +4890,10 @@ packages:
vite-plugin-vuetify: 1.0.2(vite@4.4.9)(vue@3.3.4)(vuetify@3.3.15) vite-plugin-vuetify: 1.0.2(vite@4.4.9)(vue@3.3.4)(vuetify@3.3.15)
vue: 3.3.4 vue: 3.3.4
/wcag-color@1.1.1:
resolution: {integrity: sha512-KRez+YYOx7AGoQ6+Izu3YjNsISYAC+F/g0hJ+eNaaA8taeLbEkptkgA46SM9ioXxz/2KTjJpQqAhOwAQVwaTEQ==}
dev: false
/which-boxed-primitive@1.0.2: /which-boxed-primitive@1.0.2:
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
dependencies: dependencies:

View File

@@ -5,23 +5,9 @@
* @since Beta v0.3.0 * @since Beta v0.3.0
*/ */
/** // third party
* @description 16进制颜色转 RGB import { score } from "wcag-color";
* @since Alpha v0.1.3 import * as colorConvert from "color-convert";
* @param {string} hex 16进制颜色
* @returns {{ r: number; g: number; b: number }} RGB颜色
*/
function hexToRgb(hex: string): { r: number; g: number; b: number } {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
if (result === null) {
throw new Error("无法解析颜色");
}
return {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
};
}
/** /**
* @description 给定两个16进制颜色值确认两者是否相近 * @description 给定两个16进制颜色值确认两者是否相近
@@ -31,21 +17,13 @@ function hexToRgb(hex: string): { r: number; g: number; b: number } {
* @returns {boolean} 是否相近 * @returns {boolean} 是否相近
*/ */
function isColorSimilar(colorBg: string, colorFg: string): boolean { function isColorSimilar(colorBg: string, colorFg: string): boolean {
const colorBgRGB = hexToRgb(colorBg); let hexBg, hexFg;
const colorFgRGB = hexToRgb(colorFg); if (colorBg.startsWith("#")) hexBg = colorBg;
const colorBgL = 0.2126 * colorBgRGB.r + 0.7152 * colorBgRGB.g + 0.0722 * colorBgRGB.b; else hexBg = colorConvert.keyword.hex(colorBg);
const colorFgL = 0.2126 * colorFgRGB.r + 0.7152 * colorFgRGB.g + 0.0722 * colorFgRGB.b; if (colorFg.startsWith("#")) hexFg = colorFg;
const colorBgLum = colorBgL / 255; else hexFg = colorConvert.keyword.hex(colorFg);
const colorFgLum = colorFgL / 255; const contrast = score(hexFg, hexBg);
const colorBgLumFinal = return contrast === "Fail";
colorBgLum <= 0.03928 ? colorBgLum / 12.92 : Math.pow((colorBgLum + 0.055) / 1.055, 2.4);
const colorFgLumFinal =
colorFgLum <= 0.03928 ? colorFgLum / 12.92 : Math.pow((colorFgLum + 0.055) / 1.055, 2.4);
const contrast =
(Math.max(colorBgLumFinal, colorFgLumFinal) + 0.05) /
(Math.min(colorBgLumFinal, colorFgLumFinal) + 0.05);
// console.log(colorBg, colorFg, contrast);
return contrast > 1.5 && contrast < 4;
} }
/** /**