реализуя функцию ослабления - PullRequest
0 голосов
/ 11 октября 2011

Я пытаюсь перенести и реализовать функцию замедления, которую я нашел

РЕДАКТИРОВАТЬ

: Я вставил неправильную функцию замедления, извините!Вот правильный вариант:

Math.easeOutQuart = function (t, b, c, d) {
    t /= d;
    t--;
    return -c * (t*t*t*t - 1) + b;
};

Я использую не Flash или Actionscript.Вот мой код:

ease:{outquart:{function(t as float,b as float,c as float,d as float) as float
        t=t/d
        t=t-1
        return -c * (t*t*t*t - 1) + b
    end function}}

Я вызываю функцию в цикле с помощью:

EDIT2 - вызывающая функция.

m.move установлен в 1или -1 для направления движения, или -5 +5 для перемещения на 5 длин.setspritemoves вызывается настолько часто, насколько это возможно, в настоящее время он выполняется так быстро, как может вызвать система, но я мог бы вызвать вызов по таймеру в миллисекундах.

setspritemoves:function()
                if m.move=1 then
                m.duration=1
                    if m.ishd then
                        for i=0 to m.spriteposx.count()-1
                            m.moveto[i]=m.spriteposx[i]+m.move*324
                        next i
                    else
                        for i=0 to m.spriteposx.count()-1
                            m.moveto[i]=m.spriteposx[i]+m.move*224
                        next i
                    end if                          
                else if m.move=5 then
                    m.duration=5
                    if m.ishd then
                        for i=0 to m.spriteposx.count()-1
                            m.moveto[i]=m.spriteposx[i]+m.move*324
                        next i
                    else
                        for i=0 to m.spriteposx.count()-1
                            m.moveto[i]=m.spriteposx[i]+m.move*224
                        next i
                    end if      
                else if m.move=-1 then
                m.duration=1
                    if m.ishd then
                        for i=0 to m.spriteposx.count()-1
                            m.moveto[i]=m.spriteposx[i]-m.move*324
                        next i
                    else
                        for i=0 to m.spriteposx.count()-1
                            m.moveto[i]=m.spriteposx[i]-m.move*224
                        next i
                    end if      
                else if m.move=-5 then
                    m.duration=5
                    if m.ishd then
                        for i=0 to m.spriteposx.count()-1
                            m.moveto[i]=m.spriteposx[i]-m.move*324
                        next i
                    else
                        for i=0 to m.spriteposx.count()-1
                            m.moveto[i]=m.spriteposx[i]-m.move*224
                        next i
                    end if
                end if
                end function

m.moveto [i] - это координата x назначения, m.time - это целое число, которое я увеличиваю, m.duration - это то, что я предполагаю как количество времени, которое требуется для выполнения изменения, m.spriteposx - это текущая позиция объекта, который я перемещаю.[i] текущий спрайт.

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

Во всех моих экспериментах я либо резко отклоняюсь от нормы, либо перемещаю только несколько пикселей.

В настоящее время m.time увеличивается на 1 на каждую итерацию, а m.duration равно 100.Я перепробовал все виды ценностей, и, похоже, ни одна из них не работает последовательно.

Ответы [ 3 ]

1 голос
/ 11 октября 2011

Почему вы не скопировали логику через 1-1?Анимация - это простой алгоритм, он просто отображает координаты от b до b+c в квартальной форме, т.е. b + c*t^4, где t получает значения в интервале [0,1].Подстановкой можно увидеть, что когда t=0 значение является начальным значением, b, а при t->1 позиция является обязательной b+c.

Это причина для строки t \= d, поэтому d - произвольная длительность, а t - время, прошедшее с начала анимации, получает значение в вышеупомянутом диапазоне.Но вы сделали t=t-1, взяли негативы и т. Д. Почему?

Например, при перемещении 345px за 0,5 с у вас будет начальная позиция, b и c=345 при условии, что px - единицымеры.d=0.5 и вы разбиваете анимацию на интервалы по выбранной вами длине (в зависимости от мощности машины, на которой будет выполняться анимация. Мобильные устройства не такие мощные, как настольные ПК, поэтому вы выбираете разумную частоту кадров в данных обстоятельствах),Допустим, мы выбрали 24 кадра в секунду, поэтому мы разбили интервал на 0.5*24 = 12 кадров и вызываем функцию один раз каждые 1/24 th секунды, каждый раз, когда t принимает значения 1/24, 2/24 и т. Д. Если удобнее работать не в секундах, а в кадрах, то d=12 и t принимают значения 1,2, ..., 12.Расчеты в любом случае одинаковы.

Вот хороший пример (щелкните поле, чтобы запустить демонстрацию), не стесняйтесь возиться со значениями:

http://jsfiddle.net/nKhxw/

0 голосов
/ 14 декабря 2016

Спасибо, Джонни!

Вот как реализовать функции замедления Безье: C или Objective-C для iOS

// APPLE ORIGINAL TIMINGS:
//    linear        (0.00, 0.00), (0.00, 0.00), (1.00, 1.00), (1.00, 1.00)
//    easeIn        (0.00, 0.00), (0.42, 0.00), (1.00, 1.00), (1.00, 1.00)
//    easeOut       (0.00, 0.00), (0.00, 0.00), (0.58, 1.00), (1.00, 1.00)
//    easeInEaseOut (0.00, 0.00), (0.42, 0.00), (0.58, 1.00), (1.00, 1.00)
//    default       (0.00, 0.00), (0.25, 0.10), (0.25, 1.00), (1.00, 1.00)

+(double)defaultEase_Linear:(double)t
{
    return t;
}

// Замедление в начале
+(double)defaultEase_In:(double)t
{
    return [AnimationMath easeBezier_t:t

                              point0_x:0
                              point0_y:0

                              point1_x:0.42
                              point1_y:0

                              point2_x:1
                              point2_y:1

                              point3_x:1
                              point3_y:1];
}

// Замедление в конце
+(double)defaultEase_Out:(double)t
{
    return [AnimationMath easeBezier_t:t

                              point0_x:0
                              point0_y:0

                              point1_x:0
                              point1_y:0

                              point2_x:0.58
                              point2_y:1

                              point3_x:1
                              point3_y:1];
}

+(double)defaultEase_InOut:(double)t
{
    return [AnimationMath easeBezier_t:t

                              point0_x:0
                              point0_y:0

                              point1_x:0.42
                              point1_y:0

                              point2_x:0.58
                              point2_y:1

                              point3_x:1
                              point3_y:1];
}

+(double)defaultEase_default:(double)t
{
    return [AnimationMath easeBezier_t:t

                              point0_x:0
                              point0_y:0

                              point1_x:0.25
                              point1_y:0.1

                              point2_x:0.25
                              point2_y:1.0

                              point3_x:1
                              point3_y:1];
}


// For *better understanding* there is p1 and p2, because it is a Bezier curve from 0,0 to 1,0. So, you can remove p1 and p2 from this method, it is just for better understanding what's going on here

double ease_bezier_A(double aA1, double aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
double ease_bezier_B(double aA1, double aA2) { return 3.0 * aA2 - 6.0 * aA1; }
double ease_bezier_C(double aA1)      { return 3.0 * aA1; }

// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
double ease_bezier_calc(double aT, double aA1, double aA2) {
    return ((ease_bezier_A(aA1, aA2)*aT + ease_bezier_B(aA1, aA2))*aT + ease_bezier_C(aA1))*aT;
}

// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
double ease_bezier_get_slope(double aT, double aA1, double aA2) {
    return 3.0 * ease_bezier_A(aA1, aA2)*aT*aT + 2.0 * ease_bezier_B(aA1, aA2) * aT + ease_bezier_C(aA1);
}

double ease_bezier_get_t_for_x(double aX, double mX1, double mX2) {
    // Newton raphson iteration
    double aGuessT = aX;
    for (int i = 0; i < 4; ++i) {
        double currentSlope = ease_bezier_get_slope(aGuessT, mX1, mX2);
        if (currentSlope == 0.0) return aGuessT;
        double currentX = ease_bezier_calc(aGuessT, mX1, mX2) - aX;
        aGuessT -= currentX / currentSlope;
    }
    return aGuessT;
}



// Objective-C
// For ***better understanding*** there is p1 and p2, because it is a Bezier curve from 0,0 to 1,0. So, you can remove p1 and p2 from this method, it is just for better understanding what's going on here
// p1_x always = 0
// p1_y always = 0
// p2_x always = 1.0
// p2_y always = 1.0
+(double)easeBezier_t:(double)t
             point0_x:(double)point0_x point0_y:(double)point0_y
             point1_x:(double)point1_x point1_y:(double)point1_y
             point2_x:(double)point2_x point2_y:(double)point2_y
             point3_x:(double)point3_x point3_y:(double)point3_y
{
    if (point0_x != 0 || point0_y != 0 || point3_x != 1 || point3_y != 1) {
        [NSException raise:@"Error! Your bezier is wrong!!!" format:@""];
    }

    double v = ease_bezier_calc(ease_bezier_get_t_for_x(t, point1_x, point2_x), point1_y, point2_y);

    return v;
}
0 голосов
/ 12 июля 2012

Функции Безье

Заимствовано из http://blog.greweb.fr/2012/02/bezier-curve-based-easing-functions-from-concept-to-implementation/

/**
* KeySpline - use bezier curve for transition easing function
* is inspired from Firefox's nsSMILKeySpline.cpp
* Usage:
* var spline = new KeySpline(0.25, 0.1, 0.25, 1.0)
* spline.get(x) => returns the easing value | x must be in [0, 1] range
*/
function KeySpline (mX1, mY1, mX2, mY2) {

  this.get = function(aX) {
    if (mX1 == mY1 && mX2 == mY2) return aX; // linear
    return CalcBezier(GetTForX(aX), mY1, mY2);
  }

  function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
  function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
  function C(aA1)      { return 3.0 * aA1; }

  // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
  function CalcBezier(aT, aA1, aA2) {
    return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
  }

  // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
  function GetSlope(aT, aA1, aA2) {
    return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
  }

  function GetTForX(aX) {
    // Newton raphson iteration
    var aGuessT = aX;
    for (var i = 0; i < 4; ++i) {
      var currentSlope = GetSlope(aGuessT, mX1, mX2);
      if (currentSlope == 0.0) return aGuessT;
      var currentX = CalcBezier(aGuessT, mX1, mX2) - aX;
      aGuessT -= currentX / currentSlope;
    }
    return aGuessT;
  }
}

Псевдонимы для общих кривых:

{
    "ease":        [0.25, 0.1, 0.25, 1.0], 
    "linear":      [0.00, 0.0, 1.00, 1.0],
    "ease-in":     [0.42, 0.0, 1.00, 1.0],
    "ease-out":    [0.00, 0.0, 0.58, 1.0],
    "ease-in-out": [0.42, 0.0, 0.58, 1.0]
}

Должно быть легко создавать собственные кривые ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...