您好,登錄后才能下訂單哦!
這篇文章主要介紹“Highcharts圖表中圖例顯示狀態存儲的功能怎么設計”,在日常操作中,相信很多人在Highcharts圖表中圖例顯示狀態存儲的功能怎么設計問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Highcharts圖表中圖例顯示狀態存儲的功能怎么設計”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
公司前端使用 Highcharts 構建圖表,圖表的圖例支持點擊顯示或隱藏相應的指標。現在有需求后端需要存儲用戶在前端點擊后顯示圖表的狀態,對于已經隱藏的圖例相應的指標線下次進入頁面后依然隱藏。
這樣做的目的是簡化圖表信息和去除噪音,有些信息對于某些用戶來說是不太關心的,用戶取消顯示它們是合理的。
使用數據庫枚舉值,將圖表的存儲狀態枚舉。這是一種實現上比較簡單的方案,但是其組合較多,圖例越多所需要添加的枚舉值就越多,原本的圖表狀態中有兩個圖例可以進行此操作,因此使用了這種方案。
現在需要將這個功能擴展到 4 個圖表,未來又可能擴展到更多圖表,所以這種簡單的方案已經不適用了。
使用一個數據庫 JSON 類型字段存儲圖例的是否顯示的狀態,其結構類似下面這樣:
{ "chart_1":{ "legend_1":true, "legend_2":true, "legend_3":true, "legend_4":true, "legend_5":true, "legend_6":true, "legend_7":false, "legend_8":false }, "chart_2":{ "legend_1":true, "legend_2":true, "legend_3":true, "legend_4":true, "legend_5":true }, "chart_3":{ "legend_1":true, "legend_2":true, "legend_3":true, "legend_4":true }, "chart_3":{ "legend_1":true, "legend_2":true, "legend_3":true, "legend_4":true, "legend_5":true, "legend_6":true, "legend_7":true } }
這樣使用一個字段將所有圖表的圖例狀態都在一個地方維護,而且避免了過多枚舉值的問題。但在實際項目中因為每個用戶都有這樣一個值需要在數據庫中維護,所以它會占用大量的數據庫存儲空間,在工程質量和未來成本控制上與工程目標不符。
對方案二進行改進,存儲給每個圖表存儲一個 int 值,實際這個 int 值可以在代碼中轉換成二進制,用每個二進制值位的 0 和 1 來標示圖例是否該顯示。其存儲結構如下:
{ "chart_1": 15, "chart_2": 31, "chart_3": 127, "chart_3": 252 }
同時對于大部分用戶而言很可能是不會對默認圖表做出更改,那么我們可以在代碼中維護一個默認值,當數據庫中相應值與默認值一致時,無需實際存儲到數據庫中,在用戶獲取信息時直接返回默認值即可。
后端使用的是 PHP 的 Laravel 框架,首先在相應的 Model 里我新增了一些類似下面的常量:
public const BITMAP_INDEXES_BY_LEGEND_IDENTIFIER_BY_CHART_NAME = [ 'chart_1' => [ 'legend_1' => 7, 'legend_2' => 6, 'legend_3' => 5, 'legend_4' => 4, 'legend_5' => 3, 'legend_6' => 2, 'legend_7' => 1, 'legend_8' => 0, ], 'chart_2' => [ 'legend_1' => 3, 'legend_2' => 2, 'legend_3' => 1, 'legend_4' => 0, ], 'chart_3' => [ 'legend_1' => 6, 'legend_2' => 5, 'legend_3' => 4, 'legend_4' => 3, 'legend_5' => 2, 'legend_6' => 1, 'legend_7' => 0, ], 'chart_4' => [ 'legend_1' => 4, 'legend_2' => 3, 'legend_3' => 2, 'legend_4' => 1, 'legend_5' => 0, ], ]; // Each bit of a bitmap is like a bucket, which stores the displayed or hidden state. public const DEFAULT_CHART_LEGEND_VISIBILITIES = [ 'chart_1' => 0b1111, 'chart_2' => 0b11111, 'chart_3' => 0b1111111, 'chart_4' => 0b11111100, ];
BITMAP_INDEXES_BY_LEGEND_IDENTIFIER_BY_CHART_NAME 維護的是每個圖例在 bitmap 中的存儲位置,這樣在圖例增加時只需維護相應的 chart 的存儲位置即可,不會影響到其他圖表的圖例存儲。
DEFAULT_CHART_LEGEND_VISIBILITIES 定義了圖例的默認值,當用戶未做更改時可以直接返回其值,在存儲時可進行比對,如果值一致就不存儲到數據庫里了。
在定義完這兩個常量后,需要做的就是對存儲和獲取的過程給予相應的處理,Laravel 的 Model 提供了訪問器和設置器的功能,我可以利用這個機制對值進行處理,因此我在 model 里新增了以下方法:
/** * @return array<string,array<string,bool>> */ public function getChartLegendVisibilitiesAttribute(?string $value): array { $value = $value !== null ? \Safe\json_decode($value, true) : []; $value += self::DEFAULT_CHART_LEGEND_VISIBILITIES; $chart_legend_visibilities = []; /** @var string $chart_name */ foreach ($value as $chart_name => $legend_visibilities_bitmap) { foreach (self::BITMAP_INDEXES_BY_LEGEND_IDENTIFIER_BY_CHART_NAME[$chart_name] as $legend_identifier => $bitmap_index) { $chart_legend_visibilities[$chart_name][$legend_identifier] = (bool) (($legend_visibilities_bitmap >> $bitmap_index) & 1); } } ksort($chart_legend_visibilities); return $chart_legend_visibilities; } /** * @param array<string,array<string,bool>>|null $value * * @return void */ public function setChartLegendVisibilitiesAttribute(?array $value): void { if ($value !== null) { $chart_legend_visibilities = []; foreach ($value as $chart_name => $legend_visibilities) { $legend_visibilities_bitmap = 0; foreach ($legend_visibilities as $legend_identifier => $legend_visibility) { $bitmap_index = self::BITMAP_INDEXES_BY_LEGEND_IDENTIFIER_BY_CHART_NAME[$chart_name][$legend_identifier]; $legend_visibilities_bitmap |= ($legend_visibility & true) << $bitmap_index; } if ($legend_visibilities_bitmap !== self::DEFAULT_CHART_LEGEND_VISIBILITIES[$chart_name]) { $chart_legend_visibilities[$chart_name] = $legend_visibilities_bitmap; } } $value = $chart_legend_visibilities === [] ? null : \Safe\json_encode($chart_legend_visibilities); } $this->attributes[self::COLUMN_CHART_LEGEND_VISIBILITIES] = $value; }
這樣我所要實現的功能基本在這里完成了。現在所要做的就是在控制器里對返回的圖表數據的狀態進行綁定:
/** * @param array<string,array<int|string,mixed>> $chart_data * @param \App\Models\UserExtra $user_extra * @param string $chart_name * * @return array<string,array<int|string,mixed>> */ private static function getChartLegendVisibility(array $chart_data, UserExtra $user_extra, string $chart_name): array { $legend_label_id_by_store_index = array_flip(UserExtra::BITMAP_INDEXES_BY_LEGEND_IDENTIFIER_BY_CHART_NAME[$chart_name]); $legend_visibilities = $user_extra->chart_legend_visibilities[$chart_name]; foreach ($chart_data['series'] as $series_index => $series) { $key = array_shift($legend_label_id_by_store_index); $chart_data['series'][$series_index]['id'] = $key; $chart_data['series'][$series_index]['visible'] = $legend_visibilities[$key]; } return $chart_data; }
$chart_data 傳遞的是構建好的 Highcharts 需要的數據,這部分可以參考 Highcharts 的文檔。這個函數的目的就是將每個圖例的數據與我們所維護的圖例是否顯示的數據綁定,之后再提供修改圖例顯示狀態的 API 即可實現這個功能。
到此,關于“Highcharts圖表中圖例顯示狀態存儲的功能怎么設計”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。