光明新區(qū)建設(shè)網(wǎng)站網(wǎng)頁制作軟件
起因
最近接手了一個vue3項目,echarts用的是"vue-echarts": “^6.0.0”,每次查看文檔的時候痛苦不已,找一個配置要花費大量時間,所以這篇文章,主要就是為了記錄比較常見的一些配置。
主要會寫三種圖的配置項:圓環(huán)圖、直線圖、柱狀圖
效果圖:
使用vue-echarts
在package.json中的dependencies里面加一行"vue-echarts": “^6.0.0”,然后npm install,進(jìn)行安裝,這是最簡單的。
npm(推薦方式)
npm install echarts vue-echarts
CDN
在 HTML 文件按如下方式依次引入 echarts 和 vue-echarts:
<script src="https://cdn.jsdelivr.net/npm/echarts@4.1.0/dist/echarts.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-echarts@4.0.2"></script>
在main.js中引入
import VueCharts from 'vue-echarts'
app.component('app-chart', VueCharts) //使用的時候用<app-chart></app-chart>
官方文檔(寫的不詳細(xì),很多都是讓跳轉(zhuǎn)到echarts官網(wǎng),再去查找)vue-echarts官網(wǎng)地址點這里
圓環(huán)圖
<template><div><app-chart :option="state.pieOption" style="height: 300px;" :autoresize="true"></app-chart></div>
</template>
<script setup>
import { reactive, onMounted } from 'vue'
const state = reactive({pieOption: {},
})
onMounted(() => {getCostSubItemAnalysis()
})
const getCostSubItemAnalysis= () => {state.loading = trueproxy.$apollo.query().then(res => {if (!res.loading && res.data) {state.costSubItemData = res.data.getCostSubItemAnalysisgetPieChart(state.costSubItemData.subItems) //從接口中請求到數(shù)據(jù)}}).finally(() => {state.loading = false})
}
const getPieChart = (chartData) => {let newArr = []let legendWidth = 46 //該參數(shù)是為了讓左側(cè)圖例文字對齊,給了文字寬度let totalLeft = '67%' //圓環(huán)中間總額距離左邊的距離chartData?.forEach((item, index) => { //傳過來的數(shù)據(jù)剔除為0的數(shù)據(jù)if (item.cost !== 0) newArr.push(item)})let total = 0 //計算總額newArr = newArr?.map(item => {total += Number(item.cost.toFixed(2)) //總額相加保留兩位小數(shù)if (item.name.length > 6) legendWidth = 86 //如果圖例名稱大于六個文字,寬度給86,否則給46if (total >= 10000) totalLeft = '66%' //如果總額大于10000,圓環(huán)中間總額距離左邊的距離為66%,否則為67%return { value: item.cost.toFixed(2), name: resource[item.name] ? resource[item.name] : item.name }})state.pieOption = {color: ['#4C66CE', '#F8D849', '#40CBCA', '#42AB7F', '#386F95', '#E2646C'], // 圓環(huán)圖圖例、每區(qū)域顏色legend: { // 圖例orient: 'vertical',// 布局方式,默認(rèn)為水平布局,可選為:'horizontal' | 'vertical'x: 'left',// 水平安放位置,默認(rèn)為全圖居中,可選為:'center' | 'left' | 'right'| {number}(x坐標(biāo),單位px)y: 'center',// 垂直安放位置,默認(rèn)為全圖頂端,可選為:'top' | 'bottom' | 'center'| {number}(y坐標(biāo),單位px)itemWidth: 6,// 圖例圖形寬度itemHeight: 6,// 圖例圖形高度itemGap: 8,// 圖例每項之間的間隔。橫向布局時為水平間隔,縱向布局時為縱向間隔。icon: 'circle', // 圖例項的icon,ECharts 提供的標(biāo)記類型包括'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none',可以通過 'image://url' 設(shè)置為圖片,其中 URL 為圖片的鏈接,或者 dataURI。textStyle: {// 圖例的公用文本樣式color: '#999999', //文字的顏色fontSize: 14, //文字的大小fontWeight: 400, //文字的字重rich: { // 在 rich 里面,可以自定義富文本樣式。利用富文本樣式,可以在標(biāo)簽中做出非常豐富的效果,在文本中,可以對部分文本采用 rich 中定義樣式,這里需要在文本中使用標(biāo)記符號:`{styleName|text content text content}` 標(biāo)記樣式名。注意,換行仍是使用 '\n'。a: {//styleNamewidth: legendWidth,color: '#666666'},b: {color: '#999999'},c: {color: '#999999'}}},formatter: function (name) {let total = 0let tarValue = nullfor (let i = 0; i < newArr.length; i++) {total += Number(newArr[i].value || 0)if (name === newArr[i].name) {tarValue = Number(newArr[i].value || 0)}}const p = (Number(tarValue / total) * 100).toFixed(2)var arr = ['{a|' + name + '}','{b|' + tarValue + '}','{c|' + p + '%}']return arr.join(' ')}},graphic: { // graphic 是原生圖形元素組件??梢灾С值膱D形元素包括:image, text, circle, sector, ring, polygon, polyline, rect, line, bezierCurve, arc, group,type: 'text',// 用這個在圓環(huán)中間顯示總金額left: totalLeft, //距離容器左邊的距離top: '48%',style: {text: total.toFixed(2) + '元', // 總金額保留兩位小數(shù)fontSize: 16, // 總金額字體大小color: '#333',fontWeight: 400}},series: [{type: 'pie', // 圖表類型 bar:柱狀圖 line:折線圖 pie:餅圖radius: ['50%', '56%'], // 餅圖的半徑??梢詾槿缦骂愋?#xff1a;number:直接指定外半徑值。string:例如,'20%',表示外半徑為可視區(qū)尺寸(容器高寬中較小一項)的 20% 長度。Array.<number|string>:數(shù)組的第一項是內(nèi)半徑,第二項是外半徑。每一項遵從上述 number string 的描述。center: ['74%', '50%'], // 餅圖的中心(圓心)坐標(biāo),數(shù)組的第一項是橫坐標(biāo),第二項是縱坐標(biāo)。支持設(shè)置成百分比,設(shè)置成百分比時第一項是相對于容器寬度,第二項是相對于容器高度。avoidLabelOverlap: false, // 是否啟用防止標(biāo)簽重疊策略,默認(rèn)開啟,在標(biāo)簽擁擠重疊的情況下會挪動各個標(biāo)簽的位置,防止標(biāo)簽間的重疊。minAngle: 1,//最小的角度,防止出現(xiàn)為0時,樣式出錯的情況itemStyle: { // 圖形樣式borderColor: '#fff', // 圖形的描邊顏色。支持的顏色格式同 color,不支持回調(diào)函數(shù)。borderWidth: 0, // 描邊線寬。為 0 時無描邊。borderRadius: 10 // 用于指定餅圖扇形區(qū)塊的內(nèi)外圓角半徑,支持設(shè)置固定數(shù)值或者相對于扇形區(qū)塊的半徑的百分比值},label: { // 餅圖圖形上的文本標(biāo)簽,可用于說明圖形的一些數(shù)據(jù)信息,比如值,名稱等。normal: {show: false,formatter: '{name|}\n\n{value|{c}} {money|元}', // 標(biāo)簽內(nèi)容格式器,支持字符串模板和回調(diào)函數(shù)兩種形式,字符串模板與回調(diào)函數(shù)返回的字符串均支持用 \n 換行。position: 'center',width: 130,lineHight: 30,backgroundColor: '#ffffff',rich: {name: {fontSize: 16,color: '#333',fontWeight: 400},value: {fontSize: 20,color: 'inherit',fontWeight: 600},money: {fontSize: 12,color: 'inherit',fontWeight: 600}}},show: false,position: 'center' // 標(biāo)簽的位置,可選:'outside',餅圖扇區(qū)外側(cè),通過視覺引導(dǎo)線連到相應(yīng)的扇區(qū)。'inside'餅圖扇區(qū)內(nèi)部。'inner' 同 'inside'。'center'在餅圖中心位置。},emphasis: { // 高亮狀態(tài)的扇區(qū)和標(biāo)簽樣式label: {show: true,fontSize: 16,fontWeight: '400'}},labelLine: { // 標(biāo)簽的視覺引導(dǎo)線配置show: false},labelLayout: function (params) { // 標(biāo)簽的統(tǒng)一布局配置。該配置項是在每個系列默認(rèn)的標(biāo)簽布局基礎(chǔ)上,統(tǒng)一調(diào)整標(biāo)簽的(x, y)位置,標(biāo)簽對齊等屬性以實現(xiàn)想要的標(biāo)簽布局效果。const isLeft = params.labelRect.x < 50const points = params.labelLinePointsif (!points) returnpoints[2][0] = isLeft? params.labelRect.x: params.labelRect.x + params.labelRect.widthreturn {labelLinePoints: points // 默認(rèn)引導(dǎo)線的位置,目前只有餅圖(pie)和漏斗圖(funnel)有默認(rèn)標(biāo)簽位置,如果沒有該值則為 null}},data: newArr?.map(item => { // 系列中的數(shù)據(jù)內(nèi)容數(shù)組。數(shù)組項可以為單個數(shù)值return {name: item.name,value: item.value}})}]}
}
</script>
折線圖
<template><div><app-chart :option="state.option" style="height: 350px;" :autoresize="true"></app-chart></div>
</template>
<script setup>
import { reactive, onMounted } from 'vue'
const state = reactive({option: {},
})
onMounted(() => {getCostSubItemAnalysis()
})
const getCostSubItemAnalysis= () => {state.loading = trueproxy.$apollo.query().then(res => {if (!res.loading && res.data) {state.costSubItemData = res.data.getCostSubItemAnalysisgetLineChart(state.costSubItemData.trend) //從接口中請求到數(shù)據(jù)}}).finally(() => {state.loading = false})
}
const getLineChart= (chartData) => {if (!chartData.series) chartData.series = []const maxArr = []const legend = []const series = chartData.series?.map(item => {const lineData = []item.data.forEach(subitem => {lineData.push(Math.abs(subitem)) // Math.abs計算一個數(shù)的絕對值})maxArr.push(Math.max.apply(null, lineData))legend.push({name: resource[item.name] ? resource[item.name] : item.name})return {name: resource[item.name] ? resource[item.name] : item.name,type: 'line',smooth: true,symbol: item.data.length > 1 ? 'none' : 'circle',data: item.data.map(subitem => subitem.toFixed(2))}})let max = 0max = Math.ceil(Math.max.apply(null, maxArr) * 1.2) > 0 ? Math.ceil(Math.max.apply(null, maxArr) * 1.2) : 3state.option = {color: ['#4C66CE', '#F8D849', '#40CBCA', '#42AB7F', '#386F95', '#E2646C'],grid: { // 直角坐標(biāo)系內(nèi)繪圖網(wǎng)格,單個 grid 內(nèi)最多可以放置上下兩個 X 軸,左右兩個 Y 軸. 可以在網(wǎng)格上繪制折線圖,柱狀圖,散點圖(氣泡圖)。left: '36px', // grid 組件離容器左側(cè)的距離。right: '36px',top: '24px',bottom: '48px',containLabel: true //grid 區(qū)域是否包含坐標(biāo)軸的刻度標(biāo)簽},legend: {// 下方圖例itemWidth: 8,itemHeight: 8,icon: 'circle',data: legend,left: 'center',bottom: '0',itemGap: 30,textStyle: {color: '#999999',fontSize: 12,fontWeight: 400}},tooltip: { // 提示框組件trigger: 'axis' // 觸發(fā)類型??蛇x:'item'數(shù)據(jù)項圖形觸發(fā),主要在散點圖,餅圖等無類目軸的圖表中使用。'axis'坐標(biāo)軸觸發(fā),主要在柱狀圖,折線圖等會使用類目軸的圖表中使用。'none'什么都不觸發(fā)。},xAxis: {axisLine: { // x軸線設(shè)置lineStyle: {type: 'solid',color: '#E9E9EB', // x線的顏色width: '1' // 坐標(biāo)線的寬度}},axisLabel: { // x軸字體顏色textStyle: {color: '#999999'}},axisTick: { // 去掉x軸刻度show: false},type: 'category', // 坐標(biāo)軸類型。可選:'value' 數(shù)值軸,適用于連續(xù)數(shù)據(jù)。'category' 類目軸,適用于離散的類目數(shù)據(jù)。為該類型時類目數(shù)據(jù)可自動從 series.data 或 dataset.source 中取,或者可通過 xAxis.data 設(shè)置類目數(shù)據(jù)。'time' 時間軸,適用于連續(xù)的時序數(shù)據(jù),與數(shù)值軸相比時間軸帶有時間的格式化,在刻度計算上也有所不同,例如會根據(jù)跨度的范圍來決定使用月,星期,日還是小時范圍的刻度。'log' 對數(shù)軸。適用于對數(shù)數(shù)據(jù)。data: chartData.xAxis?.map(item => {return props.periodType === 'day'? moment(item * 1000).format('yyyy-MM-DD') : props.periodType === 'quarter'? moment(item * 1000).format('yyyy') + '-' + transferDate[moment(item * 1000).format('MM')] : props.periodType === 'month'? moment(item * 1000).format('yyyy-MM') : moment(item * 1000).format('yyyy')})},yAxis: {type: 'value',max: formatIntervalandMax(max, 3).max, // 坐標(biāo)軸刻度最大值interval: formatIntervalandMax(max, 3).interval, // 強(qiáng)制設(shè)置坐標(biāo)軸分割間隔axisLabel: {// 坐標(biāo)軸刻度標(biāo)簽的相關(guān)設(shè)置formatter: (value) => {return value >= 1000 ? `¥${value / 1000}k` : `¥${value}`},textStyle: { // y軸字體顏色color: '#999999'}},splitLine: { // 保留網(wǎng)格線show: true,lineStyle: {type: 'solid',color: '#E5E6EB', // y線的顏色width: '1' // 坐標(biāo)線的寬度}}},series: series}
}
</script>
重疊(堆疊)柱狀圖
<template><div><app-chart :option="state.barOption" style="height: 380px;" :autoresize="true"></app-chart></div>
</template>
<script setup>
import { reactive, onMounted } from 'vue'
const state = reactive({barOption: {}
})
onMounted(() => {getCostTrend()
})
const getCostTrend = () => {state.loading = trueproxy.$apollo.query().then(res => {if (!res.loading && res.data) {state.loading = falsestate.resourceAnalysisData = res.data.getCostDynamicResourceAnalysis //從接口中請求到數(shù)據(jù)getBarChart(state.lineCost.trend)}}).finally(() => {state.loading = false})
}const getBarChart = (chartData) => {const lineData = []const onDemand = [] // 后付費的數(shù)據(jù)const reserved = [] // 先付費的數(shù)據(jù)const total = [] // 總額的數(shù)據(jù)chartData.series[0]?.data.forEach(item => {lineData.push(Math.abs(item.total))onDemand.push(item.onDemand.toFixed(2))reserved.push(item.reserved.toFixed(2))total.push((item.onDemand + item.reserved).toFixed(2))})const series = [{barGap: '-100%', //不同系列的柱間距離,為百分比(如 '30%',表示柱子寬度的 30%)。如果想要兩個系列的柱子重疊,可以設(shè)置 barGap 為 '-100%'。這在用柱子做背景的時候有用。name: '總數(shù)',stack: 'total', //數(shù)據(jù)堆疊,同個類目軸上系列配置相同的 stack 值可以堆疊放置。type: 'bar', barWidth: '8px', //柱條的寬度,不設(shè)時自適應(yīng)。itemStyle: {color: '#40CBCA',//柱條的顏色barBorderRadius: 5 //柱條的圓角半徑,單位px,支持傳入數(shù)組分別指定 4 個圓角半徑。},data: total},{barGap: '-100%',name: '后付費',type: 'bar',barWidth: '8px',itemStyle: {color: '#40CBCA',barBorderRadius: 5},data: onDemand},{name: '預(yù)付費',type: 'bar',barWidth: '8px',showBackground: true, //是否顯示柱條的背景色。backgroundStyle: { // 每一個柱條的背景樣式。需要將 showBackground 設(shè)置為 true 時才有效。color: '#F2F3F7'},itemStyle: {color: '#4C66CE',barBorderRadius: 5},data: reserved}]let max = 0max = Math.ceil(Math.max.apply(null, lineData) * 1.2) > 0 ? Math.ceil(Math.max.apply(null, lineData) * 1.2) : 3 // 計算y軸刻度最大值state.barOption = {legend: { //設(shè)置圖例樣式selectedMode: false, // 圖例禁止點擊itemWidth: 8,itemHeight: 8,icon: 'circle',data: ['預(yù)付費', '后付費'],left: 'center',bottom: '0',itemGap: 30,textStyle: {color: '#999999',fontSize: 12,fontWeight: 400}},grid: { // 直角坐標(biāo)系內(nèi)繪圖網(wǎng)格,單個 grid 內(nèi)最多可以放置上下兩個 X 軸,左右兩個 Y 軸. 可以在網(wǎng)格上繪制折線圖,柱狀圖,散點圖(氣泡圖)。left: '20px',right: '20px',top: '20px',bottom: '40px',containLabel: true,// grid 區(qū)域是否包含坐標(biāo)軸的刻度標(biāo)簽show: true,borderWidth: '1', // 網(wǎng)格的邊框線寬borderColor: '#E9E9EB' // 網(wǎng)格的邊框顏色},tooltip: {// 提示框組件trigger: 'axis' // 觸發(fā)類型??蛇x:'item'數(shù)據(jù)項圖形觸發(fā),主要在散點圖,餅圖等無類目軸的圖表中使用。'axis'坐標(biāo)軸觸發(fā),主要在柱狀圖,折線圖等會使用類目軸的圖表中使用。'none'什么都不觸發(fā)。axisPointer: { // 坐標(biāo)軸指示器配置項type: 'shadow' //指示器類型。可選'line' 直線指示器'shadow' 陰影指示器'none' 無指示器'cross' 十字準(zhǔn)星指示器。其實是種簡寫,表示啟用兩個正交的軸的 axisPointer。},formatter: function (params) {let total = 0let axisValue = ''params.splice(0, 1)params.forEach(item => {total += Number(item.value)axisValue = item.axisValue})let tooltipVal = `<div>${axisValue}</div><div>當(dāng)前總金額 -- ¥${total.toFixed(2)}</div>`params.forEach(item => {tooltipVal += `<div>${item.marker}<span style="margin-left: 4px;">${item.seriesName}</span><span style="margin-left: 16px; display: inline-block; min-width: 100px;">¥${item.value}</span><span>${total ? (Number(item.value) / total * 100).toFixed(2) + '%' : '--'}</span></div>`})return tooltipVal}},xAxis: {type: 'category',axisLabel: {textStyle: {color: '#999999'}},axisTick: { // 刻度show: false},axisLine: { // 軸線lineStyle: {color: '#E9E9EB',width: 1}},data: chartData.xAxis.map(item => {return props.periodType === 'day'? moment(item * 1000).format('yyyy-MM-DD') : props.periodType === 'quarter'? moment(item * 1000).format('yyyy') + '-' + transferDate[moment(item * 1000).format('MM')] : props.periodType === 'month'? moment(item * 1000).format('yyyy-MM') : moment(item * 1000).format('yyyy')})},yAxis: {max: formatIntervalandMax(max, 3).max, //y軸刻度最大值interval: formatIntervalandMax(max, 3).interval, // 強(qiáng)制設(shè)置坐標(biāo)軸分割間隔type: 'value', // 坐標(biāo)軸類型。可選:'value' 數(shù)值軸,適用于連續(xù)數(shù)據(jù)。'category' 類目軸,適用于離散的類目數(shù)據(jù)。為該類型時類目數(shù)據(jù)可自動從 series.data 或 dataset.source 中取,或者可通過 xAxis.data 設(shè)置類目數(shù)據(jù)。'time' 時間軸,適用于連續(xù)的時序數(shù)據(jù),與數(shù)值軸相比時間軸帶有時間的格式化,在刻度計算上也有所不同,例如會根據(jù)跨度的范圍來決定使用月,星期,日還是小時范圍的刻度。'log' 對數(shù)軸。適用于對數(shù)數(shù)據(jù)。axisLabel: {formatter: (value) => {return value >= 1000 ? `¥${value / 1000}k` : `¥${value}`},textStyle: { // y軸字體顏色color: '#999999'}}},series: series}
}
</script>
柱狀圖
<template><div><app-chart :option="state.option" style="height: 380px;" :autoresize="true"></app-chart></div>
</template>
<script setup>
import { reactive, onMounted } from 'vue'
const state = reactive({option: {}
})
onMounted(() => {getCostDynamicResourceAnalysis()
})
const getCostDynamicResourceAnalysis = () => {state.loading = trueproxy.$apollo.query().then(res => {if (!res.loading && res.data) {state.loading = falsestate.resourceAnalysisData = res.data.getCostDynamicResourceAnalysis //從接口中請求到數(shù)據(jù)getLineChart(state.resourceAnalysisData.trend)}}).finally(() => {state.loading = false})
}const getLineChart = (chartData) => {let max = 0const lineData = []chartData.series[0]?.data.forEach(item => {lineData.push(Math.abs(item))})max = Math.ceil(Math.max.apply(null, lineData) * 1.2) > 0 ? Math.ceil(Math.max.apply(null, lineData) * 1.2) : 3state.option = {grid: {left: '20px',right: '20px',top: '20px',bottom: '40px',containLabel: true,show: true,borderWidth: '1',borderColor: '#E9E9EB'},tooltip: {trigger: 'axis',axisPointer: { //坐標(biāo)軸指示器配置項type: 'shadow' //指示器類型。可選'line' 直線指示器'shadow' 陰影指示器'none' 無指示器'cross' 十字準(zhǔn)星指示器。其實是種簡寫,表示啟用兩個正交的軸的 axisPointer。}},xAxis: {type: 'category',axisLabel: {// x軸字體顏色textStyle: {color: '#999999'}},axisTick: { // 刻度show: false},axisLine: { // 軸線lineStyle: {color: '#E9E9EB',width: 1}},data: chartData.xAxis.map(item => {return props.periodType === 'day'? moment(item * 1000).format('yyyy-MM-DD') : props.periodType === 'quarter'? moment(item * 1000).format('yyyy') + '-' + transferDate[moment(item * 1000).format('MM')] : props.periodType === 'month'? moment(item * 1000).format('yyyy-MM') : moment(item * 1000).format('yyyy')})},yAxis: {max: formatIntervalandMax(max, 3).max,//y軸刻度最大值interval: formatIntervalandMax(max, 3).interval,// 強(qiáng)制設(shè)置坐標(biāo)軸分割間隔type: 'value', // 坐標(biāo)軸類型。可選:'value' 數(shù)值軸,適用于連續(xù)數(shù)據(jù)。'category' 類目軸,適用于離散的類目數(shù)據(jù)。為該類型時類目數(shù)據(jù)可自動從 series.data 或 dataset.source 中取,或者可通過 xAxis.data 設(shè)置類目數(shù)據(jù)。'time' 時間軸,適用于連續(xù)的時序數(shù)據(jù),與數(shù)值軸相比時間軸帶有時間的格式化,在刻度計算上也有所不同,例如會根據(jù)跨度的范圍來決定使用月,星期,日還是小時范圍的刻度。'log' 對數(shù)軸。適用于對數(shù)數(shù)據(jù)。axisLabel: {// y軸字體顏色textStyle: {color: '#999999'}}},series: [{data: chartData.series[0]?.data.map(item => item.toFixed(2)),type: 'bar',barWidth: '8px', showBackground: true,backgroundStyle: {color: '#F2F3F7'},itemStyle: {color: '#4C66CE',barBorderRadius: 5}}]}
}
</script>