工程师文化,本质是一种专研,搞清事物本质的精神?
从一次技术群的聊天说起
前端A:
请问有没有 把一组数变平滑的 JS 算法??
比如说 [100, 80, 20, 10] 这里 80 -> 20 断崖式下跌,把他转换成类似 [100, 75, 50, 25 ]这种平滑下跌的
我希望能传参调整这个平滑度(项目组产品)?
Sky:有很多方法?
插值,移动平均线,贝塞尔,多项式拟合线条
前端A
其实是想把漏斗图弄平滑点
Sky: 如果需要有控制参数的话,建议使用贝塞尔
Talk is cheap, show me the code?
本需求的分析
销售漏斗图比较锐,希望有一个柔和的宽度变化?
增加更多的点来柔和 这些[100, 80, 20, 10]
需要一个非常快捷的方式实现,前端要考虑性能
类似的解决问题的方法是否有一定的延展性?
通过插值方式将[100, 80, 20, 10]扩展成多个点集,我们选择贝塞尔3次曲线
贝塞尔曲线
1912年伯恩斯坦多项式=>在[ a, b ] 区间上所有的连续函数都可以用多项式来逼近,并且收敛性很强,也就是一致收敛。?
1959年。当时就职于雪铁龙的法国数学家 Paul de Casteljau 开始对伯恩斯坦多项式进行了图形化的尝试。
通过很少的控制点,去生成复杂的平滑曲线,也就是贝塞尔曲线。
1962年就职于雷诺的法国工程师皮埃尔·贝塞尔(Pierre Bézier),他使用这种方法来辅助汽车的车体工业设计。原来是研究汽车的线?
wiki上有更详细的E文解释?
贝赛尔曲线N阶,前端技术中常用的是3阶,如下图
实现(干货)?
以上公式取3阶即可,直接上加推3次贝塞尔代码,当然函数可以进一步柯里化
const cubicBezier = (t, x = [], y = []) => { // t~[0,1]
return [
x[0] * (1 - t) ** 3 +
3 * x[1] * t * (1 - t) ** 2 +
3 * x[2] * t ** 2 * (1 - t) +
x[3] * t ** 3,
y[0] * (1 - t) ** 3 +
3 * y[1] * t * (1 - t) ** 2 +
3 * y[2] * t ** 2 * (1 - t) +
y[3] * t ** 3
]
}
let x = [1, 2, 3, 4]
let y = [10, 20, 80, 100]
for (let i = 0; i <= 1; i += 0.1) {
console.log(cubicBezier(i, x, y))
}