基于Echarts實現繪制立體柱狀圖的示例代碼
目錄
- 前言
- 實現方法
- 先寫一個常規(guī)的柱狀圖
- echarts的配置選項
- 效果圖
前言
大家好,我是梁木由。之前在做大屏可視化項目時,UI設計了一個立體形狀的柱狀圖,根據之前做的一些圖表的項目沒有能復用的,沒有做過這種立體形狀的圖表,打開echarts也沒看到有相關的demo,看下如何實現
實現方法
先寫一個常規(guī)的柱狀圖
在這個基礎上進行改進
<div id="main"></div>?#main{ width: 500px; height: 350px;}?var chartDom = document.getElementById("main");var myChart = echarts.init(chartDom);var option;?option = { xAxis: { axisTick: { show: false }, nameTextStyle: { color: "#fff" }, data: ["春節(jié)", "元宵節(jié)", "端午節(jié)", "中秋節(jié)"] }, legend: { data: ["春節(jié)", "元宵節(jié)", "端午節(jié)", "中秋節(jié)"], right: "25", top: "18", icon: "rect", itemHeight: 10, itemWidth: 10, textStyle: { color: "#000" } }, yAxis: { type: "value", axisLabel: { color: "#000" }, splitLine: { show: true, lineStyle: {type: "dashed",color: ["#ccc"] } } }, series: [ { data: [{ name: "春節(jié)", value: 24 },{ name: "端午節(jié)", value: 44 },{ name: "中秋節(jié)", value: 32 },{ name: "春節(jié)", value: 50 } ], barWidth: 30, type: "bar" } ]};??option && myChart.setOption(option);
echarts的配置選項
首先呢我們看下echarts的配置選項
那我們看所有的type 沒有立體柱狀圖的類型,但是呢我們看最后一項type: custom,什么意思呢,自定義系列,那就是說我們可以選擇custom 類型來實現立體柱狀圖
renderItem
type為custom可以自定義系列圖形元素渲染。
根據查看配置項,發(fā)現有一個renderItem函數
,custom 系列需要開發(fā)者自己提供圖形渲染的邏輯。這個渲染邏輯一般命名為 renderItem
看下renderItem函數的介紹
renderItem 函數提供了兩個參數:
params:包含了當前數據信息和坐標系的信息。
{ context: // {Object} 一個可供開發(fā)者暫存東西的對象。生命周期只為:當前次的渲染。 seriesId: // {string} 本系列 id。 seriesName: // {string} 本系列 name。 seriesIndex: // {number} 本系列 index。 dataIndex: // {number} 數據項的 index。 dataIndexInside: // {number} 數據項在當前坐標系中可見的數據的 index(即 dataZoom 當前窗口中的數據的 index)。 dataInsideLength: // {number} 當前坐標系中可見的數據長度(即 dataZoom 當前窗口中的數據數量)。 actionType: // {string} 觸發(fā)此次重繪的 action 的 type。 coordSys: // 不同的坐標系中,coordSys 里的信息不一樣,含有如下這些可能: coordSys: {type: "cartesian2d",x: // {number} grid rect 的 xy: // {number} grid rect 的 ywidth: // {number} grid rect 的 widthheight: // {number} grid rect 的 height }, coordSys: {type: "calendar",x: // {number} calendar rect 的 xy: // {number} calendar rect 的 ywidth: // {number} calendar rect 的 widthheight: // {number} calendar rect 的 heightcellWidth: // {number} calendar cellWidthcellHeight: // {number} calendar cellHeightrangeInfo: { start: // calendar 日期開端 end: // calendar 日期結尾 weeks: // calendar 周數 dayCount: // calendar 日數} }, coordSys: {type: "geo",x: // {number} geo rect 的 xy: // {number} geo rect 的 ywidth: // {number} geo rect 的 widthheight: // {number} geo rect 的 heightzoom: // {number} 縮放的比率。如果沒有縮放,則值為 1。例如 0.5 表示縮小了一半。 }, coordSys: {type: "polar",cx: // {number} polar 的中心坐標cy: // {number} polar 的中心坐標r: // {number} polar 的外半徑r0: // {number} polar 的內半徑 }, coordSys: {type: "singleAxis",x: // {number} singleAxis rect 的 xy: // {number} singleAxis rect 的 ywidth: // {number} singleAxis rect 的 widthheight: // {number} singleAxis rect 的 height }}
其中,關于 dataIndex
和 dataIndexInside
的區(qū)別:
dataIndex
指的dataItem
在原始數據中的 index。dataIndexInside
指的是dataItem
在當前數據窗口中的 index。
[renderItem.arguments.api] 中使用的參數都是 dataIndexInside
而非 dataIndex
,因為從 dataIndex
轉換成 dataIndexInside
需要時間開銷。
api:是一些開發(fā)者可調用的方法集合。
所有屬性
{[value], [coord] , [size] , [style] , [styleEmphasis] , [visual] , [barLayout] , [currentSeriesIndices] , [font], [getWidth] , [getHeight], [getZr], [getDevicePixelRatio]}
我們使用renderItem來自定義元素會使用到renderItem.api的三個方法,先來介紹下這三個方法
- [api.value(...)],意思是取出
dataItem
中的數值。例如api.value(0)
表示取出當前dataItem
中第一個維度的數值。 - [api.coord(...)],意思是進行坐標轉換計算。例如
var point = api.coord([api.value(0), api.value(1)])
表示dataItem
中的數值轉換成坐標系上的點。 - [api.size(...)] ,表示得到坐標系上一段數值范圍對應的長度。
看下代碼實現
series: getSeriesData()?function getSeriesData() { const data = []; seriesData.forEach((item, index) => { data.push( {type: "custom",name: item.label,renderItem: function (params, api) { return getRenderItem(params, api);},data: item.value, } ) }) return data}?function getRenderItem(params, api) { // params.seriesIndex表示本系列 index const index = params.seriesIndex; // api.coord() 坐標轉換計算 // api.value() 取出當前項中的數值 let location = api.coord([api.value(0) + index, api.value(1)]); // api.size() 坐標系數值范圍對應的長度 var extent = api.size([0, api.value(1)]); return { type: "rect", shape: { x: location[0] - 20 / 2, y: location[1], width: 20, height: extent[1] }, style: api.style() };}
來看下我們的實現效果
柱狀圖效果出來了,那來看下怎么將柱狀圖改為立體圖
return_group
我看到renderItem
可以返回一個return_group
類型,來看看這個類型的介紹
- group 是唯一的可以有子節(jié)點的容器。
- group 可以用來整體定位一組圖形元素。
那就是說我們可以將設定一組圖形元素然后組合到一起形成立體柱狀圖
那么問題又來了怎么設定一組圖形元素呢?
graphic
這個呢是關于圖形相關的方法,再來了解兩個API
graphic.extendShape
創(chuàng)建一個新的圖形元素
graphic.registerShape
注冊一個開發(fā)者定義的圖形元素
創(chuàng)建圖形元素
那我們先來創(chuàng)建一個新的圖形元素
const leftRect = echarts.graphic.extendShape({ shape: { x: 0, y: 0, width: 19, //柱狀圖寬 zWidth: 8, //陰影折角寬 zHeight: 4, //陰影折角高 }, buildPath: function (ctx, shape) { const api = shape.api; const xAxisPoint = api.coord([shape.xValue, 0]); const p0 = [shape.x - shape.width / 2, shape.y - shape.zHeight]; const p1 = [shape.x - shape.width / 2, shape.y - shape.zHeight]; const p2 = [xAxisPoint[0] - shape.width / 2, xAxisPoint[1]]; const p3 = [xAxisPoint[0] + shape.width / 2, xAxisPoint[1]]; const p4 = [shape.x + shape.width / 2, shape.y];? ctx.moveTo(p0[0], p0[1]); ctx.lineTo(p1[0], p1[1]); ctx.lineTo(p2[0], p2[1]); ctx.lineTo(p3[0], p3[1]); ctx.lineTo(p4[0], p4[1]); ctx.lineTo(p0[0], p0[1]); ctx.closePath(); }, });??const rightRect = echarts.graphic.extendShape({ shape: { x: 0, y: 0, width: 18, zWidth: 15, zHeight: 8, }, buildPath: function (ctx, shape) { const api = shape.api; const xAxisPoint = api.coord([shape.xValue, 0]); const p1 = [shape.x - shape.width / 2, shape.y - shape.zHeight / 2]; const p3 = [xAxisPoint[0] + shape.width / 2, xAxisPoint[1]]; const p4 = [shape.x + shape.width / 2, shape.y]; const p5 = [xAxisPoint[0] + shape.width / 2 + shape.zWidth, xAxisPoint[1]]; const p6 = [shape.x + shape.width / 2 + shape.zWidth, shape.y - shape.zHeight / 2]; const p7 = [shape.x - shape.width / 2 + shape.zWidth, shape.y - shape.zHeight]; ctx.moveTo(p4[0], p4[1]); ctx.lineTo(p3[0], p3[1]); ctx.lineTo(p5[0], p5[1]); ctx.lineTo(p6[0], p6[1]); ctx.lineTo(p4[0], p4[1]);? ctx.moveTo(p4[0], p4[1]); ctx.lineTo(p6[0], p6[1]); ctx.lineTo(p7[0], p7[1]); ctx.lineTo(p1[0], p1[1]); ctx.lineTo(p4[0], p4[1]); ctx.closePath(); }, });
注冊圖形元素
echarts.graphic.registerShape("leftRect", leftRect);echarts.graphic.registerShape("rightRect", rightRect);
再來修改一下return_group
function getRenderItem(params, api) { const index = params.seriesIndex; let location = api.coord([api.value(0) + index, api.value(1)]); var extent = api.size([0, api.value(1)]); return { type: "group", children: [ {type: "leftRect",shape: { api, xValue: api.value(0) + index, yValue: api.value(1), x: location[0], y: location[1]},style: api.style() }, {type: "rightRect",shape: { api, xValue: api.value(0) + index, yValue: api.value(1), x: location[0], y: location[1]},style: api.style() } ] };}
再來看下效果
可以看到立體形狀的柱狀圖已經實現了,那還有個缺點就是顏色需要再按照設計圖來改改
const colors = [ [ { offset: 0, color: "rgba(26, 132, 191, 1)" }, { offset: 1, color: "rgba(52, 163, 224, 0.08)" }, ], [ { offset: 0, color: "rgba(137, 163, 164, 1)" }, { offset: 1, color: "rgba(137, 163, 164, 0.08)" }, ], [ { offset: 0, color: "rgba(44, 166, 166, 1)" }, { offset: 1, color: "rgba(44, 166, 166, 0.08)" }, ], [ { offset: 0, color: "rgba(34, 66, 186, 1)" }, { offset: 1, color: "rgba(34, 66, 186, 0.08)" }, ], ];?//在getSeriesData添加itemStyleitemStyle: { color: () => { return new echarts.graphic.LinearGradient(0, 0, 0, 1, colors[index]); },},
效果圖
以上就是基于Echarts實現繪制立體柱狀圖的示例代碼的詳細內容,更多關于Echarts繪制立體柱狀圖的資料請關注其它相關文章!
