|
纯Javascript实现平滑曲线生成前言平滑曲线生成是一个很实用的技术。很多时候,我们都需要通过绘制一些折线,然后让计算机平滑的连接起来,或者是生成一些平滑的面。先来看下最终效果(红色为我们输入的直线,蓝色为拟合过后的曲线) 首尾可以特殊处理让图形看起来更好)。实现思路是利用贝塞尔曲线进行拟合。?贝塞尔曲线简介贝塞尔曲线(英语:Bézier curve)是计算机图形学中相当重要的参数曲线。二次贝塞尔曲线?二次方贝塞尔曲线的路径由给定点P0、P1、P2的函数B(t)追踪:?三次贝塞尔曲线?对于三次曲线,可由线性贝塞尔曲线描述的中介点Q0、Q1、Q2,和由二次曲线描述的点R0、R1所建构:贝塞尔曲线计算函数根据上面的公式我们可以得到计算函数。二阶/** ? * ? * ? * @param {number} p0 ? * @param {number} p1 ? * @param {number} p2 ? * @param {number} t ? * @return {*} ? * @memberof Path ? */ ?bezier2P(p0: number, p1: number, p2: number, t: number) { ? ?const P0 = p0 * Math.pow(1 - t, 2); ? ?const P1 = p1 * 2 * t * (1 - t); ? ?const P2 = p2 * t * t; ? ?return P0 + P1 + P2; ?} ? ? ?/** ? * ? * ? * @param {Point} p0 ? * @param {Point} p1 ? * @param {Point} p2 ? * @param {number} num ? * @param {number} tick ? * @return {*} ?{Point} ? * @memberof Path ? */ ?getBezierNowPoint2P( ? ? ?p0: Point, ? ? ?p1: Point, ? ? ?p2: Point, ? ? ?num: number, ? ? ?tick: number, ?): Point { ? ?return { ? ? ?x: this.bezier2P(p0.x, p1.x, p2.x, num * tick), ? ? ?y: this.bezier2P(p0.y, p1.y, p2.y, num * tick), ? ?}; ?} ? ? ?/** ? * 生成二次方贝塞尔曲线顶点数据 ? * ? * @param {Point} p0 ? * @param {Point} p1 ? * @param {Point} p2 ? * @param {number} [num=100] ? * @param {number} [tick=1] ? * @return {*} ? * @memberof Path ? */ ?create2PBezier( ? ? ?p0: Point, ? ? ?p1: Point, ? ? ?p2: Point, ? ? ?num: number = 100, ? ? ?tick: number = 1, ?) { ? ?const t = tick / (num - 1); ? ?const points = []; ? ?for (let i = 0; i 1) { ? ? ?delta = vector2dMinus( ? ? ? ? ?p1, ? ? ? ? ?vector2dPlus(pt, vector2dMinus(p2, pt).scale(1 / v)), ? ? ?); ? ?} else { ? ? ?delta = vector2dMinus( ? ? ? ? ?vector2dPlus(pt, vector2dMinus(p1, pt).scale(v)), ? ? ? ? ?p2, ? ? ?); ? ?} ? ?delta = delta.scale(ratio); ? ?const control1: Point = { ? ? ?x: vector2dPlus(pt, delta).x, ? ? ?y: vector2dPlus(pt, delta).y, ? ?}; ? ?const control2: Point = { ? ? ?x: vector2dMinus(pt, delta).x, ? ? ?y: vector2dMinus(pt, delta).y, ? ?}; ? ?return {control1, control2}; ?} ? ? ?/** ? * 平滑曲线生成 ? * ? * @param {Point []} points ? * @param {number} ratio ? * @return {*} ? * @memberof Path ? */ ?createSmoothLine(points: Point[], ratio: number = 0.3) { ? ?const len = points.length; ? ?let resultPoints = []; ? ?const controlPoints = []; ? ?if (len { ? ? ? ?let app = document.getElementById('app'); ? ? ? ?let index = 0; ? ? ? ?let move = () => { ? ? ? ? ? ?if (index
|
|