预备知识
Scratch中的画笔除了绘制简单的几何图形,比如圆、多边形等,还可以用来画生活中常见的统计图形。什么是统计图形呢?统计图是利用点、线、面、体等绘制成几何图形,以表示各种数量间的关系及其变动情况的工具。

为什么要使用统计图?因为人对图形比数字敏感,面对一大堆数字,你不容易发现它们之间的关系。而把数字用图形的方式表示出来,就会一目了然,更加形象和生动。比如这张显示居民消费结构的图,即使没有数据,你也可以很轻松地从图上看出不同消费类型大概的比例。

常见的统计图形有条形图、柱形图、饼图、折线图等。不同类型的统计图有它们侧重的领域。我们今天关注的是折线图。折线图用线条的升降表示事物的发展变化趋势,主要用于描述两个变量间关系。比如随着时间变化居民收入的增长趋势,随着年龄增长身高的变化趋势等。
问题
提供一组洛阳市2021年各月份的最高平均气温和最低平均气温,要求使用Scratch画出随温度月份变化的折线图。
| 月份 |
1 月 |
2月 |
3月 |
4月 |
5月 |
6月 |
7月 |
8月 |
9月 |
10月 |
11月 |
12月 |
| 平均最高气温 |
8 |
14 |
16 |
20 |
29 |
34 |
32 |
29 |
26 |
19 |
15 |
10 |
| 平均最低气温 |
-3 |
2 |
6 |
10 |
16 |
22 |
23 |
21 |
18 |
10 |
4 |
-1 |
分析
我们知道使用Scratch画线条是非常简单的,只要保持落笔状态,让角色移动,角色移动的轨迹就会形成线。现在有12个月的数据,如果我们用月份(1-12)作为X坐标,温度作为Y坐标,可以把最高气温转换为坐标列表: - (1,8) - (2,14) - (3,16) - (4,20) - (5,29) - (6,34) - (7,32) - (8,29) - (9,26) - (10,19) - (11,15) - (12,10)
对最低气温也可以做同样的转换。那我们是不是让画笔角色依次移动到这些坐标就可以画出一条折线了呢?就像下图这样自左向右画:

理论上可以,但实际上行不通。为什么呢?从上图可以看出来,Scratch的舞台X坐标是 - 240到 240,如果我们就以 1至12作为X坐标,气温做Y座标,那么在图上画出来的就是短短一条线,别说美观了,可能连样子都看不清。因此,我们必须充分利用舞台的空间,把1-12月均匀地分布在舞台的横向距离上,同时也把气温均匀地分布在舞台的纵向距离上。也就是说,我们要在舞台上均匀地画一些“格子”,用这些格子的格数代表月份和气温,而不能直接使用Scratch舞台的原始坐标。如下图所示:

我们从舞台上选择一块矩形区域(红色框的范围),然后把这个框里面沿X轴方向画12条竖线,每条线代表1个月份,Y轴方向呢?观察前面的数据,我们发现最高的气温不超过40,最低的不超过-10,再留一些余量,可以用-20、-10、0、10、20、30、40、50作为温度的刻度,这样就需要画8条横线代表温度。画出了这个网格,我们就可以把实际的气温和月份换算成这个网格范围内的坐标,画出漂亮的图表了。你可能会问,为什么不把整个舞台布满?我们希望在网格旁边加上一些坐标值,把温度和月份标上去,会更直观一些。
现在问题的关键是,如何计算出每一条线的起点和终点坐标。我们把短形范围左下角的坐标设为 (X1,Y1) ,右上角坐标设为 (X2,Y2) ,那么:
- 画x轴方向的竖线时,可以设置变量 x ,从 X1 向 X2 逐渐增加,循环12次,画12条从(X,Y1) 到 (X,Y2) 的线。x 值每次增加多少呢?可以用变量 col_width 表示, col _width = (X2-X1) / (12-1) 。(X2-X1) 是从 X2 到 X1 的距离,把它分成11份(12条线中间的格子是11个)就得到 x 变量每次增加的距离了。
- 同理,画y轴方向的横线时,设置变量 y ,从 Y1 到 Y2 逐渐增加,循环8次,画8条从 (X1,Y) 到 (X2,Y) 的线。 y 值的增加量用变量 row_height 表示, row _height = (Y2 - Y1) /(8-1) 。
有了网格线,我们还需要把月份和气温转换成矩形范围内的坐标值,组成一对坐标值 (x,y) 供画笔使用:
- 月份对应 x = X1 + (月份-1) × col_width
- 温度对应 y = Y1 + (温度-(-20)) / (50-(-20)) × (Y2-Y1) = Y1 + (温度 + 20) / 70 × (Y2-Y1)
这里的温度坐标有点不太容易理解,实际上它是根据温度范围 (-20,50) 到 (-120,120) 的等比例关系 (Y坐标 - Y1 ) /( Y2-Y1 ) = (温度 - (-20)) / (50-(-20)) 换算得到的。这是本节最重要的一个变换。
有点麻烦是不是?静下心来看明白,写程序就没问题了(看来数学真的很重要啊!)
编程
一、建立画笔、月份坐标和度数坐标三个角色。画笔是关键角色,用来绘制图形;月份坐标有12个造型,用于生成克隆体,放在X轴方向做为坐标值;度数坐标有 -20、-10、0、10、20、30、40、50共8个造型,用来生成克隆体,放在Y轴方向作为坐标值。为了方便修改我们设定的绘图范围,我们把X1、Y1、X2、Y2、row_height、col_width都声明成变量,在程序启动时初始化。

二、首先画网格。自制积木如下(可以在新建时设置它为“运行时不刷新屏幕”以加快绘图):

三、为月份坐标角色建立一个私有变量“月份”,用于它生成的每个克隆体保存自己的月份值,然后根据月份计算出克隆体的造型和位置。其中,Y1-20是为了让它在网格底部一点距离外显示:

四、同样的方法为度数坐标角色建立私有变量“气温”,然后生成克隆体,移动到对应的位置。

这个时候加上调用,可以画出带坐标值的网格了。

五、现在做气温坐标值的转换和绘制函数:

六、主程序加上对绘制气温的调用:

七、现在,为背景加上图表标题和图例,运行程序,即可得到漂亮的拆线图:
[video width="848" height="638" mp4="https://cdn.scratch5.com/wp-content/uploads/2023/06/b3a7655a-c932-11ec-be0a-f26a0a946dd9-v4_t10000111-wfbYoBfNyO.mp4"][/video]
总结
本节我们采用画笔扩展绘制了一个不错的折线图,可以看出,问题的关键在于数据坐标到Scratch舞台坐标的转换。你可以试着调整X1、X2、Y1、Y2这些变量的值,看看图形会怎样变化。也可以试着调整温度范围,不过那样的话计算就稍微麻烦一些了,如果你真的掌握了这些内容,以后再画类似的折线图,都不可能难住你了。