uniapp封裝小程序雷達圖組件的完整代碼
效果圖:
實現代碼如下
view
<canvas id="radar-canvas" class="radar-canvas" type="2d"></canvas>
style
.radar-canvas width 550rpx height 550rpx margin 0 auto
script
<script> import { toRpx } from "@/utils/common" const numCount = 5 //元素個數 const numSlot = 4 //一條線上的總節點數 const mW = toRpx(275) //Canvas的寬度 const mCenter = mW / 2 //中心點 const mAngle = Math.PI * 2 / numCount //角度 const mRadius = mCenter - toRpx(43) //半徑(減去的值用於給繪制的文本留空間) let canvas = null // canvas let canvasCtx = null // canvas context export default { name: 'RadarChart', props: { }, methods: { // 初始化雷達圖,在組件掛載的時候執行 initDrawRadar() { console.log('init') const query = uni.createSelectorQuery().in(this) query.select('#radar-canvas').fields({ node: true, size: true }).exec((res) => { canvas = res[0].node canvasCtx = canvas.getContext('2d') const dpr = uni.getSystemInfoSync().pixelRatio canvas.width = res[0].width * dpr canvas.height = res[0].height * dpr canvasCtx.scale(dpr, dpr) }) }, // 開始執行繪制 handleDraw(radarData) { this.drawEdge() this.drawLinePoint() this.drawText(radarData) this.drawSubText(radarData) this.drawEdgeDot() this.drawRegion(radarData, 'rgba(255, 105, 81, 0.4)') }, // 繪制圓邊 drawEdge() { canvasCtx.strokeStyle = '#EEEEEE' for (let i = 0; i < numSlot; i++) { // 計算半徑 let radius = mRadius / numSlot * (i + 1) if (i === 3) { canvasCtx.lineWidth = toRpx(4) // 設置線寬 canvasCtx.beginPath() canvasCtx.arc(mCenter, mCenter, radius, 0, 2 * Math.PI,) // 開始畫圓 canvasCtx.stroke() } else { canvasCtx.lineWidth = toRpx(1) const space = 60 + 10 * (i+1) this.drawDashCircle(mCenter, mCenter, radius, space) } } }, // 繪制外邊框圓點 drawEdgeDot(x, y) { canvasCtx.fillStyle = '#EEEEEF' canvasCtx.beginPath() for (let k = 0; k < numCount; k++) { let x = mCenter + mRadius * Math.cos(mAngle * k - Math.PI / 2) let y = mCenter + mRadius * Math.sin(mAngle * k - Math.PI / 2) canvasCtx.arc(x, y, toRpx(5), Math.PI * 2, 0, true) canvasCtx.closePath() } canvasCtx.fill() }, // 繪制虛線圓 drawDashCircle(x, y, radius, space = 100) { const gap = 2 * Math.PI / space canvasCtx.lineCap ='square' let start = 0; //從原點開始畫 while (start <= 2 * Math.PI) { let end = start + gap canvasCtx.beginPath() //開始一個新的路徑 canvasCtx.arc(x, y, radius, start, end, false) start = gap + end canvasCtx.stroke() //對當前路徑進行描邊 } }, // 繪制連接點 drawLinePoint() { canvasCtx.lineWidth = toRpx(1) canvasCtx.beginPath() for (let k = 0; k < numCount; k++) { let x = mCenter + mRadius * Math.cos(mAngle * k - Math.PI / 2) let y = mCenter + mRadius * Math.sin(mAngle * k - Math.PI / 2) canvasCtx.moveTo(mCenter, mCenter) canvasCtx.lineTo(x, y) } canvasCtx.stroke() }, // 繪制文本信息 drawText(mData) { canvasCtx.fillStyle = '#222325' canvasCtx.font = `bold ${toRpx(14)}px PingFangSC-Medium, PingFang SC` //設置字體 for (let n = 0; n < numCount; n++) { let x = mCenter + mRadius * Math.cos(mAngle * n - Math.PI / 2) let y = mCenter + mRadius * Math.sin(mAngle * n - Math.PI / 2) //通過不同的位置,調整文本的顯示位置 const text = mData[n][0] if (n === 0) { canvasCtx.fillText(text, x - toRpx(12), y - toRpx(30)) } if (n === 1) { canvasCtx.fillText(text, x + toRpx(12), y) } if (n === 2) { canvasCtx.fillText(text, x + toRpx(12), y + toRpx(20)) } if (n === 3) { canvasCtx.fillText(text, x - toRpx(36), y + toRpx(20)) } if (n === 4) { canvasCtx.fillText(text, x - toRpx(40), y) } } }, // 繪制文本信息 drawSubText(mData) { canvasCtx.fillStyle = '#8D949B' canvasCtx.font = `${toRpx(11)}px PingFangSC-Medium, PingFang SC` //設置字體 for (let n = 0; n < numCount; n++) { const x = mCenter + mRadius * Math.cos(mAngle * n - Math.PI / 2) const y = mCenter + mRadius * Math.sin(mAngle * n - Math.PI / 2) //通過不同的位置,調整文本的顯示位置 const text = `(${mData[n][1]})` if (n === 0) { canvasCtx.fillText(text, x - canvasCtx.measureText(text).width / 2, y - toRpx(10)) } if (n === 1) { canvasCtx.fillText(text, x + canvasCtx.measureText(text).width, y + toRpx(16)) } if (n === 2) { canvasCtx.fillText(text, x + canvasCtx.measureText(text).width - toRpx(4), y + toRpx(40)) } if (n === 3) { canvasCtx.fillText(text, x - canvasCtx.measureText(text).width - toRpx(12), y + toRpx(40)) } if (n === 4) { canvasCtx.fillText(text, x - canvasCtx.measureText(text).width - toRpx(16), y + toRpx(16)) } } }, //繪制紅色數據區域(數據和填充顏色) drawRegion(mData, color){ canvasCtx.strokeStyle = '#FF6951' canvasCtx.lineWidth = toRpx(4) // 設置線寬 canvasCtx.beginPath() for (let m = 0; m < numCount; m++){ let x = mCenter + mRadius * Math.cos(mAngle * m - Math.PI / 2) * mData[m][1] / 100 let y = mCenter + mRadius * Math.sin(mAngle * m - Math.PI / 2) * mData[m][1] / 100 canvasCtx.lineTo(x, y) } canvasCtx.closePath() canvasCtx.fillStyle = color canvasCtx.fill() canvasCtx.stroke() }, }, mounted() { this.initDrawRadar() } } </script>
要註意的點是,這裡是封裝成組件調用,在初始化的時候,const query = uni.createSelectorQuery().in(this),要加上in(this),否則會報找不到node節點的錯誤信息
export function toRpx(val) { const res = uni.getSystemInfoSync() const scaleRate = res.windowWidth / 375 return val * scaleRate }
在頁面中調用
<template> <!--雷達圖--> <radar-chart :radarData="radarData" ref="radarRef"></radar-chart> </template> import RadarChart from './components/radar' export default { components: { RadarChart, }, data() { return { radarData:[["聽力", 0], ["口語",0], ["語法",0], ["詞匯",0], ["閱讀",0]], } }, methods: { getData() { // 請求數據返回後,調用組件方法渲染 this.$refs.radarRef.handleDraw(this.radarData) } } }
總結
到此這篇關於uniapp封裝小程序雷達圖組件的文章就介紹到這瞭,更多相關uniapp封裝小程序雷達圖組件內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!