Vue封裝的標準漏斗圖教程
更新時間:2025年02月12日 15:37:17 作者:努力奮斗小白
文章展示了基于Vue封裝的標準漏斗圖的代碼,包括權(quán)重算法、滾輪監(jiān)聽和點擊示例功能,旨在提供實用的圖表展示技巧
Vue封裝的標準漏斗圖
代碼展示
基于Vue封裝的標準漏斗圖,增加權(quán)重算法,避免數(shù)值很小時圖表顯示過小,監(jiān)聽滾輪高度,防止彈窗飛走,點擊示例動態(tài)顯示對應(yīng)的梯形圖表塊。
/** * 權(quán)重 */ export function qz(arr) { // 計算數(shù)列的總和 const total = arr.reduce((sum, val) => sum + val, 0) // 如果總和為零,則無法平衡,直接返回原數(shù)組 if (total === 0) { return arr } function nonlinearScale(val) { return Math.sqrt(val) // 對數(shù)值進行平方根變換 } // 平方根為了讓數(shù)小點,一般降級都采用平方根處理 const scaledArr = arr.map(val => nonlinearScale(val)) // 計算縮放后數(shù)列的總和 const scaledTotal = scaledArr.reduce((sum, val) => sum + val, 0) // 將縮放后的數(shù)列歸一到100%,超過100就越界了 let balancedArr = scaledArr.map(val => (val / scaledTotal) * 100) // 由于浮點數(shù)的精度問題,總和可能不是精確的100%,問題不大 const error = 100 - balancedArr.reduce((sum, val) => sum + val, 0) const nonZeroCount = balancedArr.filter(val => val > 0).length if (nonZeroCount > 0) { const adjustment = error / nonZeroCount balancedArr = balancedArr.map(val => val + (val > 0 ? adjustment : 0)) } // 四舍五入到小數(shù)點后兩 balancedArr = balancedArr.map(val => Math.round(val * 100) / 100) return balancedArr }
<LdChart :chart-data="charDataArray" :flag-type="flagType" /> // 接口返回 this.charDataArray = [] this.charDataTwoArray = [] this.num1 = 0 this.num2 = 0 if (res.data && res.data.length > 0) { this.loading = false // 數(shù)據(jù)都是固定的五個!!!1 const obj1 = [ { height: '20%', top: '0%', name: '名稱1', value: '', type: '10%', unit: '萬元', color: '#7aa5fa', checkItem: false, itemColor: '#7aa5fa', fontColor: '#303313' }, { height: '20%', top: '20%', name: '名稱2', value: '', type: '30%', unit: '萬元', color: '#7ae0b8', checkItem: false, itemColor: '#7ae0b8', fontColor: '#303313' }, { height: '20%', top: '40%', name: '名稱3', value: '', type: '50%', unit: '萬元', color: '#f6e0b4', checkItem: false, itemColor: '#f6e0b4', fontColor: '#303313' }, { height: '20%', top: '60%', name: '名稱4', value: '', type: '80%', unit: '萬元', color: '#d9d9d9', checkItem: false, itemColor: '#d9d9d9', fontColor: '#303313' }, { height: '20%', top: '80%', name: '名稱5', value: '', type: '100%', unit: '萬元', color: '#f5aa8a', checkItem: false, itemColor: '#f5aa8a', fontColor: '#303313' } ] const obj2 = [ { height: '20%', top: '0%', name: '名稱1', value: '', type: '10%', unit: '個', color: '#7aa5fa', checkItem: false, itemColor: '#7aa5fa', fontColor: '#303313' }, { height: '20%', top: '20%', name: '名稱2', value: '', type: '30%', unit: '個', color: '#7ae0b8', checkItem: false, itemColor: '#7ae0b8', fontColor: '#303313' }, { height: '20%', top: '40%', name: '名稱3', value: '', type: '50%', unit: '個', color: '#f6e0b4', checkItem: false, itemColor: '#f6e0b4', fontColor: '#303313' }, { height: '20%', top: '60%', name: '名稱4', value: '', type: '80%', unit: '個', color: '#d9d9d9', checkItem: false, itemColor: '#d9d9d9', fontColor: '#303313' }, { height: '20%', top: '80%', name: '名稱5', value: '', type: '100%', unit: '個', color: '#f5aa8a', checkItem: false, itemColor: '#f5aa8a', fontColor: '#303313' } ] const sumOne = res.data[0].reduce((sum, current) => sum + Number(current.sales), 0) const sumTwo = res.data[1].reduce((sum, current) => sum + Number(current.sales), 0) this.num1 = sumOne.toFixed(2) this.num2 = sumTwo obj1.forEach(item => { res.data[0].forEach(it => { if (item.type === it.winOrderRate) { item.value = it.sales // 計算比例 let bl = 0 sumOne === 0 ? bl = 0 : bl = Math.floor(Number(it.sales) / sumOne * 100) Number(it.sales) > 0 && bl === 0 ? bl = 1 : '' // 設(shè)置合適的比例1 item.height = bl + '%' } }) }) obj2.forEach(item => { res.data[1].forEach(it => { if (item.type === it.winOrderRate) { item.value = it.sales // 計算比例 let bl = 0 sumTwo === 0 ? bl = 0 : bl = Math.floor(Number(it.sales) / sumTwo * 100) Number(it.sales) > 0 && bl === 0 ? bl = 1 : '' // 設(shè)置合適的比例 item.height = bl + '%' } }) }) const qzOne = qz(obj1.map(it => Number(it.height.split('%')[0]))) const qzTwo = qz(obj2.map(it => Number(it.height.split('%')[0]))) obj1.forEach((it, index) => { it.height = qzOne[index] + '%' }) obj2.forEach((it, index) => { it.height = qzTwo[index] + '%' }) // 排除0的, const objNew1 = obj1.filter(item => item.value !== 0 && item.value !== '0') const objNew2 = obj2.filter(item => item.value !== 0 && item.value !== '0') // 第一個是 0, 第二個是 第一個的高度, 第三個是 第一個+ 第二個 第四個是 1+2+3 const result = [] const result1 = [] let sum = 0 let sum1 = 0 for (let i = 0; i < objNew1.length; i++) { sum += Number(objNew1[i].height.split('%')[0]) result.push(sum) } for (let i = 0; i < objNew2.length; i++) { sum1 += Number(objNew2[i].height.split('%')[0]) result1.push(sum1) } result.pop() result1.pop() objNew1.forEach((it, index) => { // 第一個是 0, 之后的每一個都是 前面的相加!!!1 if (index === 0) { it.top = '0%' } else { it.top = result[index - 1] + '%' } }) objNew2.forEach((it, index) => { // 第一個是 0, 之后的每一個都是 前面的相加 if (index === 0) { it.top = '0%' } else { it.top = result1[index - 1] + '%' } }) // 計算比例得 const one = '名稱1' const two = '名稱2' const three = '名稱3' const four = '名稱4' const five = '名稱5' const all = [one, two, three, four, five] this.charDataArray.push(all) this.charDataArray.push(objNew1) this.charDataArray.push(objNew2) this.charDataArray.push('類型1')
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Ant Design Vue Pro靜態(tài)路由如何改為動態(tài)路由
這篇文章主要介紹了Ant Design Vue Pro靜態(tài)路由如何改為動態(tài)路由問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10三步搞定:Vue.js調(diào)用Android原生操作
這篇文章主要介紹了三步搞定:Vue.js調(diào)用Android原生操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09Vue使用ElementUI動態(tài)修改table單元格背景顏色或文本顏色
本文主要介紹了Vue使用ElementUI動態(tài)修改table單元格背景顏色或文本顏色,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02前端實現(xiàn)Vue組件頁面跳轉(zhuǎn)的多種方式小結(jié)
這篇文章主要為大家詳細介紹了前端實現(xiàn)Vue組件頁面跳轉(zhuǎn)的多種方式,文中的示例代碼講解詳細,具有一定的參考價值,有需要的小伙伴可以了解下2024-02-02vue中iframe使用以及結(jié)合postMessage實現(xiàn)跨域通信
這篇文章主要介紹了vue中iframe使用以及結(jié)合postMessage實現(xiàn)跨域通信方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09