Matemáticas - Curvas de Bezier


inserte la descripción de la imagen aquí

Objetivo

Implemente el movimiento en el diagrama.

preparación de código

un lienzo

estructura:

<div id="app">
	<div id="rectangle"></div>
</div>

Actuación:

#app {
    
    
	width: 600px;
	height: 600px;
	margin: 0 auto;
	outline: solid pink 2px;
	position: relative;
}

#rectangle {
    
    
	position: absolute;
	width: 100px;
	height: 100px;
	background-color: red;
}

Efecto:

inserte la descripción de la imagen aquí

algunos js

Clase que representa las coordenadas:

function Point2D(x = 0, y = 0) {
    
    
	this.x = x
	this.y = y
}

El estado de la animación:

//目标元素
let element = document.getElementById('rectangle')
//状态
let index = 0
let totalTime = 3000
let direction = true

elemento: El elemento de destino de la animación.

índice: el porcentaje de la animación actual, más o menos 0,01 cada vez. El rango es de cero a uno.
totalTime: el número total de milisegundos para la animación.
dirección: la dirección de movimiento actual.

Bézier de primer orden

Los movimientos de Bezier se pueden observar en este sitio web: https://www.jasondavies.com/animated-bezier/

El primer orden es el movimiento uniforme, las coordenadas de cada cuadro: las
coordenadas del punto inicial más el desplazamiento actual.

function BezierOne(from, to, step) {
    
    
	let x = from.x + (to.x - from.x) * step
	let y = from.y + (to.y - from.y) * step
	return new Point2D(x, y)
}

Implementar movimiento de primer orden:

let fromP = new Point2D(0, 0)
let toP = new Point2D(250, 0)
setInterval(() => {
    
    
	if (index > 1 || index < 0) {
    
    
		direction = !direction
	}
	if (direction) {
    
    
		index += 0.01
	} else {
    
    
		index -= 0.01
	}
	let point = BezierOne(fromP, toP, index)
	element.style.left = point.x + "px"
	element.style.top = point.y + "px"
}, 0.01 * totalTime)

Primero determine el límite y cambie la dirección del movimiento.
El índice del siguiente cuadro está determinado por la dirección del movimiento.
Calcular las coordenadas de Bézier. Asignación.

Efecto:

inserte la descripción de la imagen aquí

Bézier de segundo orden

Punto inicial A, punto de control B, punto final C.

Calcular el primer orden de AB y el primer orden de BC.
Luego calcule el primer orden a partir de estos dos primeros pedidos. (Matrioska)

function BezierTwo(from, to, control, step) {
    
    
	let a = BezierOne(from, control, step)
	let b = BezierOne(control, to, step)
	return BezierOne(a, b, step)
}

Un punto más.

let fromP = new Point2D(0, 0)
let controlP = new Point2D(250, 0)
let toP = new Point2D(250, 500)

Cambiar la llamada a segundo orden:

BezierTwo(fromP, toP, controlP, index)

Efecto:

inserte la descripción de la imagen aquí

Bézier de tercer orden

Punto inicial A, punto de control B, punto de control C, punto final D.

Calcule el primer orden de AB, el primer orden de BC y el primer orden de CD.
Luego calcula el segundo orden a partir de estos tres primeros órdenes. (Matrioska)

function BezierThree(from, to, controlA, controlB, step) {
    
    
	let a = BezierOne(from, controlA, step)
	let b = BezierOne(controlA, controlB, step)
	let c = BezierOne(controlB, to, step)
	return BezierTwo(a, c, b, step)
}

Un punto más:

let fromP = new Point2D(0, 0)
let controlA = new Point2D(250, 0)
let controlB = new Point2D(250, 500)
let toP = new Point2D(0, 0)

Se cambia la llamada a tercer orden:

BezierThree(fromP, toP, controlA, controlB, index)

Efecto:

inserte la descripción de la imagen aquí

Bézier de cuarto orden

Punto inicial A, punto de control B, punto de control C, punto de control D, punto final E.

Calcule el primer orden de AB, el primer orden de BC, el primer orden de CD y el primer orden de DE.
Luego calcula el tercer orden de estos cuatro primeros órdenes. (Matrioska)

function BezierFour(from, to, controlA, controlB, controlC, step) {
    
    
	let a = BezierOne(from, controlA, step)
	let b = BezierOne(controlA, controlB, step)
	let c = BezierOne(controlB, controlC, step)
	let d = BezierOne(controlC, to, step)
	return BezierThree(a, d, b, c, step)
}

Un punto más:

let fromP = new Point2D(0, 0)
let controlA = new Point2D(250, 0)
let controlB = new Point2D(250, 500)
let controlC = new Point2D(0, 0)
let toP = new Point2D(0, 500)

Se cambia la llamada a cuarto orden:

BezierFour(fromP, toP, controlA, controlB, controlC, index)

Efecto:

inserte la descripción de la imagen aquí

más orden bezier

Nadie realmente lo usa.

function BezierN(arr, step) {
    
    
	if (arr.length === 2) {
    
    
		return BezierOne(arr[0], arr[1], step)
	} else {
    
    
		let arr2 = []
		for (let i = 0; i < arr.length - 1; i++) {
    
    
			arr2.push(BezierOne(arr[i], arr[i + 1], step))
		}
		return BezierN(arr2, step)
	}
}

Mira el cuarto orden, ¿verdad?

let point = BezierN([fromP, controlA, controlB, controlC, toP], index)

Efecto:

inserte la descripción de la imagen aquí

todo el código

<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport"
		  content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Document</title>
	<style>
		#app {
      
      
			width: 600px;
			height: 600px;
			margin: 0 auto;
			outline: solid pink 2px;
			position: relative;
		}

		#rectangle {
      
      
			position: absolute;
			width: 100px;
			height: 100px;
			background-color: red;
		}
	</style>
</head>
<body>
<div id="app">
	<div id="rectangle"></div>
</div>
<script>
	//目标元素
	let element = document.getElementById('rectangle')
	//状态
	let index = 0
	let totalTime = 3000
	let direction = true
	//起点,终点
	let fromP = new Point2D(0, 0)
	let controlA = new Point2D(250, 0)
	let controlB = new Point2D(250, 500)
	let controlC = new Point2D(0, 0)
	let toP = new Point2D(0, 500)
	setInterval(() => {
      
      
		if (index > 1 || index < 0) {
      
      
			direction = !direction
		}
		if (direction) {
      
      
			index += 0.01
		} else {
      
      
			index -= 0.01
		}
		let point = BezierN([fromP, controlA, controlB, controlC, toP], index)
		element.style.left = point.x + "px"
		element.style.top = point.y + "px"
	}, 0.01 * totalTime)

	function Point2D(x = 0, y = 0) {
      
      
		this.x = x
		this.y = y
	}

	function BezierOne(from, to, step) {
      
      
		let x = from.x + (to.x - from.x) * step
		let y = from.y + (to.y - from.y) * step
		return new Point2D(x, y)
	}

	function BezierTwo(from, to, control, step) {
      
      
		let a = BezierOne(from, control, step)
		let b = BezierOne(control, to, step)
		return BezierOne(a, b, step)
	}

	function BezierThree(from, to, controlA, controlB, step) {
      
      
		let a = BezierOne(from, controlA, step)
		let b = BezierOne(controlA, controlB, step)
		let c = BezierOne(controlB, to, step)
		return BezierTwo(a, c, b, step)
	}

	function BezierFour(from, to, controlA, controlB, controlC, step) {
      
      
		let a = BezierOne(from, controlA, step)
		let b = BezierOne(controlA, controlB, step)
		let c = BezierOne(controlB, controlC, step)
		let d = BezierOne(controlC, to, step)
		return BezierThree(a, d, b, c, step)
	}

	function BezierN(arr, step) {
      
      
		if (arr.length === 2) {
      
      
			return BezierOne(arr[0], arr[1], step)
		} else {
      
      
			let arr2 = []
			for (let i = 0; i < arr.length - 1; i++) {
      
      
				arr2.push(BezierOne(arr[i], arr[i + 1], step))
			}
			return BezierN(arr2, step)
		}
	}
</script>
</body>
</html>

Supongo que te gusta

Origin blog.csdn.net/qq_37284843/article/details/124343428
Recomendado
Clasificación