使用canvas仿Echarts实现金字塔图的实例代码
时间:2023-12-30 08:33:34 来源:[db:出处] 作者:[db:作者] 阅读:
前言
最近公司项目都偏向于数字化大屏展示🥱,而这次发给我的项目原型中出现了一个金字塔图🤔️, 好巧不巧,由于我们的图表都是使用Echarts,而Echarts中又不支持金字塔图,作为一个喜欢造轮子的前端开发,虽然自身技术不咋滴,但喜欢攻克难题的精神还是有的😁, 不断地内卷,才是我们这些普通前端开发的核心竞争力😂,所以就有了仿Echarts实现金字塔图的想法。
不多说先上效果

项目地址:(https://github.com/SHDjason/Pyramid.git)
正文
项目实现可传入配置有:主体图位置(distance)、主体图偏移度(offset)、数据排序(sort)、图颜色(color)、数据文本回调(fontFormatter)、tooltip配置(tooltip)、数据展示样式配置(infoStyle)等

初始化canvas基本信息 并实现大小自适应
<template>
<div id="canvas-warpper">
<div id="canvas-tooltip"></div>
</div>
</template>
先创建 canvas画布
// 创建canvas元素
this.canvas = document.createElement('canvas')
// 把canvas元素节点添加在el元素下
el.appendChild(this.canvas)
this.canvasWidth = el.offsetWidth
this.canvasHeight = el.offsetHeight
// 将canvas元素设置与父元素同宽
this.canvas.setAttribute('width', this.canvasWidth)
// 将canvas元素设置与父元素同高
this.canvas.setAttribute('height', this.canvasHeight)
获取画布中心点 方便后面做自适应和定点
this.canvasCenter = [
Math.round((this.canvasWidth - this.integration.distance[0] * 2) / 2) + this.integration.distance[0],
Math.round((this.canvasHeight - this.integration.distance[1] * 2) / 2) + this.integration.distance[1]
]
监听传来的数据 并计算数据占比
刚好在这编写 数据排序(sort)的传入配置
watch: {
data: {
immediate: true,
deep: true,
handler(newValue) {
// 数据总量
let totalData = 0
newValue.forEach(element => {
totalData = totalData + Number(element.value)
})
this.dataInfo = newValue.map(item => {
const accounted = (item.value / totalData) * 100
return { ...item, accounted, title: this.integration.title }
})
if (this.integration.sort === 'max') {
this.dataInfo.sort((a, b) => {
return a.value - b.value
})
} else if (this.integration.sort === 'min') {
this.dataInfo.sort((a, b) => {
return b.value - a.value
})
}
}
}
},
下面可以确定金字塔4个基本点的位置了
这几个基本点的位置决定在后面金字塔展示的形状 可以根据自己的审美进行微调
if (this.canvas.getContext) {
this.ctx = this.canvas.getContext('2d')
// 金字塔基本点位置
this.point.top = [this.canvasCenter[0] - this.canvasWidth / 13, this.integration.distance[1]]
this.point.left = [
this.integration.distance[0] * 1.5,
this.canvasHeight - this.integration.distance[1] - this.canvasHeight / 5
]
this.point.right = [
this.canvasWidth - this.integration.distance[0] * 1.9,
this.canvasHeight - this.integration.distance[1] - this.canvasHeight / 5
]
this.point.bottom = [
this.canvasCenter[0] - this.canvasWidth / 13,
this.canvasHeight - this.integration.distance[1]
]
this.point.shadow = [
this.integration.distance[0] - this.canvasCenter[0] / 5,
this.canvasHeight / 1.2 - this.integration.distance[1]
]
for (const key in this.point) {
this.point[key][0] = this.point[key][0] + this.integration.offset[0]
this.point[key][1] = this.point[key][1] + this.integration.offset[1]
}
} else {
throw 'canvas下未找到 getContext方法'
}
本文配套模板、静态源码可前往艾立兹素材库alisucai.com下载
发表评论
共有0条评论
扫码关注公众号
获取全套技术教程