跳转至

柿饼M之画布

上一节我们介绍了基本的动画操作,但那些都是针对已有的页面,图形对象的。本篇教程将向大家介绍如何在屏上实现自定义的绘画。

首先,要进行绘图必然得有一个绘图的目标区域,在PersimM中,可以在页面上单独提供一块画布,在这个画布上就可以进行绘图操作了。首先,我们在设计器上,在一个Page中添加一个Canvas对象,背景色设置为白色,字体选择hz 16,如下图所示。

上位机画布

具体关于画布的API请查阅Canvas API文档

基于脚本的画布

在设计器中我们把"Canvas1"画布对象拖放出来,会发现它的区域默认是没有其他额外的显示。要对画布对象操作,我们必须使用脚本的方式,我们在脚本中可以通过以下的方式返回这个名字为"Canvas1"的画布对象:

var context = pm.createCanvas("Canvas1", this);

一般的画布操作

饼图

在这一小节中,我们将介绍如何在画布上绘制一个饼图:

var data = [ 20, 30, 40, 50, 60, 70 ];  //饼图数据
var colors = [ "#ff0000", "#ffff00", "#ff00ff", "#00ff00", "#00ffff", "#0000ff"];   //饼图颜色
var context = pm.createCanvasContext('Canvas1', this)   //获取画布对象
if (context)
{
    var total = 0;  //饼图数据总和

    for( var index = 0; index < data.length; index++ )
    {
        total += data[ index ];
    }

    var point = { x: 200, y: 200 };     //圆心坐标,相对于画布
    var radius = 150;                   //半径
    var start = -0.5 * Math.PI;         //起始弧度

    for( var i = 0; i < data.length; i++ )
    {
        var stop = start + data[ i ] / total * 2 * Math.PI;     //结束弧度

        context.beginPath();    //开始新的路径

        context.arc( point.x, point.y, radius, start, stop, false);     //画一段圆弧

        context.lineTo( point.x, point.y );     //连接圆弧终点和圆心
        context.setFillStyle( colors[ i ] );    //设置填充颜色
        context.fill();                         //填充路径

        context.closePath();                    //关闭路径
        start = stop;                           //起始弧度更新
    }

    context.draw();     //更新画布
}

直接放到板子上,看看运行的效果,运行效果如下:

运行效果

  • 实际效果

实际效果demo1

柱形图

在这一小节中,我们将介绍如何在画布上绘制一份表示一年的月用电量的柱形图:

var index = 0
var data = [ 20, 30, 40, 50, 32, 56, 12, 34, 21, 23, 13, 46 ];  //柱形图数据
var context = pm.createCanvasContext('Canvas1', this)           //获取画布对象
if (context)
{
    var max = 0;

    for( index = 0; index < data.length; index++ )
    {
        max = data[index] > max ? data[index] : max;
    }

    max = Math.floor(max / 6);

    /* 画浅灰色横线 */
    context.beginPath();                //开启新路径
    context.setStrokeStyle('#C0C0C0')   //设置边框颜色

    for( index = 0; index < 7; index++ )
    {
        var y = 30 + index * 50;
        context.moveTo(60, y)                   //线条起点
        context.lineTo(60 + 12 * 28 + 14, y)    //线条终点
    }

    context.stroke()        //画线
    context.closePath();    //关闭当前路径

    /* 画横纵坐标刻度 */
    context.beginPath();            //开启新路径
    context.setStrokeStyle('black') //设置边框颜色

    context.fillText('用电量(度)', 5, 5)    //绘制文字,坐标(5,5)

    context.setTextBaseline('middle')         //设置文本绘制纵坐标对齐方式
    for( index = 0; index < 7; index++ )
    {
        var y = 30 + index * 50;
        var value = max * (7 - index);
        /*纵坐标刻度*/
        context.moveTo(55, y)
        context.lineTo(60, y)
        context.fillText(value.toString(), 20, y)
    }

    context.moveTo(55, 30 + index * 50)
    context.lineTo(60, 30 + index * 50)
    context.fillText('0', 20, 30 + index * 50)

    context.moveTo(60, 30)
    context.lineTo(60, 30 + index * 50)

    context.moveTo(60, 30 + index * 50)
    context.lineTo(60 + 12 * 28 + 14, 30 + index * 50)

    context.setTextAlign('center')  //设置文本绘制横坐标对齐方式

    for( index = 1; index <= 12; index++ )
    {
        var x = 60 - 14 + index * 28;
        /*横坐标刻度*/
        context.moveTo(x, 380)
        context.lineTo(x, 385)
        context.fillText(index.toString(), x, 395)
    }

    context.setTextAlign('left')    //设置文本绘制横坐标对齐方式
    context.fillText('时间(月)', 60 + 12 * 28 + 14, 390)
    context.stroke()
    context.closePath();

    /* 画柱形 */
    context.beginPath();
    context.setStrokeStyle('#0094FF')
    context.setLineWidth(18)        //设置线条宽度

    for( index = 0; index < data.length; index++ )
    {
        var x = 60 - 14 + 28 + index * 28;
        var y = data[index] * 350 / (max * 7)
        context.moveTo(x, 380)
        context.lineTo(x, 380 - y)
    }

    context.stroke()
    context.closePath();

    context.draw();
}

直接放到板子上,看看运行的效果,运行效果如下:

运行效果

  • 实际效果

实际效果demo2

仪表盘

在这一小节中,我们将介绍如何在画布上绘制一份仪表盘:

var context = pm.createCanvasContext('Canvas1', this)   //获取画布对象
if (context)
{
    var point = { x: 200, y: 200 };     //圆心坐标,相对于画布
    var radius = 150;                   //半径
    var start = -1.25 * Math.PI;        //起始弧度

    context.setLineWidth(30)
    context.setStrokeStyle('#91C7AE')
    context.setFillStyle('#91C7AE');

    for( var i = 0; i <= 10; i++ )
    {
        var stop = start + 0.15 * Math.PI ;     //结束弧度
        var x = Math.floor(130 * Math.cos(start)) + 200;
        var y = Math.floor(130 * Math.sin(start)) + 200;
        var v = 10 * i;

        if (i >= 5)
            context.fillText(v.toString(), x - 20, y);
        else
            context.fillText(v.toString(), x, y);

        if (i == 10)
            break;

        context.beginPath();    //开始新的路径

        context.arc( point.x, point.y, radius, start, stop - 0.003 * Math.PI, false);     //画一段圆弧

        context.stroke();                         //填充路径

        context.closePath();                    //关闭路径
        start = stop;

        if (i == 1)
        {
            context.setStrokeStyle('#63869E')
            context.setFillStyle('#63869E');
        }
        else if (i == 7)
        {
            context.setStrokeStyle('#C23531')
            context.setFillStyle('#C23531');
        }
    }

    radius = 170;
    start = -1.25 * Math.PI; 
    context.setLineWidth(22)
    context.setStrokeStyle('#91C7AE')

    for( var i = 0; i < 50; i++ )
    {
        var stop = start + 0.03 * Math.PI ;

        context.beginPath();

        context.arc( point.x, point.y, radius, start, stop - 0.003 * Math.PI, false);

        context.stroke();

        context.closePath();
        start = stop;

        if (i == 9)
        {
            context.setStrokeStyle('#63869E')
        }
        else if (i == 39)
        {
            context.setStrokeStyle('#C23531')
        }
    }

    {   //画指针
        var value = 60;     //表盘当前值
        var radius = 130;
        var x = Math.floor(radius * Math.cos((-1.25 * Math.PI + value * 1.5 * Math.PI / 100))) + point.x;
        var y = Math.floor(radius * Math.sin((-1.25 * Math.PI + value * 1.5 * Math.PI / 100))) + point.y;

        context.beginPath();

        context.setFillStyle('#91C7AE');
        context.moveTo(x, y)

        radius = 10;
        x = Math.floor(radius * Math.cos((-0.75 * Math.PI + value * 1.5 * Math.PI / 100))) + point.x;
        y = Math.floor(radius * Math.sin((-0.75 * Math.PI + value * 1.5 * Math.PI / 100))) + point.y;
        context.lineTo(x, y);

        radius = 20;
        x = Math.floor(radius * Math.cos((-0.25 * Math.PI + value * 1.5 * Math.PI / 100))) + point.x;
        y = Math.floor(radius * Math.sin((-0.25 * Math.PI + value * 1.5 * Math.PI / 100))) + point.y;
        context.lineTo(x, y);

        radius = 10;
        x = Math.floor(radius * Math.cos((0.25 * Math.PI + value * 1.5 * Math.PI / 100))) + point.x;
        y = Math.floor(radius * Math.sin((0.25 * Math.PI + value * 1.5 * Math.PI / 100))) + point.y;
        context.lineTo(x, y);

        context.fill();

        context.setTextAlign('center')
        context.fillText(value.toString(), 200, 250)

        context.closePath();
    }

    context.draw();
}

直接放到板子上,看看运行的效果,运行效果如下:

运行效果

  • 实际效果

    实际效果demo3

评论