Анимированный интерактивный интерфейс на 5000 слов для светской беседы

внешний интерфейс JavaScript Государственный аппарат CSS Canvas

author: Горный призракОн немного гнилой, так что давайте сначала посмотрим на Наггетс.

5000 слов помогут вам понять основы реализации анимации и взаимодействия. Большая часть контента относительно отрывочна, поэтому я надеюсь, что вы не слишком суетитесь, и я улучшу его позже.

1. Космос и трансформация

Когда на экране рисуется графика, будь то 2D или 3D, она будет иметь свое собственное пространство, а также свои данные преобразования.

космические координаты

  1. И однородная матрица преобразования координат: В компьютерной графике он обычно представлен однородной координатной точкой в ​​пространстве, в трехмерном пространстве он будет представлен четырехэлементным вектором.
[\frac{x}{w},\frac{y}{w},\frac{z}{w}]=[x,y,z,w]

Как правило, значение w по умолчанию равно 1. Более простые поворот, перемещение и масштабирование используют 4-мерные матрицы.Когда нам нужны сложные операции, мы также можем получить составные матрицы через матрицы.

основные операции преобразования

Будь то операция преобразования графики, такой как CSS или холст, используемая операция одна и та же.

Сковорода

\begin{matrix}x\\y\\z\\1\end{matrix}=\begin{matrix}x\\y\\z\\1\end{matrix}*\begin{matrix}1&0&0&t\\0&1&0&t\\0&0&1&t\\0&0&0&1\end{matrix}

повернуть х

\begin{matrix}x\\y\\z\\1\end{matrix}=\begin{matrix}x\\y\\z\\1\end{matrix}*\begin{matrix}1&0&0&0\\0&cosX&-sinX&0\\0&sinX&cosX&0\\0&0&0&1\end{matrix}

повернуть у

\begin{matrix}x\\y\\z\\1\end{matrix}=\begin{matrix}x\\y\\z\\1\end{matrix}*\begin{matrix}cosX&0&sinX&0\\0&1&0&0\\-sinX&0&cosX&0\\0&0&0&1\end{matrix}

повернуть z

\begin{matrix}x\\y\\z\\1\end{matrix}=\begin{matrix}x\\y\\z\\1\end{matrix}*\begin{matrix}cosX&-sinX&0&0\\sinX&cosX&0&0\\0&0&1&0\\0&0&0&1\end{matrix}

зум

\begin{matrix}S1x\\S1y\\S1z\\1\end{matrix}=\begin{matrix}x\\y\\z\\1\end{matrix}*\begin{matrix}S1&0&0&0\\0&S1&0&0\\0&0&S1&0\\0&0&0&1\end{matrix}

Возможно, глядя на преобразование 3D-графики, это покажется очень сложным, но когда мы смотрим на 2D, одно измерение обрезается, а формула фиксируется.

\begin{matrix}x\\y\\1\end{matrix}=\begin{matrix}x\\y\\1\end{matrix}*\begin{matrix} cosX&-sinX&0\\sinX&cosX&0\\0&0&1\end{matrix}

дальнейшее упрощение

\begin{matrix}x\\y\\\end{matrix}=\begin{matrix}x\\y\\\end{matrix}*\begin{matrix}cosX&-sinX\\sinX&cosX\\\end{matrix}

На этот раз мы получим относительно распространенный код вращения

/**
向量定义
var Vector2={
    x:0,
    y:0
}
**/
function rotate(site,angle=0){
    	var _angle=angle/180*Math.PI;//将弧度转换为角度
    	//进行计算
    	var x1=site.x*Math.cos(_angle)-site.y*Math.sin(_angle);
    	var y1=site.x*Math.sin(_angle)+site.y*Math.cos(_angle);
    	//返回新的向量
    	return {
    	    x:x1,
    	    y:y1
    	}
};

ограничение:Преобразования данных матрицы не подходят для таких преобразований, как нелинейная анимация, из-за форматирования данных.

Неделя — это 360 градусов, что также равно 2π радианам. Радиан определяется таким образом, отношение длины дуги к радиусу, соответствующему углу, является радианом. Окружность круга с радиусом 1 равна 2π, поэтому 360 градусов = 2π радианам, и подойдет следующая аналогия. Несколько важных углов: 30 градусов = π/6 радиан, 60 градусов = π/3 радиан, 90 градусов = π/2 радиан, 180 градусов = π радиан и т. д.

векторная теория

В пространстве его можно разделить на пространственные координаты и координаты объекта. В CSS пространственные координаты несколько похожиposition:absoluteНа основе происхождения всего представления. Координаты объекта более уместны, чтобы быть относительными координатами, подобнымиposition:relativeДля облегчения вычисления координат и преобразования данных любая точечная информация в пространстве может использовать вектор в качестве носителя информации.

Example:(1,1) может быть выражено как координатная точка x=1, y=1 в пространстве или как расстояние от (0,0) до (1,1). Переопределить класс Vector2

function Vector2(x=0,y=0){
	if(!(this instanceof Vector2)){
		return new Vector2(x,y);
	}
	this.x=x;
	this.y=y;
}
Vector2.prototype = {
    copy: function() {//返回新的向量
    	 return new Vector2(this.x, this.y); },

    length: function() {//当前向量的长度
    	 return Math.sqrt(this.x * this.x + this.y * this.y); },

    normalize: function() {//单位向量
     var inv = 1 / this.length(); 
     return new Vector2(this.x * inv, this.y * inv); },

    negate: function() {//反向向量 
    	return new Vector2(-this.x, -this.y); },

    add: function(v) {//向量和
    	return new Vector2(this.x + v.x, this.y + v.y); },

    subtract: function(v) {//向量差
     return new Vector2(this.x - v.x, this.y - v.y); },

    multiply: function(f) {//向量积 
    	return new Vector2(this.x * f, this.y * f); },

    divide: function(f) { //向量方向化
    	var invf = 1 / f; 
    	return new Vector2(this.x * invf, this.y * invf); },

    dot: function(v) {//点积 
    	return this.x * v.x + this.y * v.y; },
    move:function(v){
        this.x=v.x;
        this.y=v.y;
        return this;
    },
    prependicular:function() {//法向量
    	return new Vector(this.y, -this.x);
	},
    rotate:function(angle=0){
    	var _angle=angle/180*Math.PI;
    	this.x1=this.x*Math.cos(_angle)-this.y*Math.sin(_angle);
    	this.y1=this.x*Math.sin(_angle)+this.y*Math.cos(_angle);
    },
};

Использование векторов: скорость (v), сила (f), направление (d), цвет (rgb) и т. д.

Когда мы используем сохраненное значение векторной информации, вы обнаружите, что многие функции понятны, например, свойство интерполяции.

угол

Расчет угла при реализации компьютерной анимации имеетВыражение фиксированного угла Выражение Эйлера для угла Выражение осевого углаЭти три аргумента, но эти не нужно понимать, потому что в процессе интерполяционного расчета эти методики не подходят, если вы хотите глубоко разобраться в причинах, вы можете узнать, чтокарданный замок.

Углы Эйлера

Угол Эйлера — это самый простой способ выразить вращение.Он выражает угол поворота объекта вокруг оси системы координат.Большое количество API-интерфейсов вращения предоставляется в 2D-плоскости, а те, что в csstransform:rotate(90deg), на холстеctx.rotate(angle), Для трехмерного аспекта css также обеспечивает вращение по каждой оси, а холст — это больше матричное преобразование, используемое в webgl.

Для определения углов Эйлера некоторые люди обобщили несколько пунктов.

  1. Комбинация угла поворота: (x, y, z) - это порядок выполнения угла, например X-Y-Z или Z-X-Y, который есть в cssX-Y-Z== rotateX()-rotateY()-rotateZ()
  2. Базовая система координат для угла поворота (независимо от того, выполняется ли вращение относительно фиксированной системы координат или собственной системы координат)
  3. Является ли угол поворота левым или правым

карданный тупик

В углах Эйлера мы можем обнаружить, что при повороте оси будет порядок.Если угол не подходит, это приведет к перекрытию двух осей во время вращения оси, что приведет к уменьшению размера.

Конечно, мы также можем использовать код, чтобы воспроизвести взаимоблокировку карданного подвеса.

Point.Rotate(new Vector3(0, 0, 10));  
Point.Rotate(new Vector3(0, 90, 0));  
Point.Rotate(new Vector3(20, 0, 0));  

Вам нужно только зафиксировать угол поворота одной оси на 90°, как бы вы ни регулировали другие оси, вы обнаружите, что они будут двигаться только по плоскости.

Что нам нужно знать, так этоКватернион, понятие этого слова очень распространено в разработке игр. Итак, в чем преимущество выбора кватернионов для обработки поворотов степени свободы.Преимущество

  1. Без блокировки подвеса
  2. Высокая вычислительная эффективность (вращение матрицы менее эффективно)
  3. Вращение вокруг центра объекта

слабость

  1. Предел оси вращения (вращение матрицы может быть любой осью)
  2. Не может превышать 180° (вращение матрицы не ограничено)

Прежде чем понять кватернионы, нам нужно понять точку знаниямножественное число, если у вас уже есть основа, ее можно пропустить.

множественное число

определение:Любое комплексное число z ∈ C можно представить в виде z = a + bi, где a, b ∈ R и2i^2=−1. Назовем a действительной частью комплексного числа, а b мнимой частью комплексного числа. Если комплексные числа представлены с использованием системы координат.

Кватернион

Кватернион — ужасная вещь, потому что, когда вы поместите его на график для понимания, вы обнаружите, что его гораздо труднее понять, чем матрицу В обычной системе координат каждая ось будет прямой линией, а в четырех арность, есть дополнительная ось, и эта ось будет перпендикулярна любой оси.По сравнению с двумерным пространством комплексных чисел, кватернион является трехмерным комплексным числом.Это комплексное число высокого порядка, которое ощущается как четырехмерное пространство...

Математическое выражение кватернионов относительно легко понять.Q=w+xi+yj+zk, Q — кватернион, w — действительная часть, x, y, z — мнимые части иi^2+j^2+k^2=-1.

Когда кватернионы применяются к вращению, мы обычно можем представитьQ=(w,(x,y,z))=(w,v), w — действительное число, v — вектор, для каждого поворота требуется совпадение двух кватернионов, а диапазон кватернионов находится между [-1, 1].

Далее мы пытаемся реализовать кватернион

/* 四元数
*/
 
class Quaternion{
    constructor(x=0,y=0,z=0,w=0){
        this.x=x;
        this.y=y;
        this.z=z;
        this.w=w;
    }
    fromAxisVector(axisVector,angle){// 由 旋转轴向量,旋转角 得到
        var t = sin(0.5*angle);
 		this.w = cos(0.5*angle);
		this.x = axisVector.x * t;
		this.y = axisVector.y * t;
		this.z = axisVector.z * t;       
    }
    add(q){
  		this.w += q.w;
		this.x += q.x;
		this.y += q.y;
		this.z += q.z;     
    }
    subtract(q){
   		this.w -= q.w;
		this.x -= q.x;
		this.y -= q.y;
		this.z -= q.z;          
    }
    multiply(q){
        var {x,y,z,w}=q;
 		this.w = w*q.w - x*q.x - y*q.y - z*q.z;
		this.x = w*q.x + x*q.w + y*q.z - z*q.y;
		this.y = w*q.y + y*q.w + z*q.x - x*q.z;
		this.z = w*q.z + z*q.w + x*q.y - y*q.x;       
    }
    normalize(){
        var {x,y,z,w}=this;
 		var magnitude = Math.sqrt(x*x + y*y + z*z + w*w);
		if (magnitude != 0)
		{
			x /= magnitude;
			y /= magnitude;
			z /= magnitude;
			w /= magnitude;
		}       
    }
    convertToMatrix4(){//转换为矩阵
 		//  四元数与矩阵的转换
		//     [ 1-2y2-2z2 , 2xy-2wz , 2xz+2wy ]
		//     [ 2xy+2wz , 1-2x2-2z2 , 2yz-2wx ]
		//     [ 2xz-2wy , 2yz+2wx , 1-2x2-2y2 ]
 		var {x,y,z,w}=this;
		var xx = x*x;  var xy = x*y; 
        var xz = x*z;  var xw = x*w; 
		var yy = y*y;  var yz = y*z;  
        var yw = y*w;  var zz = z*z;  var zw = z*w;
 
		return Matrix4(  1-2*(yy+zz),  2*(xy-zw),    2*(xz+yw),    0,
							2*(xy+zw),    1-2*(xx+zz),  2*(yz-xw),    0,
							2*(xz-yw),    2*(yz+xw),    1-2*(xx+yy),  0,
							0,            0,            0,            1  );
       
    }
}
 

2. Интерполяционный расчет

Интерполяционное движение относится к подгонке данных через некоторые дискретные данные, что позволяет вывести новые неизвестные точки данных и использовать простые функции для имитации сложных функций, тем самым повышая точность данных.

Вычисление интерполяции происходит в движении, наиболее распространенной является интерполяция атрибутов, таких как цветовой градиент, чрезмерная ширина и высота, ослабление анимации и т. Д. В основном она рассчитывается самим компьютером для реализации автоматического добавления кадров. Анимация движения во Flash использует кадры интерполяции и движения.

Предполагая, что задано n дискретных данных, координаты определяются как(x_k,y_k),k=1,2,3...в интервале[a,b]На нем существует функция g(x), которая может удовлетворятьg(x_i)=f(x_i), то g(x) можно назвать f(x) в[a,b]Функции интерполяции вверх, то есть использование простых функций для имитации сложных функций.

Атрибуты тип интерполяции Эффект
color/alpha линейный (Цвет/Прозрачность) Градиент наложен
ускорение линейный равномерная скорость
Углы Эйлера линейный вращать
скорость нелинейный переменное ускорение

Линейная интерполяция

Линейная интерполяция — это очень распространенный метод интерполяции, который очень распространен в расчетах анимации и может использоваться для реализации автоматического дополнения кадров, и его базовая реализация относительно проста.

Линейная интерполяция обычно рассчитывается с использованием двухточечных данных. Наиболее распространенной является линейная интерполяция. Примером линейной интерполяции является Linear из tween.js.

/*
 * t: current time(当前时间);
 * b: beginning value(初始值);
 * c: change in value(变化量);
 * d: duration(持续时间)。
*/    
Linear: function(t, b, c, d) { 
        return c * t / d + b; 
    }

Полиномиальная интерполяция

Полиномиальная интерполяция — это расширение линейной интерполяции, которое поддерживает полиномиальные вычисления более высокого порядка по исходной формуле линейной интерполяции.

    Quad: {
        easeIn: function(t, b, c, d) {
            return c * (t /= d) * t + b;
        },
        easeOut: function(t, b, c, d) {
            return -c *(t /= d)*(t-2) + b;
        },
        easeInOut: function(t, b, c, d) {
            if ((t /= d / 2) < 1) return c / 2 * t * t + b;
            return -c / 2 * ((--t) * (t-2) - 1) + b;
        }
    }

ЭтоTween.jsКвадратичная интерполяция в , в то же время, включает также кубическую интерполяцию и даже пятую интерполяцию.

Треугольная интерполяция

Треугольная интерполяция здесь относится к тригонометрической функции COS TAN SIN, которая формирует связь между осью X и осью Y. Например:

  • v=_v*Sin(t) Изменение скорости с течением времени

3. Основная анимация

С учетом предыдущих базовых знаний и интерполяции достаточно и основы, чтобы попробовать анимацию.

Итак, мы можем начать строить с точки

class Point{
    constructor(x,y){
        this.pos=new Vector2(x,y);
    }
    draw(){
        //图形绘制
    }
    updata(){
        //逻辑处理,数据更新
    }
}

Дело тут уже вVector2метод, так что эта точка имеет определенные возможности в двумерном пространстве, включая перемещение и вращение.

Ранее было сказано, что почти все атрибуты могут использовать векторы в качестве векторов, поэтому здесь вы можете использоватьVector2ДатьPointДает много недвижимости, вы можете получить

class Point{
    constructor(x,y){
        this.pos=new Vector2(x,y);
        this.f=new Vector(0,0);
        this.m=10;
        this.a=this.f.length()/this.m;
    }
}

Очень простойF=m*aформула, просто дайтеPointНаделен способностью принимать внешние силы, а также способностью к физическим упражнениям.

F=m*a  (F为合力,F是个矢量)
v= v_0+at
S=v_0t+\frac{at^2}{2}

Эти формулы являются наиболее часто используемыми и ключевыми формулами силы и кинематики, а также они являются ключевым шагом в кинематике.Так как же правильно рассчитать состояние движения объекта?

  1. Определить текущее состояние объекта, будь то единое тело или связанное состояние
  2. Суммируя силы, действующие на объект, для одногоPointпровестиupdata
  3. RedRaw объект

Таким образом, анимация основного движения может быть реализована с использованием физических формул, таких как равномерное ускорение, переменное ускорение, круговое движение и так далее.

4. Конечный автомат в анимации

цепная анимация

Конечный автомат — это очень распространенный словарь в разработке игр, так почему же он существует и где он используется?

Сначала сPointЗа основу добавить госколичество

const PEDDING='PEDDING';//静止状态
const MOVING ='MOVING';//运动状态
const SHOW   ='SHOW';//显示
const OUT    ='OUT';//屏幕之外

//状态判断
if(Point.status=='PEDDING'){
    cb();
}

Это выглядит немного знакомо? Сравнение показало, чтоpromiseПо сути, это еще и конечный автомат, который постоянно оценивает текущее состояние выполнения, чтобы определить, когда выполнять следующее событие.promiseЦепной вызов, вы можете легко понять принцип цепного вызова в некоторых библиотеках анимации.

менеджер ресурсов

Некоторые объекты, которые анимируются в представлении, всегда исчезают за его пределами.Чтобы уменьшить занимаемую память, можно напрямую использоватьobj=nul, но когда нам все же нужны его последующие вхождения, переходить к использованию приложения для нового объекта? Очевидно, что есть много неразумных мест, поэтому есть менеджер ресурсов.

var p1=new Point(0,0);
var p2=new Point(1,1)
var resource=[p1,p2];
//状态判断
resource.forEach(p=>{
    if(p.status=='SHOW'){
        p.updata();
        p.draw();
    }
    if(p.status=='OUT'){
       	//对p进行移除或者重置设置
    }
})

Преимущество этого заключается в том, что это может сократить объем вычислений и работы по рендерингу.Если вы планируете полностью удалить объект, вы можете использоватьArray.splice

Взаимодействие с пользователем

Взаимодействие с пользователем также является очень часто используемым конечным автоматом.В качестве примера возьмем холст, мониторинг событий пользователя предназначен для холста в целом.Если мы хотим реализовать функцию перетаскивания.

Анализ состояния:

  1. При нормальных обстоятельствах мышь отпущена, и статус UP.
  2. Нажатое состояние, статус DOWN
  3. Переместите мышь после нажатия, статус DROP

Существование конечного автомата основано на событиях мыши.

5. Обнаружение столкновений

После понимания основного движения и взаимодействия объектов, следующее, что нужно понять, — это взаимодействие между объектами и объектами, и теперь мы узнали о методе обнаружения столкновений.

  1. Ограничительная рамка
  2. окружающий мяч

Эти два также являются самыми простыми расчетами, а также они наиболее подходят для обнаружения столкновений на этапе грубого расчета, что позволяет исключить некоторую объектную графику, которая не нужна для точного расчета, уменьшая объем расчета.

Ограничительная рамка

Основываясь на центре объекта, сгенерируйте наименьший ограничивающий прямоугольник

rectB.x > rectA.x - rectB.width &&
rectB.x < rectA.x + rectA.width + rectB.width &&
rectB.y > rectA.y - rectB.height &&
rectB.y < rectA.y + rectA.height + rectB.height

окружающий мяч

На основе объекта сгенерируйте наименьшую ограничивающую сферу

Math.sqrt(Math.pow(circleA.x - circleB.x, 2) + Math.pow(circleA.y - circleB.y, 2)) < circleA.radius + circleB.radius

Отдельный вал

Разделение оси может показаться головокружительным, даже при чтении некоторых онлайн-объяснений, поэтому рассмотрите возможность открытия NetEase Cloud Music в это время, выберите свою любимую песню и начните читать.

Разделение оси, как следует из названия, означает разделение оси, тогда в известном нам поле дольше всего появляются ось x и ось y, которые также являются основой системы координат, так каковы характеристики ось,вертикальный, которая также является основой для оси разделения.

Реализация разделенной оси чем-то похожа на моделирование проекции света.Когда свет проходит через объекты в двух пространствах, чтобы предотвратить деформацию тени, устанавливается перегородка для вертикального света.Представьте, может ли свет проходить через два объекта, затем два Между двумя объектами нет контакта, поэтому проецируемые тени не будут перекрываться Когда проникает достаточно света, если на перегородке с вертикальным светом нет перекрытия теней, мы можем идентифицировать эти два объекта , Столкновения не произошло.

Обнаружение столкновения требует только, чтобы обнаружение набора осей не совпадало, тогда его можно судить как разделение.Если обнаружение всех осей совпадает, объект сталкивается

Итак, здесь у нас есть две оси: оптическая ось и ось проекции.

Итак, у нас есть первый лучик солнца

var Light=new Vector2(0,0);

позволить солнечному свету проходить сквозь предметы

var Point1 =new Point(0,0);
var Point2 =new Point(0,1);
var Light =Point1.pos.subtract(Point2.pos);//光线向量
var Panel =Light.prependicular();			//获取投影轴的向量
var axis  =Panel.normalize();				//轴的单位向量,为投影点做准备

Найдите нашу точку проекции, нужная здесь формулаv_1*v_2=|v_1|*|v_2|*conθ

Light.dot(axis);

После того, как точка проекции получена, разница между максимальным значением и минимальным значением точки проекции объекта на аксиальную плоскость является диапазоном теневой поверхности.

Обнаружение пикселя

Метод обнаружения пикселей заключается в том, чтобы сохранить текущую позицию пикселя каждого объекта, а затем сравнить, повторяются ли пиксели между объектами, но объем вычислений огромен.

Оптимизация обнаружения

Растрированный

Растеризация означает, что экран делится на несколько небольших блоков, а объекты в разных областях обрабатываются отдельно.Для объектов на линии границы могут быть сделаны множественные суждения. Наиболее часто используется метод сетки.Квадтри

Продолжение следует! !

Будут более интересные дополнения, такие как IK/FK анимация, реализация эффекта 2.5D и т.д... Если вы найдете какие-либо ошибки, пожалуйста, укажите на них.