Foreword:
Our purpose is to have a smooth curve to represent the moving average, etc., rather than a polyline with obvious turning points. So we have to continue to explore the API. We found that in the canvas API, there are two APIs that can draw curves
beZierCurveTo(num1, num2, num3, num4, x, y) quadraticCurveTo(num1, num2, x, y)
Both APIs draw paths through Bezier curves. Fortunately, when I was learning PS, I also had a certain degree of proficiency in the specific performance of Bezier curves, so I knew that to determine a curve path composed of multiple points, each turning point must have 2 control points to control the curve. Performance
And at the starting point and end point of the curve, there can only be one control point. Therefore, when we draw the starting point and end point, we have to use quadraticCurveTo, and when drawing the middle point, we use beZierCurveTo.
The difficulty now is, how to calculate their control points through the known points to be passed?
In order to find an effective formula, I started drafting. I drew a draft that only I could understand.
I didn’t expect to say goodbye to high school mathematics for so many years. With a little memory, I spent a whole morning and forced myself to come up with a formula. I think if I was still a high school mathematics student If you're good at it, you can probably get it out in just 10 minutes, sweat!
I don’t know if you still remember the concept of tangent line. If we want to draw a Bezier curve, M[i-1] is the starting point, M[i] is the end point, and the other two control points are A1, A2, these two control points must be on the tangent line of a certain surface, and the tangent line can be determined by three points. For example, in my draft, the top orange line is the tangent line. We only need to On the tangent line, pick two points at will and use them as the control points of the front and rear curves respectively
So, after a long period of thinking, I summarized a formula as follows
A1[M[i-1][0] + a*(M[i][0] - M[i-2][0]), M[i-1][1] + b*(M[i][1] - M[i-2][1])] A2[M[i][0] - b*(M[i+1][0] - M[i-1][0]), M[i][1] - b*(M[i+1][1] - M[i-1][1])]
The coefficients a and b are values that I randomly choose according to the situation. I have tried it, and it is recommended to take the value near 0.3 and debug it. Try to see the specific effect and then determine the first point and the last point. Because it is impossible to obtain two control points in this way, I added a random custom point before and after the point set, and just ignored them during the actual traversal.
I have sorted out the ideas, and the specific implementation is as follows
bezierLine (canvasId, options) { let windowWidth = 0 wx.getSystemInfo({ success (result) { windowWidth = result.windowWidth } }) let a = windowWidth / (options.xAxis.length-1) let data = [] options.xAxis.map((item, i) => { data.push([i * a, 200 - options.yAxis[i]]) }) data.unshift(data[0]) data.push(data[data.length - 1]) const ctx = wx.createCanvasContext(canvasId) ctx.beginPath() data.map((item, i) => { const a = 0.25 const b = 0.25 if (i == 0 || i == data.length - 1) { // do nothing } else if (i == 1) { ctx.moveTo(item[0], item[1]) } else { const a1 = data[i - 1][0] + a * (data[i][0] - data[i - 2][0]) const a2 = data[i - 1][1] + b * (data[i][1] - data[i - 2][1]) const b1 = data[i][0] - b * (data[i + 1][0] - data[i - 1][0]) const b2 = data[i][1] - b * (data[i + 1][1] - data[i - 1][1]) ctx.bezierCurveTo(a1, a2, b1, b2, item[0], item[1]) } }) ctx.setLineWidth(1) ctx.setStrokeStyle('red') ctx.stroke() ctx.draw() } // 在onLoad中调用 this.bezierLine('stage', { xAxis: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], yAxis: [11, 33, 22, 32, 14, 15, 20, 60, 23, 44, 77, 122, 133, 89, 156, 122,128, 143, 111, 101, 132, 99, 98, 44, 62, 74, 111, 13, 42, 55] })
oh yeah! The effect is not bad, I no longer have to worry about drawing the curve, and we can manage our K-line chart again One step closer
ps: Data can be organized in various forms, it can be an array, a two-digit array, or an object. This is not the most important point, as long as it can be processed correctly
Thanks for reading, I hope it can help everyone, thank you for your support of this site!
For more WeChat mini programs, please pay attention to the PHP Chinese website for related articles on using canvas to create K-line examples!