溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Highcharts圖表中圖例顯示狀態(tài)存儲(chǔ)的功能怎么設(shè)計(jì)

發(fā)布時(shí)間:2023-03-14 10:31:53 來源:億速云 閱讀:101 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Highcharts圖表中圖例顯示狀態(tài)存儲(chǔ)的功能怎么設(shè)計(jì)”,在日常操作中,相信很多人在Highcharts圖表中圖例顯示狀態(tài)存儲(chǔ)的功能怎么設(shè)計(jì)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”Highcharts圖表中圖例顯示狀態(tài)存儲(chǔ)的功能怎么設(shè)計(jì)”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

    需求背景

    公司前端使用 Highcharts 構(gòu)建圖表,圖表的圖例支持點(diǎn)擊顯示或隱藏相應(yīng)的指標(biāo)?,F(xiàn)在有需求后端需要存儲(chǔ)用戶在前端點(diǎn)擊后顯示圖表的狀態(tài),對(duì)于已經(jīng)隱藏的圖例相應(yīng)的指標(biāo)線下次進(jìn)入頁面后依然隱藏。

    這樣做的目的是簡化圖表信息和去除噪音,有些信息對(duì)于某些用戶來說是不太關(guān)心的,用戶取消顯示它們是合理的。

    需求方案

    方案一

    使用數(shù)據(jù)庫枚舉值,將圖表的存儲(chǔ)狀態(tài)枚舉。這是一種實(shí)現(xiàn)上比較簡單的方案,但是其組合較多,圖例越多所需要添加的枚舉值就越多,原本的圖表狀態(tài)中有兩個(gè)圖例可以進(jìn)行此操作,因此使用了這種方案。

    現(xiàn)在需要將這個(gè)功能擴(kuò)展到 4 個(gè)圖表,未來又可能擴(kuò)展到更多圖表,所以這種簡單的方案已經(jīng)不適用了。

    方案二

    使用一個(gè)數(shù)據(jù)庫 JSON 類型字段存儲(chǔ)圖例的是否顯示的狀態(tài),其結(jié)構(gòu)類似下面這樣:

    {
    "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
    }
    }

    這樣使用一個(gè)字段將所有圖表的圖例狀態(tài)都在一個(gè)地方維護(hù),而且避免了過多枚舉值的問題。但在實(shí)際項(xiàng)目中因?yàn)槊總€(gè)用戶都有這樣一個(gè)值需要在數(shù)據(jù)庫中維護(hù),所以它會(huì)占用大量的數(shù)據(jù)庫存儲(chǔ)空間,在工程質(zhì)量和未來成本控制上與工程目標(biāo)不符。

    方案三

    對(duì)方案二進(jìn)行改進(jìn),存儲(chǔ)給每個(gè)圖表存儲(chǔ)一個(gè) int 值,實(shí)際這個(gè) int 值可以在代碼中轉(zhuǎn)換成二進(jìn)制,用每個(gè)二進(jìn)制值位的 0 和 1 來標(biāo)示圖例是否該顯示。其存儲(chǔ)結(jié)構(gòu)如下:

    {
    "chart_1": 15,
    "chart_2": 31,
    "chart_3": 127,
    "chart_3": 252
    }

    同時(shí)對(duì)于大部分用戶而言很可能是不會(huì)對(duì)默認(rèn)圖表做出更改,那么我們可以在代碼中維護(hù)一個(gè)默認(rèn)值,當(dāng)數(shù)據(jù)庫中相應(yīng)值與默認(rèn)值一致時(shí),無需實(shí)際存儲(chǔ)到數(shù)據(jù)庫中,在用戶獲取信息時(shí)直接返回默認(rèn)值即可。

    代碼實(shí)現(xiàn)

    后端使用的是 PHP 的 Laravel 框架,首先在相應(yīng)的 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 維護(hù)的是每個(gè)圖例在 bitmap 中的存儲(chǔ)位置,這樣在圖例增加時(shí)只需維護(hù)相應(yīng)的 chart 的存儲(chǔ)位置即可,不會(huì)影響到其他圖表的圖例存儲(chǔ)。

    DEFAULT_CHART_LEGEND_VISIBILITIES 定義了圖例的默認(rèn)值,當(dāng)用戶未做更改時(shí)可以直接返回其值,在存儲(chǔ)時(shí)可進(jìn)行比對(duì),如果值一致就不存儲(chǔ)到數(shù)據(jù)庫里了。

    在定義完這兩個(gè)常量后,需要做的就是對(duì)存儲(chǔ)和獲取的過程給予相應(yīng)的處理,Laravel 的 Model 提供了訪問器和設(shè)置器的功能,我可以利用這個(gè)機(jī)制對(duì)值進(jìn)行處理,因此我在 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;
    }

    這樣我所要實(shí)現(xiàn)的功能基本在這里完成了?,F(xiàn)在所要做的就是在控制器里對(duì)返回的圖表數(shù)據(jù)的狀態(tài)進(jìn)行綁定:

    /**
    * @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 傳遞的是構(gòu)建好的 Highcharts 需要的數(shù)據(jù),這部分可以參考 Highcharts 的文檔。這個(gè)函數(shù)的目的就是將每個(gè)圖例的數(shù)據(jù)與我們所維護(hù)的圖例是否顯示的數(shù)據(jù)綁定,之后再提供修改圖例顯示狀態(tài)的 API 即可實(shí)現(xiàn)這個(gè)功能。

    到此,關(guān)于“Highcharts圖表中圖例顯示狀態(tài)存儲(chǔ)的功能怎么設(shè)計(jì)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI