項目中有需求爲highcharts的分組堆疊柱圖配置漸變色,該類柱圖原始的實現是隨機色的,那麼配置爲漸變色就須要咱們調用highchart的配色api寫入咱們計算好的漸變色的顏色編碼前端
具體實現能夠將問題抽象成 爲一個二維數組配置漸變色,初步想一想差很少就是顏色代碼0~255之間累加就能夠了,後來發現不是這麼回事。 那咱們來仔細看看這個問題。編程
首先咱們來抽象一下問題。json
有二維數組a,假設爲 m * n 維度:
a = [
[{value:1,color:null}, {value:2,color:null}, ····n個····, {value:3,color:null}],
·
·
m個
·
·
[{value:7,color:null}, {value:8,color:null}, ····n個····, {value:9,color:null}],
]
咱們的任務就是把m個一級維度設計爲一個大色系,其中每一個裏面的n個二級維度設計爲由淺至深的漸變色。 據此設計需求將相應的顏色代碼值填充到每一個json對象的color屬性中。api
ok問題明確,咱們來了解一下相關的顏色代碼知識。 通常網頁設計中顏色代碼經常使用表示方法有:數組
#667788, #333, RGB(0.2,0.4,0.5), rgb(100%,0%,0%), 文字"紅色"
可是這些代碼都是RGB顏色模型的,它們是經過對紅(R)、綠(G)、藍(B)三個顏色通道的變化以及它們相互之間的疊加來獲得各式各樣的顏色 RGB數學模型以下:
瀏覽器
直觀的就能發現,這個顏色模型沒有選項來解決漸變色的問題,深刻一下還會發現這個模型不能進行可編程式的顏色劃分。 亦即咱們不能簡單的在RGB三個通道上等值累加來得到不一樣的顏色紅橙黃等等系列或實現指定色系的顏色漸變。 這麼作咱們得到的僅僅是不一樣程度的灰色。 如#333,#666,#999是逐漸變淺的灰色, 而這些顏色也是通常前端人員惟一記住的顏色代碼 :)編碼
通過一番資料搜尋,終於發現一個HSV模型,
spa
這是一個六角錐體模型,這個模型中顏色的參數分別表明了:色調(H),飽和度(S),亮度(V)。設計
ok,找到一個合適的模型後,咱們就方便編程實現了。 咱們能夠以下設計: 在H參數的360度範圍內步進來實現顏色系的切換,在S參數的0 ~ 100%範圍內實現顏色漸變,V參數在0 ~ 100% 範圍內咱們就取值一個合適的固定值80%吧。 在瞭解了這些以後,剩下的問題就只剩下數學模型間的轉換了,也就是把得到的HSV對象轉換爲瀏覽器可識別的RGB對象就完成了。 ok, 針對這個抽象好的問題上代碼。code
/*************************************//**** start to fill in color code ****//*************************************///raw data without color code, Dimension: m*nvar rawData = [ [{value:1,color:null}, {value:2,color:null}, ····n個····, {value:3,color:null}], · · m個 · · [{value:7,color:null}, {value:8,color:null}, ····n個····, {value:9,color:null}], ];var dataWithColor = [];var sediaoStep = Math.round(360 / m); //caculate the step value for sediao, var jianbianStep = Math.round(100 / n); //caculate the step value for jianbian,var sediao = 0;rawData.forEach(function(item, index){ var jianbian = 0; //every time we switch the color, we init the jianbian with zero sediao += sediaoStep; //switch the color item.forEach(function(one){ jianbian += jianbianStep; //switch the jianbian var hsv = { h: sediao, s: jianbian, v: 80, }; var color = HSV_To_RGB(hsv); dataWithColor[index] || dataWithColor.push( [] ); //judge if the index item is exist in dataWithColor, if not ,push in on empty array dataWithColor[index].push({ value: one.value, color: color, }); });});//Convert HSV obj like {h:195, s:70, v:60} to RGB object like {r:220, g:160, b:80}//@param {object} HSV The param strcture is {h:*, s:*, v:*} H:指定色調 S:指定飽和度,用於顏色漸變 V:指定亮度//@return {object} The return object strcture is like {r:null, g:null, b:null}function HSV_To_RGB(HSV){ var result = { r: 0, g: 0, b: 0 }; var h = HSV.h / 360; var s = HSV.s / 100; var v = HSV.v / 100; if (s == 0) { result.r = v * 255; result.g = v * 255; result.v = v * 255; } else { var_h = h * 6; var_i = Math.floor(var_h); var_1 = v * (1 - s); var_2 = v * (1 - s * (var_h - var_i)); var_3 = v * (1 - s * (1 - (var_h - var_i))); if (var_i == 0) { var_r = v; var_g = var_3; var_b = var_1 } else if (var_i == 1) { var_r = var_2; var_g = v; var_b = var_1 } else if (var_i == 2) { var_r = var_1; var_g = v; var_b = var_3 } else if (var_i == 3) { var_r = var_1; var_g = var_2; var_b = v } else if (var_i == 4) { var_r = var_3; var_g = var_1; var_b = v } else { var_r = v; var_g = var_1; var_b = var_2 }; result.r = var_r * 255; result.g = var_g * 255; result.b = var_b * 255; result.r = Math.round(result.r); result.g = Math.round(result.g); result.b = Math.round(result.b); } return RGB_To_Color(result);},//Convert the RGB Object like {r:220, g:160, b:80} to "#768844"//@param {object} obj The RGB object//@return {string} The return color stringfunction RGB_To_Color(obj){ obj.r = Math.round(obj.r); obj.g = Math.round(obj.g); obj.b = Math.round(obj.b); var color = '#'; color += (obj.r < 16 ? '0' : '') + obj.r.toString(16); color += (obj.g < 16 ? '0' : '') + obj.g.toString(16); color += (obj.b < 16 ? '0' : '') + obj.b.toString(16); return color;},/******************************//**** end to fill in color ****//******************************/