JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html>
<html lang="Zh-Hant">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>顏色</title>
</head>
<body>
選擇 CIELab 顏色
<input class="labInput" type="text" placeholder="L*">
<input class="labInput" type="text" placeholder="a*">
<input class="labInput" type="text" placeholder="b*">
<input type="submit" value="確認">
<hr>
<div class="container">
<div class='grid' id='js-color'></div>
<iframe id='pdf-color'></iframe>
</div>
<ul>
<li>這會產生一個以 L*a*b* 填滿色塊的 PDF(PDF允許以 L*a*b* 設定顏色)</li>
<li>另外也會產生一個 div 放在 pdf 中間,其顏色是透過 js 轉換出來的 RGB</li>
<li>比較兩者,如果看不出與色塊差別代表 js 算出來的結果與瀏覽器處理PDF顏色的結果相同</li>
</ul>
</body>
</html>
CSS
.labInput{
width: 3em;
text-align: center;
}
.container{
position: relative;
height: 400px;
}
#js-color{
position: absolute;
left: 100px;
top: 100px;
z-index: 100;
width: 200px;
height: 200px;
display: flex;
align-items: center;
justify-content:center;
}
#pdf-color{
position: absolute;
left: 0px;
top: 0px;
width:400px;
height: 400px;
vertical-align: top;
border:none;
}
JavaScript
/**
* 色彩空間的轉換函式庫
*/
const ColorSpace={
Xn: 0,
Yn: 0,
Zn: 0,
CIELab2XYZ(l, a, b) {
let fy=(l+16)/116,
fx=fy+a/500,
fz=fy-b/200,
d=6/29;
return [
this.Xn*(fx>d ? fx*fx*fx : (fx-16/116)*3*d*d),
this.Yn*(fy>d ? fy*fy*fy : (fy-16/116)*3*d*d),
this.Zn*(fz>d ? fz*fz*fz : (fz-16/116)*3*d*d),
];
},
XYZ2SRGB(x, y, z) {
let arr=[3.2406255 * x - 1.5372080 * y - 0.4986286 * z,
-0.9689307 * x + 1.8757561 * y + 0.0415175 * z,
0.0557101 * x - 0.2040211 * y + 1.0569959 * z
];
return arr.map(ci=>{
let v=ci>0.0031308?1.055*Math.pow(ci, 1/2.4)-0.055:ci*12.92;
v=Math.round(v*255);
return v<0?0:(v>255?255:v);
});
},
// XYZ2ADOBERGB(x, y, z) { //此函式尚未確認正確
// let arr=[2.04159 * x - 0.56501 * y - 0.34473 * z,
// -0.96924 * x + 1.87597 * y + 0.04156 * z,
// 0.01344 * x - 0.11836 * y + 1.01517 * z
// ];
// return arr.map(ci=>{
// return Math.round(255*(ci<0?0:Math.pow(ci, 256/563)));
// });
// },
CIELab2SRGB(l, a, b) {
let arr=this.CIELab2XYZ(l, a, b);
return this.XYZ2SRGB.apply(this, arr);
},
useD50() {
this.Xn = 0.964212;
this.Yn = 1;
this.Zn = 0.825188;
},
useD65() {
this.Xn = 0.950489;
this.Yn = 1;
this.Zn = 1.088840;
},
}
ColorSpace.useD65();
/**
* 產生 pdf 的基本工具
* 先用 addObject 寫入所需的物件
* 最後用 output 輸出
*/
function Pdf()
{
this.idCount=0;
this.data=[];
}
Pdf.prototype.addObject=function(dict, stream) {
if(typeof stream==='string') {
dict['Length']=stream.length;
}
let arr=[];
arr.push(`${++this.idCount} 0 obj`);
arr.push('<<');
for(let key in dict) {
arr.push(`/${key} ${dict[key]}`);
}
arr.push('>>');
if(typeof stream==='string') {
...