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)
钻研不易,转载请注明出处。。。。。。。