js之形状补间算法

js之形状补间算法

效果:

从一条线形变成另外一条线,计算其中的变化过程。

应用场景:

1.编写从矩形缓慢变化为圆形。

2.展示水位上升时候海岸线被淹没的过程。

原理:

1.将两条线个字按照长度平均分成1000份得到两个1000个点的数组。

2.两跳线生成的数组的点一一对应。

3.计算两个对应点中间的比例,得到中间过程中的线的数据。

缺点:

因为是按照长度去做的对应,如果长度在整条线上分布的不均匀,会导致中间过程中线会与预期情况偏差过大

数据准备:(使用海岸线变化的数据举例)

变化前的线:

let line1 = [[111.982019, 21.757804], [113.584883, 22.176118], [113.640075, 22.825748], [114.090809, 22.373042], [114.780707, 22.612395]]

变化后的线:

let line2 = [[111.982019, 21.757804], [111.403052, 23.671332], [115.142303, 23.722159], [114.780707, 22.612395]]

代码:

function getLine(line1, line2, time) {
        // 将线换算为100个点的等距离数组
        function lineChange(line) {
          // 等分线数组
          let linec = []
      // 线分开的段数,数量越大,线越圆滑
          let amount = 100
          // 将源数据线每两个点重组为线段
          let lines = []
          // 将源数据线每两个点重组为线段的长度数组
          let linesLength = []
          // 源数据线总长度
          let allLinesLength = 0
          // 计算前面三个值
          line.forEach((e, i) => {
            if (i + 1 < line.length) {
              lines.push([e, line[i + 1]])
              let point1 = e
              let point2 = line[i + 1]
              let distance = Math.sqrt(Math.pow(point1[0] - point2[0], 2) + Math.pow(point1[1] - point2[1], 2))
              linesLength.push(distance)
              allLinesLength = allLinesLength + distance
            }
          })
          // 切割后每段线长度
          let lineLength = allLinesLength / amount
          // 生成平均分线的每个点
          for (let i = 0; i < amount; i++) {
            // 当前点距离起点的长度
            let length = lineLength * i
            // 当前点在第几条线段上
            let inum = 0
            for (let j = 0; j < linesLength.length; j++) {
              if (length - linesLength[j] < 0) {
                inum = j
                break;
              }
              length = length - linesLength[j]
            }
            // 在上述循环完成后 length即当前点所在当前线段距离起点的长度
            // 当前点所在线段的起点
            let point1 = lines[inum][0]
            // 当前点所在线段的终点
            let point2 = lines[inum][1]
            // linesLength[inum]为当前点所在线段的总长度
            // 根据比例关系计算当前点坐标
            let x = (point2[0] - point1[0]) * length / linesLength[inum] + point1[0]
            let y = (point2[1] - point1[1]) * length / linesLength[inum] + point1[1]
            linec.push([x, y])
          }
          return linec
        }
        let linec1 = lineChange(line1)
        let linec2 = lineChange(line2)
        // 中间态线数组
        let arealine = []
        for (let i = 0; i < linec1.length; i++) {
          let point1 = linec1[i]
          let point2 = linec2[i]
          // 默认总动画时间为1秒
          let alltime = 1.0
          // time为传入的值,区间为0~1.表示动画运行的进度
          // 根据动画进度计算当前中间态线
          let x = (point2[0] - point1[0]) * time / alltime + point1[0]
          let y = (point2[1] - point1[1]) * time / alltime + point1[1]
          arealine.push([x, y])
        }
        return arealine
      }
 // 传入line1、line2和时间可获得当前时间线变化的中间态线
   let line3 = getLine(line1, line2, time)

 

 

 

 

 

钻研不易,转载请注明出处。。。。。。。

 

posted @ 2021-09-03 16:43  莫小龙  阅读(273)  评论(0编辑  收藏  举报