全国免费咨询:

13245491521

VR图标白色 VR图标黑色
X

中高端软件定制开发服务商

与我们取得联系

13245491521     13245491521

2024-12-10_老板不让用ECharts,还想让我画很多圆环!

您的位置:首页 >> 新闻 >> 行业资讯

老板不让用ECharts,还想让我画很多圆环! 点击关注公众号,“技术干货”及时达! 需求简介这几天下来个新需求:「要在页面上动态渲染多个表格,每个表格内还要实现若干圆环!」 刚拿到这个需求的时候,我第一反应是用echarts实现,简单快捷 然而,老板无情的拒绝了我!他说: ?咱这个项目就一个独立页面,你引入个ECharts项目又要大很多!而且一个页面这么多ECharts实例,性能怎么保障?不准用ECharts,用CSS实现! ?没办法,我只好百度如何用CSS画圆环。幸运的是,我确实找到了类似的文章: 「不幸的事」,效果和我的差异很大,代码根本 无法复用!没办法,只能用别的办法实现了。经过一番研究,最终借助「Canvas」搞出来了,简单的分享一下我的实现思路吧。 圆环组件简介为了方便复用,我把这个功能封装成了项目可直接复用的组件。并支持自定义圆环大小、圆环宽度和圆环颜色比例配置属性。 Ring :storkWidth="5" :size="60" :ratioList="[ { ratio: 0.3, color: '#FF5733' }, { ratio: 0.6, color: '#33FF57' }, { ratio: 0.1, color: '#3357FF' } ]"/Ring 技术方案实现目标根据我们的UX需求,我们需要实现一个简单的组件,该组件可以展示一个圆环图表,并根据外部传入的比例数据(如 ratioList)绘制不同颜色的环形区域。 使用 Vue 3 和 TypeScript。动态绘制环形图,根据传入的数据绘制多个环。支持自定义环形图的大小和环宽。创建 Vue 组件框架首先,我们创建一个名为 RingChart.vue的组件。组件的初始结构非常简单,只包含一个 canvas 元素。 template !-- 创建一个 canvas 元素,用于绘制图表 -- canvas ref="canvasDom"/canvas/template script lang="ts" setupimport { ref, onMounted } from 'vue'; // 获取 canvas DOM 元素的引用const canvasDom = refHTMLCanvasElement | null(null); // 初始化 canvas 和上下文变量let ctx: CanvasRenderingContext2D | null = null;let width: number, height: number; // 初始化 canvas 尺寸和绘图环境const initCanvas = () = { const dom = canvasDom.value; if (!dom) return; ctx = dom.getContext('2d'); if (!ctx) return; // 设置 canvas 的宽高 dom.width = dom.offsetWidth; dom.height = dom.offsetHeight; width = dom.offsetWidth; height = dom.offsetHeight;}; // 在组件挂载后执行初始化onMounted(() = { initCanvas();});/script style scopedcanvas { width: 100%; height: 100%;}/style上述代码中,我们初始化了 canvas 元素,并且设定了 width 和 height 属性。 绘制基本的圆环接下来,我们添加「绘制圆环」的功能:通过 arc 方法来绘制圆环,设置 lineWidth 来调整环的宽度。 script lang="ts" setupimport { ref, onMounted } from 'vue'; // 获取 canvas DOM 元素的引用const canvasDom = refHTMLCanvasElement | null(null); // 初始化 canvas 和上下文变量let ctx: CanvasRenderingContext2D | null = null;let width: number, height: number; // 初始化 canvas 尺寸和绘图环境const initCanvas = () = { const dom = canvasDom.value; if (!dom) return; ctx = dom.getContext('2d'); if (!ctx) return; // 设置 canvas 的宽高 dom.width = dom.offsetWidth; dom.height = dom.offsetHeight; width = dom.offsetWidth; height = dom.offsetHeight; // 调用绘制圆环的方法 drawCircle({ ctx, x: width / 2, y: height / 2, radius: 8, lineWidth: 4, color: '#C4C9CF4D', startAngle: -Math.PI / 2, endAngle: Math.PI * 1.5, });}; // 绘制一个圆环的方法const drawCircle = ({ ctx, x, y, radius, lineWidth, color, startAngle, endAngle,}: { ctx: CanvasRenderingContext2D; x: number; y: number; radius: number; lineWidth: number; color: string; startAngle: number; endAngle: number;}) = { ctx.beginPath(); ctx.arc(x, y, radius, startAngle, endAngle); ctx.lineWidth = lineWidth; ctx.strokeStyle = color; ctx.stroke(); ctx.closePath();}; onMounted(() = { initCanvas();});/scriptdrawCircle 函数是绘制圆环的核心。我们通过 arc 方法绘制圆形路径,使用 lineWidth 来调整环的宽度,并用 strokeStyle 给圆环上色。startAngle 和 endAngle 参数决定了圆环的起始和结束角度,通过改变它们可以控制环的覆盖区域。绘制多个环形区域现在,我们来实现绘制多个环形区域的功能。我们将通过传入一个 ratioList 数组来动态生成多个环,每个环代表不同的比例区域。 script lang="ts" setupimport { ref, computed, onMounted } from 'vue'; // 定义 props 的类型interface RatioItem { ratio: number; color: string;} const props = defineProps{ size?: number; // 画布大小 storkWidth?: number; // 环的宽度 ratioList?: RatioItem[]; // 比例列表} // 默认值const defaultSize = 200;const defaultStorkWidth = 4;const defaultRatioList: RatioItem[] = [ { ratio: 1, color: '#C4C9CF4D' },]; // canvas DOM 和上下文const canvasDom = refHTMLCanvasElement | null(null);let ctx: CanvasRenderingContext2D | null = null; // 动态计算 canvas 的中心点和半径const size = computed(() = props.size || defaultSize);const center = computed(() = ({ x: size.value / 2, y: size.value / 2,}));const radius = computed(() = size.value / 2 - (props.storkWidth || defaultStorkWidth)); // 初始化 canvasconst initCanvas = () = { const dom = canvasDom.value; if (!dom) return; ctx = dom.getContext('2d'); if (!ctx) return; dom.width = size.value; dom.height = size.value; drawBackgroundCircle(); drawDataRings();}; // 绘制背景圆环const drawBackgroundCircle = () = { if (!ctx) return; drawCircle({ ctx, x: center.value.x, y: center.value.y, radius: radius.value, lineWidth: props.storkWidth || defaultStorkWidth, color: '#C4C9CF4D', startAngle: -Math.PI / 2, endAngle: Math.PI * 1.5, });}; // 绘制数据圆环const drawDataRings = () = { const { ratioList = defaultRatioList } = props; if (!ctx) return; let startAngle = -Math.PI / 2; ratioList.forEach(({ ratio, color }) = { const endAngle = startAngle + ratio * Math.PI * 2; drawCircle({ ctx, x: center.value.x, y: center.value.y, radius: radius.value, lineWidth: props.storkWidth || defaultStorkWidth, color, startAngle, endAngle, }); startAngle = endAngle; });}; // 通用绘制函数const drawCircle = ({ ctx, x, y, radius, lineWidth, color, startAngle, endAngle,}: { ctx: CanvasRenderingContext2D; x: number; y: number; radius: number; lineWidth: number; color: string; startAngle: number; endAngle: number;}) = { ctx.beginPath(); ctx.arc(x, y, radius, startAngle, endAngle); ctx.lineWidth = lineWidth; ctx.strokeStyle = color; ctx.stroke(); ctx.closePath();}; // 监听画布大小变化onMounted(() = { initCanvas();});/script上述代码中,我们通过 ratioList 数组传递每个环的比例和颜色,使用 startAngle 和 endAngle 来控制每个环的绘制区域。其中,drawDataRings 函数遍历 ratioList,根据每个数据项的比例绘制环形区域。 现在,我们的组件就实现完毕了,可以在其他地方引入使用了 RingChart :storkWidth="8" :size="60" :ratioList="[ { ratio: 0.3, color: '#F8766F' }, { ratio: 0.6, color: '#69CD90' }, { ratio: 0.1, color: '#FFB800' } ]"/RRingChart 组件代码template canvas ref="canvasDom"/canvas/template script lang="ts" setupimport { ref, computed, onMounted, watchEffect } from 'vue'; // 定义 props 的类型interface RatioItem { ratio: number; color: string;} const props = defineProps{ size?: number; // 画布大小 storkWidth?: number; // 环的宽度 ratioList?: RatioItem[]; // 比例列表} // 默认值const defaultSize = 200; // 默认画布宽高const defaultStorkWidth = 4;const defaultRatioList: RatioItem[] = [{ ratio: 1, color: '#C4C9CF4D' }]; // canvas DOM 和上下文const canvasDom = refHTMLCanvasElement | null(null);let ctx: CanvasRenderingContext2D | null = null; // 动态计算 canvas 的中心点和半径const size = computed(() = props.size || defaultSize);const center = computed(() = ({ x: size.value / 2, y: size.value / 2}));const radius = computed(() = size.value / 2 - (props.storkWidth || defaultStorkWidth)); // 初始化 canvasconst initCanvas = () = { const dom = canvasDom.value; if (!dom) return; ctx = dom.getContext('2d'); if (!ctx) return; dom.width = size.value; dom.height = size.value; drawBackgroundCircle(); drawDataRings();}; // 绘制背景圆环const drawBackgroundCircle = () = { if (!ctx) return; drawCircle({ ctx, x: center.value.x, y: center.value.y, radius: radius.value, lineWidth: props.storkWidth || defaultStorkWidth, color: '#C4C9CF4D', startAngle: -Math.PI / 2, endAngle: Math.PI * 1.5 });}; // 绘制数据圆环const drawDataRings = () = { const { ratioList = defaultRatioList } = props; if (!ctx) return; let startAngle = -Math.PI / 2; ratioList.forEach(({ ratio, color }) = { const endAngle = startAngle + ratio * Math.PI * 2; drawCircle({ ctx, x: center.value.x, y: center.value.y, radius: radius.value, lineWidth: props.storkWidth || defaultStorkWidth, color, startAngle, endAngle }); startAngle = endAngle; });}; // 通用绘制函数const drawCircle = ({ ctx, x, y, radius, lineWidth, color, startAngle, endAngle}: { ctx: CanvasRenderingContext2D; x: number; y: number; radius: number; lineWidth: number; color: string; startAngle: number; endAngle: number;}) = { ctx.beginPath(); ctx.arc(x, y, radius, startAngle, endAngle); ctx.lineWidth = lineWidth; ctx.strokeStyle = color; ctx.stroke(); ctx.closePath();}; // 监听画布大小变化watchEffect(() = { initCanvas();}); onMounted(() = { initCanvas();});/script style scopedcanvas { display: block; margin: auto; border-radius: 50%;}/style使用 Ring :storkWidth="5" :size="60" :ratioList="[ { ratio: 0.3, color: '#FF5733' }, { ratio: 0.6, color: '#33FF57' }, { ratio: 0.1, color: '#3357FF' } ]"/Ring点击关注公众号,“技术干货”及时达! 阅读原文

上一篇:2021-09-23_深入浅出虚拟 DOM 和 Diff 算法,及 Vue2 与 Vue3 中的区别 下一篇:2025-09-11_关系5.0

TAG标签:

15
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设网站改版域名注册主机空间手机网站建设网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。
项目经理在线

相关阅读 更多>>

猜您喜欢更多>>

我们已经准备好了,你呢?
2022我们与您携手共赢,为您的企业营销保驾护航!

不达标就退款

高性价比建站

免费网站代备案

1对1原创设计服务

7×24小时售后支持

 

全国免费咨询:

13245491521

业务咨询:13245491521 / 13245491521

节假值班:13245491521()

联系地址:

Copyright © 2019-2025      ICP备案:沪ICP备19027192号-6 法律顾问:律师XXX支持

在线
客服

技术在线服务时间:9:00-20:00

在网站开发,您对接的直接是技术员,而非客服传话!

电话
咨询

13245491521
7*24小时客服热线

13245491521
项目经理手机

微信
咨询

加微信获取报价