3.4 贝塞尔曲线canvas提供了两个绘制贝塞尔曲线api:ctx.quadraticCurveTo(cpx, cpy, x, y);二次贝塞尔曲线,(cpx, cpy)控制点 (x, y)终点ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);三次贝塞尔曲线,(cp1x, cp1y)控制点一, (cp2x, cp2y)控制点二, (x, y)终点题外话:贝塞尔曲线的数学基础是早在 1912 年就广为人知的伯恩斯坦多项式。最早用来辅助汽车车体的工业设计。CSS3的transition-timing-function属性,取值就可以设置为一个三次贝塞尔曲线方程transition-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1)。canvas绘图示例:// 二次ctx.moveTo(200, 100);ctx.quadraticCurveTo(230, 250, 350, 200);// 三次ctx.moveTo(450, 250);ctx.bezierCurveTo(530, 150, 650, 300, 700, 200);蓝色是控制点问题一:那canvas是如何通过控制点来绘制出曲线的,或者如果不用这个,自己绘制曲线该如何操作呢:这个是n阶贝塞尔曲线的方程:我们重点看二(三)阶方程:B(t)是曲线上的点,t在01之间取值, P0起始点,P2终点,P1控制点t从01之间取值不断增大,B(t)不断取出曲线上的点,从P0移至P1const bx = (1-t)(1-t)start.x + 2t(1-t)control.x + ttend.x;const by = (1-t)(1-t)start.y + 2t*(1-t)control.y + tt*end.y;问题二:我咋知道控制点该怎么选,特别是起终点动态数据时(也就是说,我们使用时,往往只知道起点P0终点P1):这个根据曲线斜率,可视化需求可能选取的方式不一致,不过大致原理相似可以在起点和终点的垂直平分线上选一点作为控制点, 然后用一个参数来控制曲线的弯曲程度// curveness 弯曲程度(0-1)const cp = { x: ( start.x + end.x ) / 2 - ( start.y - end.y ) * curveness, y: ( start.y + end.y ) / 2 - ( end.x - start.x ) * curveness};题外话:关于cp点的求解:线段中点:const mid = [ ( start.x + end.x) / 2, ( start.y + end.y ) / 2 ];根据起点和终点也可以得到一个向量v: const v = [ end.x - start.x, end.y- start.y ]; 将这个向量顺时针旋转90度,得到一个垂直于它的向量v2:const v2 = [ v.y, -v.x ];那么中间控制点的坐标为(向量v2乘curveness加上中间点坐标)const cp = { x: mid.x + v2.x curveness, y: mid.y + v2.y curveness} = { x:( start.x + end.x ) / 2 - ( start.y - end.y ) * curveness, y:( start.y + end.y ) / 2 - ( end.x - start.x ) * curveness}