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') {
       ...