|
@@ -0,0 +1,92 @@
|
|
|
|
+const Bezier = function (pointArr, allTime = 2) {
|
|
|
|
+
|
|
|
|
+ let _this = {}
|
|
|
|
+ // 曲线点集合,曲线总长,上一个点,当前时间
|
|
|
|
+ let _pointLists, totalLength, prevPos, currentRunTime;
|
|
|
|
+ // 运行时间
|
|
|
|
+ let _runTime = allTime;
|
|
|
|
+ let _pointArr = pointArr;
|
|
|
|
+ // 重置数据
|
|
|
|
+ let resetData = function () {
|
|
|
|
+ // 点集合
|
|
|
|
+ _pointLists = [];
|
|
|
|
+ // 线段总长度
|
|
|
|
+ totalLength = currentRunTime = 0;
|
|
|
|
+ // 初始位置
|
|
|
|
+ prevPos = {
|
|
|
|
+ x: pointArr[0].x,
|
|
|
|
+ y: pointArr[0].y,
|
|
|
|
+ length: 0,
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //阶乘
|
|
|
|
+ function factorial(i) {
|
|
|
|
+ let n = 1;
|
|
|
|
+ for (let j = 1; j <= i; j++)
|
|
|
|
+ n *= j;
|
|
|
|
+ return n;
|
|
|
|
+ }
|
|
|
|
+ // ------------------------【核心代码】---------------------------
|
|
|
|
+ let ComputeBezier = function (dt, runTime) {
|
|
|
|
+ // 把时间从 [0,runTime] 映射到 [0,1] 之间
|
|
|
|
+ let t = currentRunTime / runTime;
|
|
|
|
+
|
|
|
|
+ var x = 0, y = 0;
|
|
|
|
+ //控制点数组
|
|
|
|
+ var n = _pointArr.length - 1;
|
|
|
|
+
|
|
|
|
+ _pointArr.forEach((item, index) => {
|
|
|
|
+ if (!index) {
|
|
|
|
+ x += item.x * Math.pow((1 - t), n - index) * Math.pow(t, index)
|
|
|
|
+ y += item.y * Math.pow((1 - t), n - index) * Math.pow(t, index)
|
|
|
|
+ } else {
|
|
|
|
+ //factorial为阶乘函数
|
|
|
|
+ x += factorial(n) / factorial(index) / factorial(n - index) * item.x * Math.pow((1 - t), n - index) * Math.pow(t, index)
|
|
|
|
+ y += factorial(n) / factorial(index) / factorial(n - index) * item.y * Math.pow((1 - t), n - index) * Math.pow(t, index)
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ // // 二阶贝塞尔曲线公式 (t => [0,1])
|
|
|
|
+ // var x = Math.pow(1 - t, 2) * _startPos.x
|
|
|
|
+ // + 2 * t * (1 - t) * _controlPos.x
|
|
|
|
+ // + Math.pow(t, 2) * _endPos.x;
|
|
|
|
+
|
|
|
|
+ // var y = Math.pow(1 - t, 2) * _startPos.y
|
|
|
|
+ // + 2 * t * (1 - t) * _controlPos.y
|
|
|
|
+ // + Math.pow(t, 2) * _endPos.y;
|
|
|
|
+
|
|
|
|
+ // console.log(`x:${x},y:${y}`);
|
|
|
|
+ // 计算两点距离
|
|
|
|
+ let length = Math.sqrt(Math.pow(prevPos.x - x, 2) + Math.pow(prevPos.y - y, 2));
|
|
|
|
+ let v2 = { x, y, length };
|
|
|
|
+ // 存储当前节点
|
|
|
|
+ _pointLists.push(v2);
|
|
|
|
+ prevPos = v2;
|
|
|
|
+ // 累计长度
|
|
|
|
+ totalLength += length;
|
|
|
|
+ // 累计时间
|
|
|
|
+ currentRunTime += dt;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 切割贝塞尔曲线
|
|
|
|
+ _this.getPoints = function (count = 10) {
|
|
|
|
+ resetData();
|
|
|
|
+ // 分割时间
|
|
|
|
+ let dt = _runTime / count;
|
|
|
|
+ // 开始分割曲线
|
|
|
|
+ for (var i = 0, len = count + 1; i < len; i++) {
|
|
|
|
+ ComputeBezier(dt, _runTime);
|
|
|
|
+ }
|
|
|
|
+ return _pointLists
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _this.getCurveLength = function () {
|
|
|
|
+ return totalLength;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return _this;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+module.exports = Bezier;
|