微信小程序canvas 绘制图表

本文介绍了如何基于D3.js库简化实现线性比例尺、序数比例尺和饼图比例尺,并展示了在小程序中应用这些自定义组件进行数据可视化的例子。作者通过仿照Echarts的配置方式,创建了柱状图和饼图的示例,实现了数据驱动的图表绘制。
摘要由CSDN通过智能技术生成

之前做了一个问卷小程序,做了一个将数据可视化保存为图片,如下:
在这里插入图片描述
当时仅仅实现绘制饼图,现在有个想法把柱状图、折线图等补齐。说干就干。
先放源码

d3.js 可视化库

之前有粗略学习过d3.js, 觉得D3 使用scale 类型的函数处理数据十分方便,于是想把scale放在小程序中引用,殊不知文件太大了,不方便操作。于是便粗略的自己实现了几个。这些方法将会再绘制图表中处理数据使用。

linearScale

// 映射 值域

class MyScaleLinear {
    constructor() {
        this.domainVal = []
        this.rangeVal = []
    }
    domain(arr) {
        try {
            if (!Array.isArray(arr)) throw 'domain 参数不是一个数组!';
            if (arr.length !== 2)    throw 'domain 数组长度不为2';
            this.domainVal = [...arr];
        }
        catch (e) {
            console.error(e)
        }
        return this;
    }
    range(arr) {
        try {
            if (!Array.isArray(arr)) throw 'domain 参数不是一个数组!';
            if (arr.length !== 2)    throw 'domain 数组长度不为2';
            this.rangeVal = [...arr];
        }
        catch (e) {
            console.error(e)
        }
        return this.findRange.bind(this);
    }

    findRange(val){
        let  result = (val - this.domainVal[0]) / (this.domainVal[1] - this.domainVal[0]) *  (this.rangeVal[1] - this.rangeVal[0]) +  this.rangeVal[0];
        return result
    }

}

export default MyScaleLinear

OrdinalScale

// 数组map
class  MyScaleOrdinal {
    constructor() {
        this.domainVal = []
        this.rangeVal = []
    }
    domain(arr) {
        try {
            if (!Array.isArray(arr)) throw 'domain 参数不是一个数组。'
            this.domainVal = [...arr]
        } catch (e) {
            console.error(e)
        }
        return this
    }
    range(arr) {
        try {
            if (!Array.isArray(arr)) throw 'range 参数不是一个数组。'
            this.rangeVal = [...arr]
        } catch (e) {
            console.error(e)
        }
        return this.findRange.bind(this);
    }
    findRange(val){
        let index = this.domainVal.findIndex((item) => item === val);
        let rlen = this.rangeVal.length
        if (rlen > index) return this.rangeVal[index]
        return this.rangeVal[index % rlen];
    }
	
	

}

export default MyScaleOrdinal;

ScalePie

// 饼图角度
class  MyScalePie{
    constructor() {
        this.arcData = []
        this.hasValueFunc =  false
        this.valueFunc = null
    }
    value(fn) {
        this.hasValueFunc = true;
        this.valueFunc = fn
        return this
    }
    getArcs(arr) {
        try {
            if (!Array.isArray(arr)) throw  'getArcs 参数为非数组'
            this.arcData = [...arr]
            this.arcData.sort((a, b) =>{
                if (this.hasValueFunc) return this.valueFunc(b) - this.valueFunc(a)
                return b - a
            })
            let totals  = this.arcData.reduce((total, num) => {
                if ( this.hasValueFunc) return total + this.valueFunc(num)
                return total + num
            },0)
            let result = []
            let resObj = {}
            let resValue = 0
            let lastAngle = 0
            let currentAngle = 0
            this.arcData.forEach((num)=>{
                resValue = num
                if ( this.hasValueFunc)  resValue = this.valueFunc(num)
                currentAngle = lastAngle + resValue / totals * Math.PI * 2
                resObj = {
                    data: num,
                    value: resValue,
                    startAngle: lastAngle,
                    endAngle: currentAngle
                }
                result.push(resObj)
                lastAngle = currentAngle
            })
            return  result
        } catch (e) {
            console.error(e)
        }
        return []
    }

}

export default MyScalePie

效果

经常使用的是 Echart 可视化,对它的数据配置以及新版的颜色认可。便粗略仿照它的样子去实现。效果如下:

柱状图:

在这里插入图片描述

在这里插入图片描述
饼图:
在这里插入图片描述
折线图
在这里插入图片描述
雷达图
在这里插入图片描述
仪表盘
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天也想MK代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值