Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
近期,三大主流瀏覽器引擎均發(fā)布最新版本,支持W3C的CSS Color 4標(biāo)準(zhǔn),包含新的取色方法color()和相應(yīng)語(yǔ)法,可展示更多的色域及色彩空間,這意味著web端能展示更豐富更高清的色彩。雖然目前只有最新版本的現(xiàn)代瀏覽器才支持,我們可以先提前了解一下這項(xiàng)新標(biāo)準(zhǔn)。
本文首先會(huì)先簡(jiǎn)單介紹幾個(gè)色彩的基礎(chǔ)概念,了解為何需要新標(biāo)準(zhǔn),之后會(huì)介紹新標(biāo)準(zhǔn)中的方法和語(yǔ)法使用。
指顏色的可選范圍。如sRGB色域,目前web廣泛應(yīng)用的色域標(biāo)準(zhǔn),使用紅(red)綠(green)藍(lán)(blue)作為基礎(chǔ)色,色值范圍0~255,三種基礎(chǔ)色互相混合起來(lái)可展示255*255*255種顏色,這大致可理解為sRGB的色域。
現(xiàn)代web css使用的sRGB色域僅滿足基礎(chǔ)性的色彩需求,能展示的色彩范圍遠(yuǎn)小于人類肉眼所能感知的顏色范圍,也遠(yuǎn)低于高清展示的要求。
以下是sRGB與其他幾種色域標(biāo)準(zhǔn)的色值范圍大小比較:
??以下是sRGB與人類肉眼可感知的色域比較:
色彩空間可以理解為一個(gè)基于某一色域標(biāo)準(zhǔn)下構(gòu)建的空間數(shù)學(xué)模型,例如一些簡(jiǎn)單的方塊、圓柱的3D模型,可以用來(lái)標(biāo)記出色域中每個(gè)顏色的空間位置,各個(gè)顏色之間的關(guān)系等。
再用sRGB舉例,紅(red)綠(green)藍(lán)(blue)三種基礎(chǔ)色可設(shè)置為3個(gè)直線坐標(biāo)軸,每種顏色便可標(biāo)記為這個(gè)立方體中的一個(gè)點(diǎn),在css中便是使用rgb()方法來(lái)取色,參數(shù)為指定顏色在色彩空間中的坐標(biāo)(R, G, B)。
再再比如css的另一個(gè)取色方法hsl(),使用的是一套完全不同的色彩空間HSL,H色相(hue)是取值范圍為0~360的角度,可作為角軸;S飽和度(Saturation)和L亮度(Lightness)作為兩個(gè)直線軸,可構(gòu)建為一個(gè)圓柱形的空間,css中使用hsl(H, S, L)表示顏色。
??一種色域標(biāo)準(zhǔn)可以使用不同的色彩空間來(lái)描述,不同的色域標(biāo)準(zhǔn)也可以使用的是同一類的色彩空間表示。例如sRGB可以使用rgb()、hsl()、hwb()等方式進(jìn)行描述,而像Display-P3、Rec2020色域都可以使用(R,G,B)的色彩空間來(lái)描述,只是空間的邊界范圍有所不同。
高清意味著更高范圍的色域,讓我們先直觀感覺(jué)一下窄色域與廣色域的視覺(jué)差距:
??在實(shí)際的css顏色取值中,我們常用的方法有很多rgb()、rgba()、hsl()、hwb(),對(duì)應(yīng)不同的色彩空間,但取的都是同一色域范圍內(nèi)的顏色,即sRGB,大概只能展示人類肉眼可感知的色彩中的30%,仿佛在使用一臺(tái)90年代的電視機(jī)播放4K電影。
雖然目前的網(wǎng)絡(luò)顯示設(shè)備很多還是sRGB標(biāo)準(zhǔn),并不支持顯示更廣色域標(biāo)準(zhǔn)的色彩,僅部分HDR顯示器、或視頻錄制設(shè)備、電影制造中使用了如Display P3這類更廣的色域標(biāo)準(zhǔn)。但對(duì)于高清的需求只會(huì)越來(lái)越多,支持更廣色域標(biāo)準(zhǔn)注定也是未來(lái)web端顯示的目標(biāo)之一。
為應(yīng)對(duì)這一趨勢(shì),W3C的CSS Color 4標(biāo)準(zhǔn)定義了新方法color()和其他語(yǔ)法能更靈活的指定各種不同色域標(biāo)準(zhǔn)下的顏色,以及更好的色彩漸變展示。最近,主流三大web瀏覽器也都已支持了W3C的新標(biāo)準(zhǔn)。
2000年以來(lái),我們有多種方式指定色值:hex色值(#rgb、#rrggbb)、rgb()、rgba()、或是一些特定顏色的字符(如white、pink等);2010年左右開(kāi)始,瀏覽器開(kāi)始支持hsl()方法;2017年,hex色值擴(kuò)展了對(duì)于透明度的支持,#rrggbbaa;之后各種瀏覽器又陸續(xù)增加對(duì)hwb()方法的支持。
不同的方法對(duì)應(yīng)的是不同的色彩空間,但色域都是同一個(gè),即sRGB。
?使用十六進(jìn)制的數(shù)字來(lái)分別表示R、G、B、A的值
.valid-css-hex-colors {
/* 一般標(biāo)準(zhǔn) */
--3-digits: #49b;
--6-digits: #4499bb;
/* 帶透明度 */
--4-digits-opaque: #f9bf; /* 不透明 */
--8-digits-opaque: #ff99bbff; /* 不透明 */
--4-digits-with-opacity: #49b8; /* 透明度88% */
--8-digits-with-opacity: #4499bb88; /* 透明度88% */
}
??使用0~255的十進(jìn)制數(shù)字,或是0%~100%的百分比來(lái)指明R、G、B,透明度A使用百分比或0~1的數(shù)字表示
.valid-css-rgb-colors{
--classic:rgb(64, 149, 191);
--modern:rgb(64 149 191);
--percents:rgb(25% 58% 75%);
--classic-with-opacity-percent:rgba(64, 149, 191, 50%);
--classic-with-opacity-decimal:rgba(64, 149, 191, .5);
--modern-with-opacity-percent:rgb(64 149 191 / 50%);
--modern-with-opacity-decimal:rgb(64 149 191 / .5);
--percents-with-opacity-percent:rgb(25% 58% 75% / 50%);
--percents-with-opacity-decimal:rgb(25% 58% 75% / 50%);
--empty-channels:rgb(none none none);
}
??這種色彩空間更符合人類自然理解,無(wú)需了解紅綠藍(lán)基礎(chǔ)色是如何混合的。參數(shù)分別表示:
?H:hue,色相,取值0deg~360deg
?S:Saturation,飽和度,取值0%~100%
?L:Lightness,亮度,取值0%~100%
.valid-css-hsl-colors{
--classic:hsl(200deg, 50%, 50%);
--modern:hsl(200 50% 50%);
--classic-with-opacity-percent:hsla(200deg, 50%, 50%, 50%);
--classic-with-opacity-decimal:hsla(200deg, 50%, 50%, .5);
--modern-with-opacity-percent:hsl(200 50% 50% / 50%);
--modern-with-opacity-decimal:hsl(200 50% 50% / .5);
/* 無(wú)色相和飽和度,僅用亮度可表示黑白色 */
--empty-channels-white:hsl(none none 100%);
--empty-channels-black:hsl(none none 0%);
}
??形式上和HSL類似,但使用的3個(gè)維度為:
?H:Hue,色相,取值0deg~360deg;
?W:Whiteness,白色的濃度(0~100%);
?B:Blackness,黑色的濃度(0~100%);
.valid-css-hwb-colors{
--modern:hwb(200deg 25% 25%);
--modern2:hwb(200 25% 25%);
--modern-with-opacity-percent:hwb(200 25% 25% / 50%);
--modern-with-opacity-decimal:hwb(200 25% 25% / .5);
/* 無(wú)色相和飽和度,僅用亮度可表示黑白色 */
--empty-channels-white:hwb(none 100% none);
--empty-channels-black:hwb(none none 100%);
}
??新的color()方法的參數(shù)類似于rgb()方法,使用R、G、B三個(gè)直線軸上的數(shù)值來(lái)指明色彩,不同的是color()方法的第一個(gè)參數(shù)可以接收除sRGB以外的其他色域下的色彩空間標(biāo)識(shí)符,且R、G、B的值僅支持0~1或0%~100%。
.valid-css-color-function-colors {
--srgb: color(srgb 1 1 1);
--srgb-linear: color(srgb-linear 100% 100% 100% / 50%);
--display-p3: color(display-p3 1 1 1);
--rec2020: color(rec2020 0 0 0);
--a98-rgb: color(a98-rgb 1 1 1 / 25%);
--prophoto: color(prophoto-rgb 0% 0% 0%);
--xyz: color(xyz 1 1 1);
}
方法定義:color(colorspace c1 c2 c3[ / A])
? 參數(shù)colorspace:標(biāo)識(shí)符,指明使用哪種色彩空間,可選值包括:srgb,srgb-linear,display-p3,a98-rgb,prophoto-rgb,rec2020,xyz,xyz-d50, andxyz-d65.
?參數(shù)c1、c2、c3:可以是number(0~1)、百分比或none,對(duì)應(yīng)指定色彩空間下的各參數(shù)值,比如srgb,srgb-linear,display-p3對(duì)應(yīng)的是R、G、B的值,具體需要看指定色彩空間描述顏色的維度。
?參數(shù)A:可選項(xiàng),可以是number(0~1)、百分比或none,指明顏色的透明度
不再支持0~255取值,改為0~1范圍,其實(shí)和百分比的形式是等價(jià)的。如果傳了大于1的數(shù)值也默認(rèn)當(dāng)作1來(lái)解析。
.valid-css-srgb-colors{
--percents:color(srgb 34% 58% 73%);
--decimals:color(srgb .34 .58 .73);
--percents-with-opacity:color(srgb 34% 58% 73% / 50%);
--decimals-with-opacity:color(srgb .34 .58 .73 / .5);
/* 色值為none或空時(shí),表示黑色 */
--empty-channels-black:color(srgb none none none);
--empty-channels-black2:color(srgb);
}
Linear sRGB和sRGB是不同的色彩空間,sRGB的取值是通過(guò)一個(gè)伽馬曲線函數(shù)做過(guò)校正的,并不是線性變化的,更適應(yīng)人眼的感知特性,即對(duì)明暗的感知是非線性的;而Linear sRGB的顏色變化是線性的,以下是明暗從0-1漸變時(shí),兩種色彩空間實(shí)際的漸變走向。
.valid-css-srgb-linear-colors{
--percents:color(srgb-linear 34% 58% 73%);
--decimals:color(srgb-linear .34 .58 .73);
--percents-with-opacity:color(srgb-linear 34% 58% 73% / 50%);
--decimals-with-opacity:color(srgb-linear .34 .58 .73 / .5);
/* 色值為none或空時(shí),表示黑色 */
--empty-channels-black:color(srgb-linear none none none);
--empty-channels-black2:color(srgb-linear);
}
display P3是最早由蘋果公司推行的。如今這一標(biāo)準(zhǔn)已成為HDR顯示的基礎(chǔ)標(biāo)準(zhǔn),能顯示的顏色比sRGB多50%。而Rec2020標(biāo)準(zhǔn)比display P3的色域更廣,可以用來(lái)顯示4K甚至8K的影像,但目前支持這一標(biāo)準(zhǔn)的終端顯示器還很少。兩種色域都是使用RGB來(lái)描述的。
.valid-css-display-p3-colors{
--percents:color(display-p3 34% 58% 73%);
--decimals:color(display-p3 .34 .58 .73);
--percent-opacity:color(display-p3 34% 58% 73% / 50%);
--decimal-opacity:color(display-p3 .34 .58 .73 / .5);
/* 無(wú)色度色相,展示為黑色 */
--empty-channels-black:color(display-p3 none none none);
--empty-channels-black2:color(display-p3);
}
.valid-css-rec2020-colors {
--percents: color(rec2020 34% 58% 73%);
--decimals: color(rec2020 .34 .58 .73);
--percent-opacity: color(rec2020 34% 58% 73% / 50%);
--decimal-opacity: color(rec2020 .34 .58 .73 / .5);
/* 無(wú)色度色相,展示為黑色 */
--empty-channels-black: color(rec2020 none none none);
--empty-channels-black2: color(rec2020);
}
讓我們先回到開(kāi)頭的兩張色域圖,會(huì)發(fā)現(xiàn)基于RGB描述的色域基本是一個(gè)三角形,因?yàn)槎际鞘褂?個(gè)基礎(chǔ)色混合而成,但人眼所能感知的色域是形似馬蹄的圖形(具體如何繪制出的,感興趣的可自行搜索了解)。基于RGB標(biāo)準(zhǔn)的色彩空間,都很難完全覆蓋人眼能感知的所有顏色。而基于CIE標(biāo)準(zhǔn)(國(guó)際照明委員會(huì)制定的一種測(cè)定顏色的國(guó)際標(biāo)準(zhǔn),它描述了人眼對(duì)顏色的感知和色彩的測(cè)量方法)的色彩空間,理論上是能夠包括人視覺(jué)所能感知到的所有顏色。
CSS Color 4新標(biāo)準(zhǔn)也新增了對(duì)于CIE標(biāo)準(zhǔn)色域的支持。下面介紹的lab()、lch()、oklab()、oklch()都是基于CIE的取色新方法。
?lab()方法描述的是基于CIE標(biāo)準(zhǔn)的色彩空間中的顏色,能夠覆蓋人眼所能看到的全色域。和與基于RGB來(lái)描述色彩的維度不同,lab使用的維度分別為:
?L:lightness,視覺(jué)上線性漸變的亮度,取值范圍0~100或0%~100%;
?A:代表更貼合人眼視覺(jué)特性的兩個(gè)色軸之其一:紅-綠,取值范圍均為 -125~125 或 -100%~100%。當(dāng)A為正值,則為更偏紅色;為負(fù)值時(shí),更偏綠;
?B:代表更貼合人眼視覺(jué)特性的兩個(gè)色軸之其二:藍(lán)-黃,取值范圍均為 -125~125 或 -100%~100%。值為正值,更偏黃;為負(fù)值,更偏藍(lán)。
.valid-css-lab-colors{
--percent-and-degrees:lab(58% -16 -30);
--minimal:lab(58 -16 -30);
--percent-opacity:lab(58% -16 -30 / 50%);
--decimal-opacity:lab(58% -16 -30 / .5);
/* 后兩個(gè)參數(shù)為none是可表示純灰度 */
--empty-channels-white:lab(100 none none);
--empty-channels-black:lab(none none none);
}
lch使用的維度分別是:
?L:lightness,視覺(jué)上線性漸變的亮度,取值范圍0~100或0%~100%;
?C:chroma,顏色的純度,類似于飽和度,取值范圍0~230,但實(shí)際上,這個(gè)值是沒(méi)有上限的;
?H:hue,色相,類似hsl和hwb,是個(gè)角軸,取值范圍0deg~360deg;
.valid-css-lch-colors{
--percent-and-degrees:lch(58% 32 241deg);
--just-the-degrees:lch(58 32 241deg);
--minimal:lch(58 32 241);
--percent-opacity:lch(58% 32 241 / 50%);
--decimal-opacity:lch(58% 32 241 / .5);
/* 后兩個(gè)參數(shù)為none是可表示純灰度 */
--empty-channels-white:lch(100 none none);
--empty-channels-black:lch(none none none);
}
?oklab是校正版的lab,優(yōu)化了圖片處理質(zhì)量,在CSS中意味著漸變優(yōu)化和顏色處理函數(shù)優(yōu)化,消除了色相偏移(hue shift,即在lab中改變顏色純度,色相也會(huì)變化),使用的維度和lab()是一致的。
.valid-css-oklab-colors{
--percent-and-degrees:oklab(64% -.1 -.1);
--minimal:oklab(64 -.1 -.1);
--percent-opacity:oklab(64% -.1 -.1 / 50%);
--decimal-opacity:oklab(64% -.1 -.1 / .5);
/* 后兩個(gè)參數(shù)為none是可表示純灰度 */
--empty-channels-white:oklab(100 none none);
--empty-channels-black:oklab(none none none);
}
??相應(yīng)的,oklch是lch的校正版,取色的邏輯和hsl類似,在圓色盤中選擇一個(gè)角度從而選中一個(gè)色相,再通過(guò)調(diào)節(jié)亮度和純度,也就是hsl中的飽和度,純度和飽和度基本可認(rèn)為是等價(jià)的,區(qū)分僅在于純度和亮度的調(diào)節(jié)通常是同步進(jìn)行的,否則純度很容易超出目標(biāo)色域的范圍。這里有一個(gè)oklch的拾色器,可以體驗(yàn)下。
.valid-css-oklch-colors{
--percent-and-degrees:oklch(64% .1 233deg);
--just-the-degrees:oklch(64 .1 233deg);
--minimal:oklch(64 .1 233);
--percent-opacity:oklch(64% .1 233 / 50%);
--decimal-opacity:oklch(64% .1 233 / .5);
/* 后兩個(gè)參數(shù)為none是可表示純灰度 */
--empty-channels-white:oklch(100 none none);
--empty-channels-black:oklch(none none none);
}
?除了新增的一些取色方法外,新標(biāo)準(zhǔn)還有一個(gè)混色函數(shù),可以將上邊提到的各種不同色彩空間的中顏色進(jìn)行混合計(jì)算出新顏色。
color-mix(in lch, plum, pink);
color-mix(in lch, plum 40%, pink);
color-mix(in srgb, #34c9eb 20%, white);
color-mix(in hsl longer hue,hsl(120 100% 50%) 20%, white);
方法定義:color-mix(method, color1[ p1], color2[ p2])
?參數(shù)method:指定混色的色彩空間,以 in <color space> 的形式,<color space>包含:srgb,srgb-linear,lab,oklab,xyz,xyz-d50, xyz-d65,hsl,hwb,lch, oroklch
?參數(shù)color1、color2:為對(duì)應(yīng)method中指定色彩空間中的任一顏色;
?參數(shù)p1、p2:為可選參數(shù),取值范圍為0%~100%,可以指明混色的比例,如果為空,默認(rèn)color1和color2各為50%;
在我們應(yīng)用一項(xiàng)新語(yǔ)法時(shí),我們通常會(huì)有兩種策略:優(yōu)雅降級(jí)和漸進(jìn)增強(qiáng),具體實(shí)施方案:
這種實(shí)施起來(lái)比較簡(jiǎn)單,即同時(shí)使用新舊取色方法,讓瀏覽器自動(dòng)判斷展示哪種
/* 原代碼 */
color: red;
color:color(display-p3 1 0 0);
/* 如果瀏覽器不支持display-p3,則會(huì)只解析第一行 */
color: red;
/* 如果瀏覽器支持,則會(huì)最終使用第二行 */
color:color(display-p3 1 0 0);
使用@supports和@media先判斷當(dāng)前瀏覽器是否支持新的色域標(biāo)準(zhǔn),并在條件的情況下提供新的色值。
?dynamic-range:取值standard或high,用于判斷當(dāng)前硬件設(shè)備是否支持高清、高對(duì)比度、高色彩精度,不過(guò)這一屬性判斷的比較籠統(tǒng),并不能準(zhǔn)確判斷瀏覽器是否支持新色域和色彩空間。
@media(dynamic-range: high){
/* safe to use HD colors */
color: color(display-p3 34% 58% 73%);
}
?color-gamut:取值 srgb、p3 或 rec2020,對(duì)應(yīng)可判斷用戶設(shè)備是否支持sRGB、Display P3 或 REC2020色域。
@media(color-gamut: srgb){
/* safe to use srgb colors */
color: #4499bb;
}
@media(color-gamut: p3){
/* safe to use p3 colors */
color: color(display-p3 34% 58% 73%);
}
@media(color-gamut: rec2020){
/* safe to use rec2020 colors */
color: color(rec2020 34% 58% 73%);
}
除了可以直接使用css媒體查詢,還可用途JavaScript中的window.matchMedia()方法來(lái)進(jìn)行媒體查詢。
const hasHighDynamicRange = window.matchMedia('(dynamic-range: high)').matches;
console.log(hasHighDynamicRange);// true || false
const hasP3Color = window.matchMedia('(color-gamut: p3)').matches;
console.log(hasP3Color);// true || false
?使用@supports判斷某個(gè)css方法或?qū)傩允欠裰С?/span>
@supports(background:rgb(0 0 0)){
/* rgb color space supported */
background:rgb(0 0 0);
}
@supports(background:color(display-p3 0 0 0)){
/* display-p3 color space supported */
background:color(display-p3 0 0 0);
}
@supports(background:oklch(0 0 0)){
/* oklch color space supported */
background:oklch(0 0 0);
}
在實(shí)際應(yīng)用中,在新舊標(biāo)準(zhǔn)過(guò)渡期間,可以綜合使用上邊的查詢方法,下面是一個(gè)兼容新舊標(biāo)準(zhǔn)的實(shí)例:
:root{
--neon-red:rgb(100% 0 0);
--neon-blue:rgb(0 0 100%);
}
/* 設(shè)備是否支持展示高清 */
@media(dynamic-range: high){
/* 瀏覽器是否能解析display-p3 */
@supports(color:color(display-p3 0 0 0)){
/* 安全使用display-p3 */
--neon-red:color(display-p3 1 0 0);
--neon-blue:color(display-p3 0 0 1);
}
}
如果更新了最新版本的chrome瀏覽器的話,就能發(fā)現(xiàn)DevTools里的拾色器已經(jīng)支持了CSS Color 4中的新語(yǔ)法,點(diǎn)擊頁(yè)面元素中的顏色屬性,在彈出的拾色器中,中間色值右側(cè)的箭頭,之前的版本中,點(diǎn)擊箭頭是在hex、rgb、hsl和hwb之間切換,但新版本中,點(diǎn)擊箭頭會(huì)出現(xiàn)下拉框,可以看到所有新增的色彩空間和方法,以及當(dāng)前色值所對(duì)應(yīng)的可替換色值。
??同時(shí)在選擇了不同的色彩空間后,色彩的可調(diào)節(jié)參數(shù)也會(huì)相應(yīng)改變。
??當(dāng)我們選擇了一個(gè)非sRGB色域的色值后,會(huì)發(fā)現(xiàn)拾色器的上方區(qū)域里會(huì)展示一條sRGB的分界線,可以清晰地看出當(dāng)前選擇的顏色所在的色域。這能幫助開(kāi)發(fā)者分辨高清色與非高清色。
??而當(dāng)我們選擇一個(gè)超出sRGB范圍的顏色后,再來(lái)點(diǎn)擊色值右側(cè)的箭頭彈出選項(xiàng)列表時(shí),會(huì)發(fā)現(xiàn)sRGB色域下的色值后邊會(huì)帶上一個(gè)三角嘆號(hào)。這說(shuō)明當(dāng)前色值已超出了sRGB所能描述的范圍,只能使用相近的顏色作為替代。
??關(guān)于chrome DevTools更多關(guān)于高清顏色的更新,可參閱官方文檔。
sRGB之外的色域和色彩空間目前雖然還剛剛在web端起步,但未來(lái)的設(shè)計(jì)和開(kāi)發(fā)要求可能會(huì)慢慢出現(xiàn),尤其是H5動(dòng)畫、游戲、3D圖像等等,對(duì)于色彩顯示的要求不會(huì)永遠(yuǎn)停留在sRGB階段,希望本文簡(jiǎn)陋的介紹能讓大家多少開(kāi)始了解一些關(guān)于色彩的東西。如有錯(cuò)誤或疏漏,歡迎指正討論。
參考文章:
1. https://web.dev/articles/color-spaces-and-functions?hl=en
2. https://developer.chrome.com/articles/high-definition-css-color-guide/
3. https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color
作者:京東科技 鄭莉
來(lái)源:京東云開(kāi)發(fā)者社區(qū) 轉(zhuǎn)載請(qǐng)注明來(lái)源
在學(xué)習(xí)和工作中,我們經(jīng)常需要使用日志來(lái)記錄程序的運(yùn)行狀態(tài)和調(diào)試信息。而為了更好地區(qū)分不同的日志等級(jí),我們可以使用不同的顏色來(lái)呈現(xiàn),使其更加醒目和易于閱讀。
在下圖運(yùn)行結(jié)果中,我們使用了 colorlog 庫(kù)來(lái)實(shí)現(xiàn)彩色日志輸出。通過(guò)定義不同日志等級(jí)對(duì)應(yīng)的顏色,我們可以在控制臺(tái)中以彩色的方式顯示日志信息。例如,DEBUG 級(jí)別的日志使用白色,INFO 級(jí)別的日志使用綠色,WARNING 級(jí)別的日志使用黃色,ERROR 級(jí)別的日志使用紅色,CRITICAL 級(jí)別的日志使用藍(lán)色。
但是在查看日志文件時(shí),我們會(huì)發(fā)現(xiàn)日志信息是系統(tǒng)默認(rèn)的字體顏色,并且前后多了一些特殊符號(hào),例如 [32m 等。這是因?yàn)樵诳刂婆_(tái)中使用的是 ANSI 轉(zhuǎn)義序列來(lái)實(shí)現(xiàn)彩色文本效果,而這些特殊符號(hào)是 ANSI 轉(zhuǎn)義序列的一部分。如下圖所示:
現(xiàn)在有一個(gè)需求,在前端頁(yè)面直接查看日志內(nèi)容并還原彩色文本效果,因此,我們將進(jìn)行以下內(nèi)容講解:
本文代碼點(diǎn)擊此處跳轉(zhuǎn),往期系列文章請(qǐng)?jiān)L問(wèn)博主的 項(xiàng)目實(shí)戰(zhàn)專欄,博文中的所有代碼全部收集在博主的 GitHub 倉(cāng)庫(kù)中;
ANSI 轉(zhuǎn)義序列是美國(guó)國(guó)家標(biāo)準(zhǔn)化組織(American National Standards Institute,ANSI)制定的標(biāo)準(zhǔn),是一種用于控制文本終端顯示的特殊字符序列。它們以 3[ 開(kāi)頭,以字母和數(shù)字組合的形式表示不同的控制功能。
ANSI 轉(zhuǎn)義序列可以用于控制文本的顏色、背景色、文本樣式(如粗體、斜體等)、光標(biāo)位置、清屏等操作。通過(guò)在輸出文本中插入適當(dāng)?shù)?ANSI 轉(zhuǎn)義序列,可以實(shí)現(xiàn)豐富的終端顯示效果。
以下是一些常用的 ANSI 轉(zhuǎn)義序列示例:
需要注意的是,ANSI 轉(zhuǎn)義序列在不同的終端和操作系統(tǒng)上的支持程度可能會(huì)有所不同。在某些終端中,可能無(wú)法正確解釋和顯示 ANSI 轉(zhuǎn)義序列。
我們以 3[31m 和 3[42m 為例,輸出一個(gè)綠底紅字的句子 Hello World! --sidiot.,代碼如下所示:
log.debug("3[42m3[31mHello World! --sidiot.3[0m3[0m")
運(yùn)行結(jié)果:
這里的話,我們使用 Python 的 http.server 模塊來(lái)啟動(dòng)一個(gè)簡(jiǎn)單的 HTTP 服務(wù)器。
比較快捷的方式就是在日志文件夾中打開(kāi)終端,輸入 python -m http.server 8888 即可,運(yùn)行結(jié)果如下所示:
不過(guò)這種方式相對(duì)來(lái)說(shuō)還是不太安全的,因此我們可以通過(guò)設(shè)置白名單的方式,來(lái)規(guī)避一些潛在的安全隱患,代碼如下所示:
import http.server
import socketserver
class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def check_client_address(self):
# 設(shè)置白名單,只允許特定的IP地址或主機(jī)訪問(wèn)
whitelist = ['127.0.0.1', 'localhost']
client_address = self.client_address[0]
if client_address not in whitelist:
self.send_response(403)
self.end_headers()
self.wfile.write(b'Forbidden. Please contact sidiot.')
return False
return True
def do_GET(self):
if not self.check_client_address():
return
super().do_GET()
with socketserver.TCPServer(('0.0.0.0', 8888), HTTPRequestHandler) as httpd:
httpd.serve_forever()
目前本機(jī)的 IP 為 192.168.124.23,當(dāng)我們以 127.0.0.1 來(lái)訪問(wèn) 8888 服務(wù)端口時(shí),訪問(wèn)是成功的,但是當(dāng)我們用 192.168.124.23 來(lái)訪問(wèn)服務(wù)端口時(shí),訪問(wèn)是失敗的。
運(yùn)行結(jié)果:
現(xiàn)在我們點(diǎn)擊文件,它會(huì)直接通過(guò)瀏覽器直接下載,但是我們需要的是在網(wǎng)頁(yè)上能夠直接閱覽文件中的內(nèi)容,因此我們可以從 do_GET() 下手。
我們可以設(shè)計(jì)一個(gè)根據(jù)傳入的文件名參數(shù),讀取本地文件并作為響應(yīng)結(jié)果進(jìn)行返回的方法,然后根據(jù)一定的規(guī)則進(jìn)行觸發(fā),代碼如下所示:
def read_file(self):
try:
self.send_response(200)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.end_headers()
self.wfile.write(open(self.path[6:], 'rb').read())
except FileNotFoundError:
self.send_response(404)
self.end_headers()
self.wfile.write(b'File not found!')
def do_GET(self):
if self.check_client_address():
if self.path.startswith("/?log="):
self.read_file()
else:
super().do_GET()
上述代碼通過(guò)檢查請(qǐng)求的資源路徑來(lái)處理 GET 請(qǐng)求。如果請(qǐng)求的資源路徑前綴是 /?log=,且是當(dāng)前目錄下存在的日志文件,它會(huì)讀取文件并將其內(nèi)容作為響應(yīng)發(fā)送。否則,它會(huì)使用基類的默認(rèn)行為處理普通的 GET 請(qǐng)求。
運(yùn)行結(jié)果:
至此,我們已經(jīng)實(shí)現(xiàn)了前端頁(yè)面直接查看日志內(nèi)容的功能。
原理分析
當(dāng)我們想要在前端頁(yè)面展示 ANSI 字體的彩色效果時(shí),我們只需要簡(jiǎn)單地將 ANSI 轉(zhuǎn)義序列轉(zhuǎn)換成相應(yīng)的 HTML 代碼就可以實(shí)現(xiàn)了。這個(gè)轉(zhuǎn)換過(guò)程實(shí)際上可以通過(guò)編寫一個(gè) Python 函數(shù)來(lái)實(shí)現(xiàn),該函數(shù)可以接受包含 ANSI 控制碼的字符串作為輸入,并將其轉(zhuǎn)換為帶有相應(yīng)樣式的 HTML 代碼輸出,代碼如下所示:
def convert_ansi_to_html(ansi_text):
ansi_to_html = {
'\x1b[31m': '<span style="color: red;">',
'\x1b[42m': '<span style="background-color: green;">',
...,
}
html_text = re.sub(r'\x1b[[0-9;]*m', lambda match: ansi_to_html.get(match.group(0), ''), ansi_text)
return html_text
if __name__ == '__main__':
ansi = "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m"
print(ansi)
html = convert_ansi_to_html(ansi)
print(f"convert content: {html}")
需要注意的是,在 ANSI 轉(zhuǎn)義序列中,\x1b 和 3 都代 表ASCII 碼中的 Escape 字符,用于開(kāi)始一個(gè)轉(zhuǎn)義序列。
運(yùn)行結(jié)果:
使用 ansiconv 轉(zhuǎn)換
接下來(lái),我們借助已有的庫(kù)函數(shù) ansiconv 進(jìn)行 ANSI 的轉(zhuǎn)換。
通過(guò) pip 進(jìn)行安裝:
pip install ansiconv
根據(jù) ansiconv 的官方文檔使用其中的三個(gè)方法 to_plain(),to_html() 和 base_css() 來(lái)實(shí)現(xiàn)在前端頁(yè)面展示 ANSI 字體的彩色效果,代碼如下所示:
import ansiconv
ansi = "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m"
print(f"Ansi: {ansi}")
plain = ansiconv.to_plain(ansi)
html = ansiconv.to_html(ansi)
print(f"Convert Plain: {plain}")
print(f"Convert HTML: {html}")
在 base_css() 中會(huì)有相關(guān)的 CSS 映射表,如下所示:
css_rule('.ansi31', color="#FF0000"),
css_rule('.ansi42', background_color="#00FF00"),
運(yùn)行結(jié)果:
研究 ansiconv 源碼
我們將通過(guò)研究 ansiconv 的源碼,以便深入了解它是如何將 ANSI 轉(zhuǎn)換成純文本或 HTML 代碼的工作原理。
to_plain() 的源碼如下所示:
上述代碼使用正則表達(dá)式匹配字符串中的 ANSI 轉(zhuǎn)義序列,并將其替換為空字符串,從而得到不包含轉(zhuǎn)義序列的純文本。
正則表達(dá)式的含義如下:
我們通過(guò) re.findall() 方法來(lái)獲取所有匹配的結(jié)果,這樣夠清晰地捕獲所有符合條件的匹配項(xiàng),從而更好地理解 ansiconv 是如何進(jìn)行 ANSI 到純文本的轉(zhuǎn)換,代碼如下所示:
ansi = "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m"
print(re.findall(r'\x1B[[0-9;]*[ABCDEFGHJKSTfmnsulh]', ansi))
運(yùn)行結(jié)果:
to_html() 的源碼如下所示:
上述代碼將 ANSI 字符串分割成塊,并對(duì)每個(gè)塊調(diào)用 _block_to_html() 函數(shù)進(jìn)行解析和轉(zhuǎn)換,同時(shí)還處理了 ANSI 命令 "A",模擬向上移動(dòng)光標(biāo)的行為。如果 replace_newline 為 True,則 HTML 字符串中的換行符 \n 將替換為 <br />\n 以保留 HTML 輸出中的換行符。
其中 _block_to_html() 的源碼如下所示:
上述代碼使用正則表達(dá)式匹配 ANSI 代碼,并根據(jù)匹配結(jié)果生成對(duì)應(yīng)的 HTML 代碼。
正則表達(dá)式的含義:
我們可以通過(guò)運(yùn)行源碼里的部分代碼來(lái)幫助理解,代碼如下所示:
text = ("\x1B[0;32;45msidiot\n"
"\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m")
print(text)
blocks = text.split('\x1B')
print(blocks)
for block in blocks:
match = re.match(r'^[(?P<code>\d+(?:;\d+)*)?(?P<command>[Am])', block)
if match is not None:
print("\nmatch:", match, ", code:", match.group('code'), ", command:", match.group('command'))
運(yùn)行結(jié)果:
實(shí)際應(yīng)用
通過(guò)深入理解 ANSI 轉(zhuǎn)換思路和 ansiconv 源碼,我們可以為之前的 http.server 服務(wù)帶來(lái)全新的優(yōu)化。
首先,將原先的 read_file() 方法進(jìn)行優(yōu)化,代碼如下所示:
def read_file(self, content_type, file_io):
try:
self.send_response(200)
self.send_header("Content-Type", f"{content_type}; charset=utf-8")
self.end_headers()
self.wfile.write(file_io)
except FileNotFoundError:
self.send_response(404)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.end_headers()
self.wfile.write(b'File not found!')
上述代碼通過(guò)接收 content_type 和 file_io 兩個(gè)參數(shù),實(shí)現(xiàn)將自定義內(nèi)容作為響應(yīng)返回給客戶端。
然后修改請(qǐng)求路徑,使其能夠返回純文本和 HTML 兩種不同類型的內(nèi)容,代碼如下所示:
def do_GET(self):
if self.check_client_address():
if self.path.startswith("/?plain="):
file = open(self.path[8:], 'rb').read()
plain = ansiconv.to_plain(file.decode('UTF-8'))
self.read_file("text/plain", plain.encode())
elif self.path.startswith("/?html="):
file = open(self.path[7:], 'rb').read()
conv = ansiconv.to_html(file.decode('UTF-8'))
css = ansiconv.base_css()
html = """
<html>
<head><style>{0}</style></head>
<body>
<pre class="ansi_fore ansi_back">{1}</pre>
</body>
</html>
""".format(css, conv)
print(html)
self.read_file("text/html", html.encode())
else:
super().do_GET()
這里要注意的是,需要設(shè)置 CSS 樣式,不然 class 類是無(wú)法進(jìn)行渲染的。
純文本運(yùn)行結(jié)果:
HTML 運(yùn)行結(jié)果:
在本文中,我們探討了如何實(shí)現(xiàn)將 ANSI 字體在前端頁(yè)面進(jìn)行彩色展示的方法。在前端頁(yè)面中直接顯示 ANSI 轉(zhuǎn)義序列是不起作用的,因?yàn)闉g覽器不會(huì)解析和處理這些轉(zhuǎn)義序列。
為了在前端頁(yè)面實(shí)現(xiàn)彩色展示,我們介紹了一種方法,即將 ANSI 轉(zhuǎn)義序列轉(zhuǎn)換為對(duì)應(yīng)的 HTML 代碼。通過(guò)解析 ANSI 轉(zhuǎn)義序列并將其轉(zhuǎn)換為適當(dāng)?shù)?HTML 標(biāo)簽和樣式,我們可以在前端頁(yè)面上還原彩色文本的效果。
在本文中,我們使用了 Python 中的 ansiconv 庫(kù)來(lái)實(shí)現(xiàn) ANSI 轉(zhuǎn)換。該庫(kù)提供了 to_plain 和 to_html 兩個(gè)方法,分別用于將 ANSI 轉(zhuǎn)義序列轉(zhuǎn)換為純文本和 HTML 代碼。我們還展示了如何使用這些方法來(lái)轉(zhuǎn)換 ANSI 字符串,并在前端頁(yè)面上顯示轉(zhuǎn)換后的結(jié)果。
通過(guò)本文的介紹,讀者可以了解到如何在前端頁(yè)面實(shí)現(xiàn)彩色文本的展示,從而提升用戶體驗(yàn)和可讀性。無(wú)論是在日志查看器、終端模擬器還是其他需要展示彩色文本的應(yīng)用中,這種技術(shù)都能發(fā)揮重要作用。
以上就是 從終端到瀏覽器:實(shí)現(xiàn) ANSI 字體在前端頁(yè)面的彩色展示 的所有內(nèi)容了,希望本篇博文對(duì)大家有所幫助!歡迎大家持續(xù)關(guān)注我的博客,一起分享學(xué)習(xí)和成長(zhǎng)的樂(lè)趣!?
作者:sidiot
鏈接:https://juejin.cn/post/7381820436274184202
reamweaver的CSS面板分類
type(類型)
background(背景)
block(區(qū)塊)
box(方框) 或盒子意思
border(邊框)
list(列表)
positioning(定位)
extensions(擴(kuò)展)
共八個(gè)部分
1. type(類型)
type面板主要是對(duì)文字的字體,大小,顏色,效果等基本樣式進(jìn)行設(shè)置。
注意:屬性名帶*號(hào)的是指樣式效果不能在編輯文檔時(shí)顯示,要用瀏覽器打開(kāi)才能看到效果。
(1)font-family:設(shè)置字體系列。什么叫字體系列呢?是指對(duì)文字設(shè)定幾個(gè)字體,當(dāng)遇到第一個(gè)字體不能顯示的文字時(shí)會(huì)自動(dòng)用系列中的第二個(gè)
字體或后面的字體顯示。
注意:一般英文字體我們用"Verdana, Arial, Helvetica, sans-serif"這個(gè)系列比較好看。如果不用這些字體系列,你就需要自己編輯字體系列,
也可以直接手動(dòng)在下拉框里寫字體名,字體之間用逗號(hào)隔開(kāi)。中文網(wǎng)頁(yè)默認(rèn)字體是宋體, 一般就空著不要選取任何字體。
默認(rèn)值: not specified(取決于瀏覽器,系統(tǒng)默認(rèn)的字體, 如: 微軟雅黑)
注意:
1.如果有漢字, 那么我們要加引號(hào)
2.如果有多個(gè)英文字母組成的單詞, 我們也要加引號(hào); "microsoft yahei" 中間用空格隔開(kāi)
3.font-family:"黑體","宋體","華文隸書"; 首先找黑體, 沒(méi)有黑體找宋體...
為了避免在CSS中使用 font 或 font-family 設(shè)置中文字體時(shí)亂碼, 可以使用 Unicode 編碼來(lái)表示字體。
/* 示例:使用Unicode字體編碼設(shè)置字體為"微軟雅黑" */
font-family: "\5FAE\8F6F\96C5\9ED1";
(2)font-size:定義文字的大小。你可以通過(guò)選取數(shù)字和度量單位來(lái)選擇具體的字體大小,或者你也可以選擇一個(gè)相對(duì)的字體大小。
最好使用pixels作為單位,這樣不會(huì)在瀏覽器中文本變形。一般字體用比較標(biāo)準(zhǔn)的12px或14px, 默認(rèn)值為16px。
注意:CSS中長(zhǎng)度的單位分絕對(duì)長(zhǎng)度單位和相對(duì)長(zhǎng)度單位:
絕對(duì)長(zhǎng)度單位有:
pt:磅(point)
mm、cn、in、pc:(毫米、厘米、英寸、活字)根據(jù)顯示的實(shí)際尺寸來(lái)確定長(zhǎng)度。
此類單位不隨顯示器的分辨率改變而改變。
相對(duì)長(zhǎng)度單位有:
px:(像素)根據(jù)顯示器的分辨率來(lái)確定長(zhǎng)度。
em:當(dāng)前文本的尺寸。例如:{font-size:2em}是指文字大小為原來(lái)的2倍。
比如自身font-size: 30px; 那么此時(shí)1em=30px;
ex:當(dāng)前字母"x"的高度,一般為字體尺寸的一半。
%:是以當(dāng)前文本的百分比定義尺寸。例如:{ font-size:300%}是指文字大小為原來(lái)的3倍。
small、large:表示比當(dāng)前小一個(gè)級(jí)別或大一個(gè)級(jí)別的尺寸。
默認(rèn)值:medium(標(biāo)準(zhǔn)大小)
(3)font-style:定義字體樣式為normal、italic、oblique。默認(rèn)設(shè)置為normal。
注意: italic 斜體 oblique 歪斜體 italic和oblique實(shí)際效果是一樣的。
默認(rèn)值:normal
(4)line-height:設(shè)置文本所在行的行高。默認(rèn)為normal。可以是行內(nèi)元素、行內(nèi)塊元素, 通常與height設(shè)置的高度值相同, 可以做到垂直居中的作用。
你也可以自己鍵入一個(gè)精確的數(shù)值并選取一個(gè)計(jì)量單位。
比較直觀的寫法用百分比, 例如140%是指行高等于文字大小的1.4倍。
最常用的方法: line-height:1.5em; /*行間距,相對(duì)數(shù)值,1.5倍行距,*/ 可有效的避免文字發(fā)生重疊
默認(rèn)值: normal
(5)text-decoration:在文本中添加underline(下劃線)、overline(上劃線)、line-through(中劃線)、blink(閃爍效果)。
這些效果可以同時(shí)存在,將效果前的復(fù)選框選定即可。
注意:鏈接的默認(rèn)設(shè)置是underline,我們可以通過(guò)選none去除下劃線。blink(閃爍效果)只在mozilla瀏覽器里可以看到, IE、opera不支持
默認(rèn)值: none
(6)font-weight:給字體指定粗體字的磅值。
normal 默認(rèn)值。定義標(biāo)準(zhǔn)的字符。
bold 定義粗體字符。
bolder 定義更粗的字符。
lighter 定義更細(xì)的字符。
100
200
300
400
500
600
700
800
900
inherit 規(guī)定應(yīng)該從父元素繼承字體的粗細(xì)。
定義由粗到細(xì)的字符。400 等同于 normal, 而 700 等同于 bold。
默認(rèn)值: normal
(7)font-variant:允許你選取字體的變種, 選small-caps(小型大寫字母)時(shí), 此樣式區(qū)域內(nèi)所有字母大寫。
normal表示正常的字體, 為默認(rèn)值;
默認(rèn)值: normal
(8)text-transform:將選區(qū)中每個(gè)單詞的第一個(gè)字母轉(zhuǎn)為大寫, 或者令單詞全部大寫或全部小寫。
參數(shù):capitalize(單詞首字母大寫)、uppercase(轉(zhuǎn)換成大寫)、lowercase(轉(zhuǎn)換成小寫)、none(不轉(zhuǎn)換)。
默認(rèn)值:none
(9)color:定義文字顏色。包括對(duì)表單輸入的文字顏色。
CSS中顏色的值有三種表示方法:
#RRGGBB格式,是由紅綠藍(lán)三種顏色的值組合,每種顏色的值為"00 – FF"的兩位十六進(jìn)制正整數(shù)。
例如:#FF0000表示紅色,#FFFF00表示黃色。
rgb(R,G,B)格式, RGB為三色的值, 取0~255, 例如:rgb(255,0,0)表示紅色, rgb(255,255,0)表示黃色。
用顏色名稱。CSS可以使用已經(jīng)定義好的顏色名稱。例如:red表示紅色, yellow表示黃色。
顏色值的縮寫:
p{color:#000000} 可以縮寫為:p{color:#000}
p{color:#336699} 可以縮寫為:p{color:#369}
默認(rèn)值: not specified
color: transparent; 透明色
rgba() 解釋: rgba(紅0-255, 綠0-255, 藍(lán)0-255, 透明度0-1)
注意: 如果文字的顏色通過(guò)單獨(dú)的類選擇去設(shè)置沒(méi)有改變顏色, 則應(yīng)該通過(guò)組合選擇器(.header .top .topR .blue)去設(shè)置, 改變它的優(yōu)先級(jí)。
2. background(背景)
background面板主要是對(duì)元素的背景進(jìn)行設(shè)置,包括背景顏色、背景圖象、背景圖象的控制。
一般是對(duì)body(頁(yè)面)、table(表格)、div(區(qū)域)的設(shè)置。
(1)background-color:設(shè)置元素的背景色。包括對(duì)input表單輸入框的背景顏色;
默認(rèn)值: transparent(背景顏色為透明)
rgba() 解釋: rgba(紅0-255, 綠0-255, 藍(lán)0-255, 透明度0-1) 一般用于背景色
(2)background-image:設(shè)置元素的背景圖像。
默認(rèn)值:none
CSS3支持多重背景圖,只要加上一個(gè)url指定圖片路徑,并用逗號(hào)(,)將兩組url分隔就可以了
background-image:url(a.jpg),url(b.jpg);
base64使用
background-image: url("data:image/png;base64,iVBORw0KGgo=...");
(3)background-repeat:確定背景圖像是否以及如何重復(fù)。
repeat 默認(rèn)值。背景圖像將在垂直方向和水平方向重復(fù)。
repeat-x 背景圖像將在水平方向重復(fù)。
repeat-y 背景圖像將在垂直方向重復(fù)。
no-repeat 背景圖像將僅顯示一次。
inherit 規(guī)定應(yīng)該從父元素繼承background-repeat屬性的設(shè)置。
注意:如果定義的元素的body,可以控制頁(yè)面背景是否重復(fù)。
默認(rèn)值: repeat
(4)background-attachment:固定背景圖像或者跟隨內(nèi)容滾動(dòng)。
參數(shù)fixed表示固定背景(不隨屏幕滾動(dòng)而滾動(dòng),決定背景圖像是否要固定在原來(lái)的位置), scroll表示跟隨內(nèi)容滾動(dòng)的背景。
注意:如果定義的元素的body, 可以使頁(yè)面背景固定。
默認(rèn)值: scroll
(5)background-position(X):指定背景圖像的水平位置。
可以指定為left(左邊), center(居中),right(右邊);
也可以指定數(shù)值,如20px是指背景距離左邊20象素。
background-position(Y):指定背景圖像的垂直位置。
可以指定為top(頂部), center(居中), bottom(底部);也可以指定數(shù)值。
background-position屬性值:
left top
center top
right top
left center
center center
right center
left bottom
center bottom
right bottom
如果您僅規(guī)定了一個(gè)關(guān)鍵詞,那么第二個(gè)值將是"center"。
注意:采用英文單詞的水平位置和垂直位置的屬性值可以調(diào)換
x% y% 第一個(gè)值是水平位置,第二個(gè)值是垂直位置。左上角是 0% 0%。右下角是 100% 100%。如果您僅規(guī)定了一個(gè)值,另一個(gè)值將是 50%。
xpos ypos 第一個(gè)值是水平位置,第二個(gè)值是垂直位置。左上角是 0 0。單位是像素 (0px 0px) 或任何其他的 CSS 單位。
如果您僅規(guī)定了一個(gè)值,另一個(gè)值將是50%。
您可以混合使用 % 和 position 值。
默認(rèn)值:0% 0%
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。