ECharts繪圖解決方案——四象限散點圖

需求場景

用品牌持機量和品牌凈流入量兩個維度來幫助運營分析所選品牌的競爭能力健康度舟舒。

  • 競爭能力健康度:判斷品牌具備正向競爭能力付材,還是處于危險狀態(tài)肛循。
  • 維度呈現
    橫坐標:品牌持機量,中心點為取所有11個品牌持機量的中位數(注:一期為取“平均數”)峭咒;
    縱坐標:品牌凈流入量=本月流入量-本月流出量烹卒,中心點為0狱掂,即向上為凈流入量增加穆刻,向下為凈流入量減少;
    四個象限:分別表示“上升品牌”消约、“潛力品牌”肠鲫、“高危品牌”、“下滑品牌”或粮。

最終實現效果如下圖所示:
品牌健康度分析最終效果圖

需求拆解(從實現的角度)

  • 確定使用的基本圖表類型及數據格式:以散點圖為基礎导饲;每個散點的數據對應一個(品牌)名稱和(坐標)值。
  • 四象限劃分:確定橫氯材、縱軸的分割臨界點渣锦。
  • 確定散點的樣式、交互效果:每個散點大小一致氢哮;處于不同象限的散點使用指定不同顏色區(qū)分(此時注意考慮散點處于臨界點的情況)袋毙;散點上顯示名稱,hover時顯示對應維度值信息冗尤。
  • 使用圖例展示對應象限表示的含義听盖。

問題及解決方案

  • 后續(xù)示例基于以下模擬數據做調整:
    let data = [
      {
        name: '三星',
        value: [10.0, -6.04],
      },
      {
        name: '一加',
        value: [8.0, 1.95],
      },
      {
        name: '華為',
        value: [12.0, 7.58],
      },
      {
        name: '蘋果',
        value: [15.0, -7.81],
      }
    ]
    

問題一:四象限的劃分,用ECharts原生提供的xAxis裂七、yAxis屬性無法做到皆看。

因為x軸、y軸的位置是不可按具體值靈活控制的碍讯。
例如y軸在左側時,如果x軸上的最小值<=0扯躺,則y軸位于x=0上捉兴;否則按xAxis.min的設定規(guī)則(即坐標軸刻度最小值,不設置時會自動計算最小值保證坐標軸刻度的均勻分布)計算录语。
幾種情況的效果示例如下圖所示:

x軸上的最小值<=0時

x軸上的值均大于0倍啥,且無設置xAxis.min時
x軸上的值均大于0,且設置了xAxis.min時

  • 思路:利用其它屬性來模擬軸澎埠?
  • 方案:由于markLine屬性的位置完全可控虽缕,可使用markLine模擬劃分象限的軸。參考文檔series-scatter.markLine.data中笛卡爾坐標系的相關配置說明蒲稳。
  • 相關代碼片段:
    const median = 11.0 // 實際值由后臺計算給出氮趋,為固定值
    /* 隱藏默認的x軸和y軸 */
    xAxis: {
      show: false
    },
    yAxis: {
      show: false
    },
    /* 注:以下配置項位于series內 */
    label: {
      show: true,
      formatter: (param) => param.name || '未命名'
    }, // 顯示名稱
    symbolSize: 50, // 散點大小
    type: 'scatter',
    data,
    markLine: {
      lineStyle: {
        normal: {
          color: '#555555',
          type: 'solid'
        }
      },
      data: [
        {
          xAxis: median,
          // 注釋為一期實現
          // type: 'average',
          // valueDim: 'x',
          label: {
            normal: {
              show: true,
              formatter: '品牌凈流入量',
            },
          }
        },
        {
          yAxis: 0,
          label: {
            normal: {
              show: true,
              formatter: '品牌持機量',
            }
          }
        },
      ]
    },
    
  • 腦洞成果:

問題二:左側視野出現的大片空白伍派,在本圖中無意義。

  • 思路:將y軸偏移到所有數據的橫軸最小值剩胁。
  • 方案:利用問題一總結出來的規(guī)則即可解決诉植。
  • 相關代碼片段:
    xAxis: {
      min: 'dataMin' // 取數據在該軸上的最小值作為最小刻度
    },
    
  • 腦洞成果:

問題三:處于不同象限的散點使用指定不同顏色區(qū)分

  • 思路:通過對每個點表示的坐標值分別與臨界值比較,從而確定所在區(qū)間昵观,設置相應的顏色值晾腔。
  • 方案:與產品經理確認,處于臨界值的點按偏“右啊犬、上”規(guī)則處理灼擂。
  • 相關代碼片段:
    const xSeparate = median
    const ySeparate = 0
    const getAreaPointColor = (value = [0, 0]) => {
      const [x, y] = value
      switch ([x, y]) {
        case (x >= xSeparate && y >= ySeparate):
          return '#3583FF'
        case (x < xSeparate && y >= ySeparate):
          return '#33BB7B'
        case (x < xSeparate && y < ySeparate):
          return '#FB7962'
        case (x >= xSeparate && y < ySeparate):
          return '#8560C5'
      }
    }
    data = data.map(d => ({
      ...d,
      itemStyle: {
        color: getAreaPointColor(d.value)
      }
    }))
    
  • 腦洞成果:

問題四:使用不同顏色圖例展示對應不同象限的含義的實現方式及其限制。

首先觉至,查看圖例legend的配置規(guī)則:“圖例組件展現了不同系列的標記(symbol)剔应,顏色和名字”,這說明了展示多個圖例需要依賴于有多組series康谆。

  1. 基于一期需求(橫坐標以所選品牌持機量的平均數來分割)领斥,參考series-scatter.markLine.data.0.type可知,取平均數是基于設置了markLine的該組數據計算的沃暗,此時數據只能放在一組series中才有意義月洛,否則橫坐標的分割線會永遠處于加了平均數配置的那組數據的平均值上(可看以下反例幫助理解),因此圖例的展示就不能用ECharts提供的legend屬性實現了孽锥。
  • 反例1:series的每項都加上平均數配置時


    出現多條“縱軸”
  • 反例2:只給其中一個子項加上平均數配置時
    只有一條軸嚼黔,但效果顯然不是我們想要的
  • 思路:在不需要圖例的任何交互的情況下,可簡單地通過將圖例作為渲染的Canvas以外的dom元素來實現惜辑;否則需要考慮更復雜的實現(衡量實現成本)唬涧。
  • 方案:直接用html+css實現。
  1. 基于第二版需求(橫坐標以所選固定的11個品牌持機量的中位數來分割)
    • 思路:由于markLine.xAxis取固定值盛撑,因此根據象限拆分多組series變得可行了碎节。
    • 方案:實現一個根據象限拆分多組series的函數,圖例信息從series獲取即可抵卫。

問題五:將散點整體縮小后狮荔,由于markLine層級過高,導致散點文字被遮擋介粘。

  • 思路:將散點元素的層級調高或調低markLine的層級殖氏。
  • 方案:markLine層級暫無法調整,使用series-scatter.z將散點層級適當調高即可姻采。
  • 相關代碼片段:
    label: {
      show: true,
      fontSize: 8,
      formatter: (params) => params.name
    },
    symbolSize: 28,
    z: 9, // 將散點層級調高至不被markLine遮擋
    
  • 腦洞成果:

效果樣例

可直接粘貼在https://echarts.apache.org/examples/zh/editor.html?c=line-simple
查看效果雅采。

  • 樣例1:簡版配置(省略legend、tooltip),可作為研究基礎
const median = 11.0
option = {
  title: {
    text: '品牌健康度分析',
  },
  xAxis: {
    min: 'dataMin',
    show: false
  },
  yAxis: {
    show: false
  },
  series: [{
    label: {
      show: true,
      formatter: (param) => param.name || '未命名'
    },
    symbolSize: 50,
    z: 9,
    data: [
      {
        name: '三星',
        value: [10.0, -6.04],
        itemStyle: {
          color: '#FB7962'
        }
      },
      {
        name: '一加',
        value: [8.0, 1.95],
        itemStyle: {
          color: '#33BB7B'
        }
      },
      {
        name: '華為',
        value: [12.0, 7.58],
        itemStyle: {
          color: '#3583FF'
        }
      },
      {
        name: '蘋果',
        value: [15.0, -7.81],
        itemStyle: {
          color: '#8560C5'
        }
      },
      // [9.0, 8.81],
      // [11.0, 8.33],
      // [14.0, 9.96],
      // [6.0, 7.24],
      // [4.0, -4.26],
      // [12.0, 10.84],
      // [7.0, 4.82],
      // [5.0, 5.68]
    ],
    type: 'scatter',
    markLine: {
      lineStyle: {
        normal: {
          color: '#555555',
          type: 'solid'
        }
      },
      data: [
        {
          xAxis: median,
          label: {
            normal: {
              show: true,
              formatter: '品牌凈流入量',
            },

          }
        },
        {
          yAxis: 0,
          label: {
            normal: {
              show: true,
              formatter: '品牌持機量',
            }
          }
        },
      ]
    },
  }]
}

  • 樣例2:最終版
// 思路已在本文提供婚瓜,具體業(yè)務代碼不公開
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末宝鼓,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子闰渔,更是在濱河造成了極大的恐慌席函,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冈涧,死亡現場離奇詭異茂附,居然都是意外死亡,警方通過查閱死者的電腦和手機督弓,發(fā)現死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門营曼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人愚隧,你說我怎么就攤上這事蒂阱。” “怎么了狂塘?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵录煤,是天一觀的道長。 經常有香客問我荞胡,道長妈踊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任泪漂,我火速辦了婚禮廊营,結果婚禮上,老公的妹妹穿的比我還像新娘萝勤。我一直安慰自己露筒,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布敌卓。 她就那樣靜靜地躺著慎式,像睡著了一般。 火紅的嫁衣襯著肌膚如雪趟径。 梳的紋絲不亂的頭發(fā)上瘪吏,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音舵抹,去河邊找鬼肪虎。 笑死劣砍,一個胖子當著我的面吹牛惧蛹,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼香嗓,長吁一口氣:“原來是場噩夢啊……” “哼迅腔!你這毒婦竟也來了?” 一聲冷哼從身側響起靠娱,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤沧烈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后像云,有當地人在樹林里發(fā)現了一具尸體锌雀,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年迅诬,在試婚紗的時候發(fā)現自己被綠了腋逆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡侈贷,死狀恐怖惩歉,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情俏蛮,我是刑警寧澤撑蚌,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站搏屑,受9級特大地震影響争涌,放射性物質發(fā)生泄漏。R本人自食惡果不足惜睬棚,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一第煮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抑党,春花似錦包警、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至暑中,卻和暖如春壹瘟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鳄逾。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工稻轨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雕凹。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓殴俱,卻偏偏與公主長得像政冻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子线欲,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容