# Drawing charts in wechat applet (Part2)

Time：2021-6-23

## Outline of this issue

1. Determine the range of ordinate and draw

2. Draw broken line according to real data

## Determine the range of ordinate and draw

In order to avoid decimals in the scale of the ordinate, we divide the ordinate into five blocks. We take the minimum unit scale as 10 (which can be divided by 5). Of course, the real situation will be more complicated than this. We will discuss it later.

So our processing input and output should be the following result

``````(5, 34.1)  => (10, 40)
(10, 34)   => (10, 40)
(-5.1, 40) => (-10, 40)``````
``````//Determine the value range of y-axis
function findRange (num, type, limit) {
limit = limit || 10;

//Upper looks up and lower looks down
type = type ? type : 'upper';

//Carry out rounding operation to avoid entering dead loop when 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;
}``````

OK, the preliminary determination range has been completed, but it is not ideal to think about this range. For example, the data passed in by users is decimal level, such as`(0.2, 0.8)`Our output range is`(0, 5)`This range is too large, and the effect of the chart will be that most of the data above is left blank. Similarly, the data input by the user is very large, such as`(10000, 18000)`The range we get is`(10000, 18010)`This range is meaningless, so we need to determine our minimum unit scale according to the range of the incoming data.

Our parameter format is as follows:

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

Let’s continue to optimize

``````//Merge data, and integrate each data item in series into an array
function dataCombine(series) {
return series.reduce(function(a, b) {
return (a.data ? a.data : a).concat(b.data);
}, []);
}

//Determine the minimum unit scale according to the data range
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);
//Gets the minimum value of the incoming data
var minData = Math.min.apply(this, dataList);
//Gets the maximum value of the incoming data
var maxData = Math.max.apply(this, dataList);

var limit = getLimit(maxData, minData);

var minRange = findRange(minData, 'lower', limit);
var maxRange = findRange(maxData, 'upper', limit);``````

Now let’s dynamically determine the appropriate minimum scale range. Next, let’s optimize the above`findRange`Method, mainly to increase the support for decimals

``````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;
}``````

Now we have determined the value range of y-axis. For how to draw y-axis, please refer topart1The method of drawing the x-axis is no longer cumbersome here.

Y-axis rendering:

``````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]
}
]
}``````

It’s not bad. Let’s move on

## Draw broken line according to real data

The key of the problem is to determine the location of each data point`(x, y)`Coordinates,`x`It’s easy to determine the coordinates. Let’s use the width of the canvas and`opts.categories`It can be determined.

Our configuration is as follows:

``````config = {
Xaxisheight: 30, // X-axis height
Yaxiswdith: 30 // Y-axis width
}``````
``````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`The coordinates will be a little more complicated and need to be calculated according to the range of Y axis.

So we worked it out`y`It should be

``````y = validHeight * (data - min) / (max - min);
//Since the upper left corner of the canvas is the origin coordinate, let's change it
//Get the final y drawing point
y = valideHeight - y;``````

The code is as follows:

``````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);
}``````

Now that we have determined the drawing coordinates of the data points on the canvas, please see how to draw thempart1This is no longer cumbersome.

The final picture is as follows:

Notice: in the next part, we will discuss some skills in the drawing process, animation effects and how to engineer our project.