uniapp封装小程序雷达图组件的完整代码
作者:码克吐温 发布时间:2024-04-17 09:55:26
标签: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)
}
}
}
总结
来源:https://juejin.cn/post/6976173872445915144


猜你喜欢
- 自动追踪算法,在我们设计2D射击类游戏时经常会用到,这个听起来很高大上的东西,其实也并不是军事学的专利,在数学上解决的话需要去解微分方程,这
- 表单外观的美化很多时候,我们仅仅为了实现数据采集这个功能来使用表单,常看到的表单都是“千人一面”、毫无
- 本人刚开始学习python,看了一段时间视频教程之后,决定做一个小游戏来巩固一下知识点,就做了一个文字版飞行棋,暂不具备图形界面。把代码贴出
- 问题描述:通过EasyConnect登录后可以用xshell连接服务器,同时可以使用navicat和pymysql连接mysql数据库(无论
- 抽象工厂模式(Abstract Factory Pattern):属于创建型模式,它提供了一种创建对象的最佳方式。在抽象工厂模式中,接口是负
- python图片生成视频MP4import osimport cv2# 要被合成的多张图片所在文件夹# 路径分隔符最好使用“/”,而不是“\
- python对PPT演示文档读写,是通过第三方库python-pptx实现的,python-pptx是用于创建和更新 PowerPoint(
- 本文程序针对Python选课系统进行开发,供大家参考,具体内容如下角色:学校、学员、课程、讲师要求:1. 创建北京、上海 2 所学校2. 创
- 使用Pycharm的时候需要导入解释器然后安装一些第三方库,讲道理都是project Interpreter里面直接install的。但是打
- 本文实例讲述了python概率计算器实现方法。分享给大家供大家参考。具体实现方法如下:from random import randrang
- 最近在看红楼梦,看的诗词多了,时不时的也想来一句...这几天刚看看到了underscore.js的防抖和节流的部分,正好又去复习了这部分内容
- jupyter notebook 图片显示模糊的解决办法加入这几行代码即可:矢量图设置import matplotlib.pyplot as
- JSON(JavaScript Object Notation, JS 对象标记)是一种轻量级的数据交换格式,通常用于服务端向网页传递数据
- 前言:现在写爬虫,入门已经不是一件门槛很高的事情了,网上教程一大把,但很多爬虫新手在爬取数据的过程中依旧会遇到这样那样的问题。今天整理了部分
- 背景:我们有一个用go做的项目,其中用到了zmq4进行通信,一个简单的rpc过程,早期远端是使用一个map去做ip和具体socket的映射。
- torch.Tensor类型的数据loss和acc打印时如果写成以下写法print('batch_loss: '+str(l
- 操作步骤A.cmd输入:pip install requests,安装requestsB.py文件导入:import requestsC.g
- 前言一首歌热门了,参与评论的人也很多,这时无论好坏评论都来了,没有人控评得话,指不定乱七八糟但是自己有喜欢看评论,不想影响好心情,想看看精彩
- SQL Server会把经常使用到的数据缓存在内存里(就是数据页缓存),用以提高数据访问速度。因为磁盘访问速度远远低于内存,所以减少磁盘访问
- 一、引言池化技术在Java中应用的很广泛,简而论之,使用对象池存储某个实例数受限制的实例,开发者从对象池中获取实例,使用完之后再换回对象池,