本期大纲

1、确定纵坐标的范围并绘制

2、根据真实数据绘制折线

相关阅读:
在微信小程序中绘制图表(part1)
在微信小程序中绘制图表(part3)

关注我的 github 项目 查看完整代码。

确定纵坐标的范围并绘制

为了避免纵坐标的刻度出现小数的情况,我们把纵坐标分为5个区块,我们取最小单位刻度为例如10(能够被5整除),当然真实情况会比这复杂,待会儿我们再讨论。

所以我们的处理输入输出应该是下面的结果

(5, 34.1)  => (10, 40)
(10, 34) => (10, 40)
(-5.1, 40) => (-10, 40)
// 确定Y轴取值范围
function findRange (num, type, limit) {
limit = limit || 10; // upper向上查找,lower向下查找
type = type ? type : 'upper'; // 进行取整操作,避免while时进入死循环
if (type === 'upper') {
num = Math.ceil(num);
} else {
num = Math.floor(num);
}
while (num % limit !== 0) {
if (type === 'upper') {
num++;
} else {
num--;
}
} return num;
}

好了,初步的确定范围已经完成了,但是细想一下这个范围还是不是很理想,比如用户传入的数据都是小数级别的,比如 (0.2, 0.8),我们输出的范围是(0, 5)这个范围偏大,图表展现的效果则会是上面有大部分的留白,同样用户输入的数据很大,比如(10000, 18000),我们得到的范围是(10000, 18010),这个范围则没什么意义,所以我们需要根据传入的数据的范围来分别确定我们的最小单位刻度。

规定我们的参数格式是这样的:

opts = {
...
series: [{
...
data: [15, 20, 45, 37, 4, 80]
}, {
...
data: [70, 40, 65, 100, 34, 18]
}
]
}

让我们继续进行优化

// 合并数据,将series中的每项data整合到一个数组当中
function dataCombine(series) {
return series.reduce(function(a, b) {
return (a.data ? a.data : a).concat(b.data);
}, []);
} // 根据数据范围确定最小单位刻度
function getLimit (maxData, minData)
var limit = 0;
var range = maxData - minData;
if (range >= 10000) {
limit = 1000;
} else if (range >= 1000) {
limit = 100;
} else if (range >= 100) {
limit = 10;
} else if (range >= 10) {
limit = 5;
} else if (range >= 1) {
limit = 1;
} else if (range >= 0.1) {
limit = 0.1;
} else {
limit = 0.01;
}
} var dataList = dataCombine(opts.series);
// 获取传入数据的最小值
var minData = Math.min.apply(this, dataList);
// 获取传入数据的最大值
var maxData = Math.max.apply(this, dataList); var limit = getLimit(maxData, minData); var minRange = findRange(minData, 'lower', limit);
var maxRange = findRange(maxData, 'upper', limit);

现在我们动态的确定除了合适的最小刻度范围,接下来我们接着优化一下上面的findRange方法,主要是增加对小数的支持

function findRange (num, type, limit) {
limit = limit || 10;
type = type ? type : 'upper';
var multiple = 1;
while (limit < 1) {
limit *= 10;
multiple *= 10;
}
if (type === 'upper') {
num = Math.ceil(num * multiple);
} else {
num = Math.floor(num * multiple);
}
while (num % limit !== 0) {
if (type === 'upper') {
num++;
} else {
num--;
}
} return num / multiple;
}

现在我们已经确定好了Y轴的取值范围,关于如何画出Y轴可以参看 part1 中X轴的绘制方法,此处不再累赘。

Y轴效果图:

opts = {
...
series: [{
...
data: [15, 20, 45, 37, 4, 80]
}, {
...
data: [70, 40, 65, 100, 34, 18]
}
]
}

opts = {
...
series: [{
...
data: [0.15, 0.2, 0.45, 0.37, 0.4, 0.8]
}, {
...
data: [0.30, 0.37, 0.65, 0.78, 0.69, 0.94]
}
]
}

效果还不错,我们接着往下

根据真实数据绘制折线

问题的关键在于确定每个数据点的(x, y)坐标,x坐标比较好确定,我们根据画布的宽度以及opts.categories即可确定。

规定我们的配置为:

config = {
xAxisHeight: 30, // X轴高度
yAxisWdith: 30 // Y轴宽度
}
var data = [15, 20, 45, 37, 4, 80];
var xPoints = [];
var validWidth = opts.width - config.yAxisWidth;
var eachSpace = validWidth / opts.categories.length;
var start = config.yAxisWidth; data.forEach(function (item, index) {
xPoints.push(start + (index + 0.5) * eachSpace);
});

y坐标稍微会复杂一点,需要根据Y轴的范围已经本身的数值进行计算得出。

所以我们计算出的y应该为

y = validHeight * (data - min) / (max - min);
// 由于canvas画布是左上角为原点坐标,故我们变化一下
// 得到最终的y绘制点
y = valideHeight - y;

代码如下:

var data = [15, 20, 45, 37, 4, 80];
var yPoints = [];
var validHeight = opts.height - config.xAxisHeight;
data.forEach(function(item) {
var y = validHeight * (item - min) / (max - min);
y = validHeight - y; yPoints.push(y);
}

现在我们已经确定了数据点在画布上的绘制坐标,关于如何绘制折现请查看 part1 中相关内容,此处不再累赘。

最终效果图如下:

预告:下一部分我们一起讨论绘制过程中的一些技巧、动画效果和如何工程化我们的项目。

相关阅读

在微信小程序中绘制图表(part1)
在微信小程序中绘制图表(part3)

本文转载于猿2048:在微信小程序中绘制图表(part2)

在微信小程序中绘制图表(part2)的更多相关文章

  1. 在微信小程序中使用图表

    前言:网上有许多的图表库,如:Echarts.Tau Charts.ChartJS等等,具体自行百度. 这次我们使用的是:Echarts 官方教程:点击查看 Echarts下载地址:飞机直达 1.下载 ...

  2. 微信小程序中的图表构建

    第一 html中的代码 <view class="container"> <canvas canvas-id="lineCanvas" bin ...

  3. 微信小程序中使用ECharts 异步加载数据 实现图表

    <!--pages/bar/index.wxml--> <view class="container"> <ec-canvas id="my ...

  4. 微信小程序的跨平台图表库开发

    写在前面 微信小程序出来已经有一段时间了,github上也有很多人开源了很多项目.但是由于微信平台的限制(底层Canvas能力调用为一系列JSBridge封装),图表的制作一直是个比较头疼的问题.当前 ...

  5. 微信小程序遍历Echarts图表,实现多个饼图

    如何在微信小程序中使用Echarts可以看我的另一个教程:点击查看 首先看一个简单的例子 1.wxml文件 <view style='width:100%;height:200rpx'> ...

  6. 微信小程序-canvas绘制文字实现自动换行

    在使用微信小程序canvas绘制文字时,时常会遇到这样的问题:因为canvasContext.fillText参数为 我们只能设置文本的最大宽度,这就产生一定的了问题.如果我们绘制的文本长度不确定或者 ...

  7. 微信小程序中使用canvas

    微信小程序中使用canvas会存在的一些问题: 由于小程序在绘制canvas的时候不能加载网络图片 所以需要把网络图片保存到本地之后再进行绘制 downLoadImg: function (netUr ...

  8. 网页或微信小程序中使元素占满整个屏幕高度

    在项目中经常要用到一个容器元素占满屏幕高度和宽度,然后再在这个容器元素里放置其他元素. 宽度很简单就是width:100% 但是高度呢,我们知道的是height:100%必须是在父元素的高度给定了的情 ...

  9. 在微信小程序中使用富文本转化插件wxParse

    在微信小程序中我们往往需要展示一些丰富的页面内容,包括图片.文本等,基本上要求能够解析常规的HTML最好,由于微信的视图标签和HTML标签不一样,但是也有相对应的关系,因此有人把HTML转换做成了一个 ...

随机推荐

  1. php模式的设计

    工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式. 工厂模式有一个关键的构造,根据一般原则命名为Factory的静态方法,然而这只是一种原则,虽然工厂方法可以任意命名这个静态 ...

  2. 一文详解Redis键过期策略

    摘要:Redis采用的过期策略:惰性删除+定期删除. 本文分享自华为云社区<Redis键过期策略详解>,作者:JavaEdge. 1 设置带过期时间的 key # 时间复杂度:O(1),最 ...

  3. 详解Nacos 配置中心客户端配置缓存动态更新的源码实现

    Nacos 作为配置中心,当应用程序去访问Nacos动态获取配置源之后,会缓存到本地内存以及磁盘中. 由于Nacos作为动态配置中心,意味着后续配置变更之后需要让所有相关的客户端感知,并更新本地内存! ...

  4. CF1548B题解

    在日报上面看到的,发现 NOIP 模拟赛考过这个 trick( 首先我们把题目要求的条件这么写: \[a_i=x_i \times m+k \] 那么我们要找到满足条件的数组,差分后的数组一定都是 \ ...

  5. LGP2414题解

    难不成是我后缀自动机学魔怔了,AC 自动机都能套上线段树 题意:给你一颗 Trie,每次询问两个节点 \(u,v\),\(u\) 代表的字符串在 \(v\) 代表的字符串中出现了多少次. 让我们思考一 ...

  6. 基于pytorch实现Resnet对本地数据集的训练

    本文是使用pycharm下的pytorch框架编写一个训练本地数据集的Resnet深度学习模型,其一共有两百行代码左右,分成mian.py.network.py.dataset.py以及train.p ...

  7. 用python生成你想要的任意大小文件

    在测试的日常工作中,我们经常会需要测试上传文件的边界值.今天分享一段30行的简单代码,可以生成任意大小的文件,方便测试. file_size=input("请输入想要生成文件的大小:(单位M ...

  8. NET经典书籍必读

    C#与.NET框架,入门 + 进阶 + 精通,外加并发编程实例,10本C#图书,一本都不能少. 1.<Learning hard C#学习笔记> 作者:李志  书号:978-7-115-3 ...

  9. [Java编程思想] 第一章 对象导论

    第一章 对象导论 "我们之所以将自然界分解,组织成各种概念,并按其含义分类,主要是因为我们是整个口语交流社会共同遵守的协定的参与者,这个协定以语言的形式固定下来--除非赞成这个协定中规定的有 ...

  10. 《手把手教你》系列基础篇(八十)-java+ selenium自动化测试-框架设计基础-TestNG依赖测试-番外篇(详解教程)

    1.简介 经过前边几篇知识点的介绍,今天宏哥就在实际测试中应用一下前边所学的依赖测试.这一篇主要介绍在TestNG中一个类中有多个测试方法的时候,多个测试方法的执行顺序或者依赖关系的问题.如果不用de ...