123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- 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;
|