Graphics饼状图/折线图

Cocos creator 2.4

饼状图
`cc.Class({
extends: cc.Component,
properties: {
中空: true,
半径: 300,
},

// LIFE-CYCLE CALLBACKS:

// onLoad () {},

start()
{
    let list = [
        {
            "type": "游戏",
            "number": Math.random() * 1000
        },
        {
            "type": "音乐",
            "number": Math.random() * 1000
        },
        {
            "type": "科技",
            "number": Math.random() * 1000
        },
        {
            "type": "新闻",
            "number": Math.random() * 1000
        },
        {
            "type": "电影",
            "number": Math.random() * 1000
        },
    ];
    this.colorChart = [
        cc.color(254, 67, 101), cc.color(252, 157, 154), cc.color(249, 205, 173), cc.color(200, 200, 169), cc.color(131, 175, 155),
        cc.color(182, 194, 154), cc.color(220, 87, 18), cc.color(137, 190, 178), cc.color(222, 221, 140), cc.color(222, 156, 83),
        cc.color(101, 147, 74),
    ];
    this.data = list;
    this.paint = this.node.addComponent(cc.Graphics);
    this.r_info = this.中空 ? 0.85 : 0.7
    this.drawSectorChart(this.半径, list);
},

//设置绘画信息
setInfo(r = this.半径, data)
{
    this.paint.clear(); // 清除它画过的图
    this.drawSectorChart(r, data);
},

//重绘
reStart(r = this.半径, data = this.data)
{
    this.paint.clear(); // 清除它画过的图
    this.drawSectorChart(r, data);
},


/**
 *绘制扇形统计图
 *
 * @param {*} r     半径
 * @param {*} info  信息    [{"type":"游戏","number":100},...]
 */
drawSectorChart(r, info)
{
    let sum = 0;
    let lastAngle = 0;
    this.shuffle(this.colorChart);
    for (let i = 0; i < info.length; i++)
    {
        sum += info[i].number;
    };
    for (let i = 0; i < info.length; i++)
    {
        let angle = 360 * info[i].number / sum;
        let showInfo = "  " + info[i].type + "\n" + (100 * info[i].number / sum).toFixed(2) + "%";
        let audio = info[i].number / sum
        this.drawTag2(r, lastAngle + angle / 2, showInfo, audio);
        this.drawSector(r, lastAngle, lastAngle + angle, this.colorChart[i % this.colorChart.length])
        lastAngle += angle
    };
    if (this.中空)
    {
        this.paint.fillColor = cc.color(255, 255, 255, 255);
        this.paint.circle(0, 0, r * 0.7);
        this.paint.fill();
    }
},

/**
 *绘制扇形区域
 *
 * @param {*} r             半径
 * @param {*} angleStart    起始角度
 * @param {*} angleEnd      结束角度
 * @param {*} color         颜色
 */
drawSector(r, angleStart, angleEnd, color)
{
    this.paint.lineWidth = 3;
    this.paint.moveTo(0, 0);
    this.paint.lineTo(r * Math.cos(angleStart * (Math.PI / 180)), r * Math.sin(angleStart * (Math.PI / 180)))
    this.paint.fillColor = color;
    this.paint.arc(0, 0, r, angleStart * Math.PI / 180, angleEnd * Math.PI / 180, true);
    this.paint.lineTo(0, 0)
    this.paint.fill();
    //绘制分割线
    if ((angleEnd - angleStart) > 10)//比例过小则不设置分割线
    {
        this.paint.lineWidth = 3;//设置宽度
        this.paint.strokeColor = new cc.Color(255, 255, 255);//设置线条颜色
        this.paint.moveTo(0, 0);
        this.paint.lineTo(r * Math.cos(angleStart * (Math.PI / 180)), r * Math.sin(angleStart * (Math.PI / 180)));
        this.paint.stroke();
        this.paint.moveTo(0, 0);
        this.paint.lineTo(r * Math.cos(angleEnd * (Math.PI / 180)), r * Math.sin(angleEnd * (Math.PI / 180)));
        this.paint.stroke();
    }

},

/**
 *样式1
 *绘制指示线条和文字
 * @param {*} r         半径
 * @param {*} angle     角度
 * @param {*} str       说明文字
 */
drawTag1(r, angle, str)
{
    //设置线条颜色
    this.paint.lineWidth = 3;//设置宽度
    this.paint.strokeColor = new cc.Color(0, 0, 0);
    //判断是否在第一三象限
    let ifRight = Math.floor(angle / 90) == 0 || Math.floor(angle / 90) == 3;
    //移动到扇形内
    r1 = r * 0.9;
    this.paint.moveTo(r1 * Math.cos(angle * (Math.PI / 180)), r1 * Math.sin(angle * (Math.PI / 180)))
    //绘制到扇形的路径
    r2 = r * 1.1;
    let x1 = r2 * Math.cos(angle * (Math.PI / 180));
    let y1 = r2 * Math.sin(angle * (Math.PI / 180));
    this.paint.lineTo(x1, y1)
    //平移出指示线路径
    let x2 = ifRight ? x1 + 100 : x1 - 100;
    this.paint.lineTo(x2, y1)
    //绘制
    this.paint.stroke()
    //添加文字说明
    let textNode = new cc.Node();
    let text = textNode.addComponent(cc.Label);
    this.node.addChild(textNode);
    text.string = str;
    textNode.x = ifRight ? x2 + 80 : x2 - 80;
    textNode.y = y1;
    textNode.height = Math.floor(r * 0.1);
    text.fontSize = textNode.height - 3;
    textNode.color = cc.Color(0, 0, 0);

},

/**
 *样式2
 *添加指示文字,过小的区域添加指示线条
 * @param {*} r      半径
 * @param {*} angle  角度
 * @param {*} str    说明文字
 * @param {*} ratio  所占比例
 */
drawTag2(r, angle, str, ratio)
{
    let x1 = this.r_info * r * Math.cos(angle * (Math.PI / 180));
    let y1 = this.r_info * r * Math.sin(angle * (Math.PI / 180));
    if (ratio > 0.06)
    {
        //添加文字说明
        let textNode = new cc.Node();
        let text = textNode.addComponent(cc.Label);
        this.node.addChild(textNode);
        text.string = str;
        textNode.x = x1;
        textNode.y = y1;
        textNode.height = Math.floor(r * 0.09);
        text.fontSize = textNode.height - 3;
        textNode.color = cc.Color(0, 0, 0);
    }
    else
    {
        this.drawTag1(r, angle, str)
    }
},

/**
 *洗牌算法
 *
 */
shuffle(list)
{
    for (let i = 0; i < list.length; i++)
    {
        let k = Math.floor(Math.random() * (list.length - i) + i);
        [list[i], list[k]] = [list[k], list[i]];
    }
}
// update (dt) {},

});
`

//折线图

`properties: {
height: 300,
width: 600,

},

start()
{
    this.paint = this.node.addComponent(cc.Graphics);
    this._leve = 10;
    let list = [];
    for (let i = 0; i < 10; i++)
    {
        list.push(Math.random() * 100);
    }
    this.drawLineChart(list, null, new cc.Color(255, 66, 66, 255));
},

drawLineChart(listY, listX, color)
{
    //计算数据
    let max = Math.max.apply(null, listY);
    let min = Math.min.apply(null, listY);
    let yd = this.height / (max - min);
    let xd = this.width / listY.length;

    //画横轴
    this.paint.lineWidth = 5;//设置宽度
    this.paint.strokeColor = new cc.Color(66, 66, 66, 66);
    this.paint.moveTo(0, 0);
    for (let i = 0; i <= this._leve; i++)
    {
        this.paint.moveTo(0, i * this.height / this._leve);
        this.paint.lineTo(this.width, i * this.height / this._leve);
        this.putLabel(-20, i * this.height / this._leve - 15, Math.floor((i * (max - min) / this._leve) + min), 25)
    }
    this.paint.stroke();


    //画数据线
    this.paint.lineWidth = 5;//设置宽度
    this.paint.strokeColor = color;
    this.paint.moveTo(0, (listY[0] - min) * yd);
    for (let i = 0; i < listY.length; i++)
    {
        this.paint.lineTo(i * xd, (listY[i] - min) * yd);
    }
    this.paint.stroke();


    //画 刻度,点,字
    this.paint.lineWidth = 4;//设置宽度
    this.paint.strokeColor = new cc.Color(66, 66, 66, 66);
    for (let i = 0; i < listY.length; i++)
    {
        this.paint.moveTo(i * xd, 0);
        this.paint.lineTo(i * xd, -10);
        this.paint.stroke();

        this.putPoint(i * xd, (listY[i] - min) * yd, 7, color)
        if (!!listX && !!listX[i])
        {
            this.putLabel(i * xd, -40, listX[i], 25)
        }
        else
        {
            this.putLabel(i * xd, -40, i, 25)
        }

    }


    cc.log(listY);

},

//字
putLabel(x, y, str, size)
{
    let textNode = new cc.Node();
    let text = textNode.addComponent(cc.Label);
    this.node.addChild(textNode);
    text.string = str;
    textNode.x = x
    textNode.y = y;
    textNode.height = size;
    text.fontSize = textNode.height - 3;
    textNode.color = cc.Color(0, 0, 0);
},

//画实心点
putPoint(x, y, r, color)
{
    this.paint.fillColor = color;
    this.paint.circle(x, y, r);
    this.paint.fill();
}`

不太会用这个markdown,总有部分代码超出…注意加上

8赞

感谢大佬分享 测试的时候发现折线图这里有个错误的地方 已经moveto到了第一个坐标 所以i的初始值应该是从1开始的 目前是0所以第一条线开始位置比较粗

mark一下

mark一下

学习一下下

感谢:grinning:,我说么这条线有点粗

mark一下

mark一下

为啥我的运行不起来报错Cannot read property ‘sub’ of undefined 去掉 this.paint.moveTo(0, 0); 解决的

mark!!!

请问,为什么我这边饼状图出现了,但是图上的文件内容都无法显示呢,打印发现texNode都是生成了的

刚好需要,准备移植到3.4,非常感谢