ActionScript 3 - анимация вращения roroundAroundExternalPoint - PullRequest
2 голосов
/ 20 июня 2010

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

альтернативный текст http://www.freeimagehosting.net/uploads/0b937c92e6.png

на изображении выше3 состояния подростка.состояние 1 показывает красный прямоугольник в начале линии без угла.состояние 2 показывает, что красный прямоугольник имеет ползунок вдоль линии с углом 45º, что также составляет половину общего угла 90º.состояние 3 показывает конечную позицию анимации, где красный прямоугольник имеет угол 90º и расположен на краю линии.

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

вот мой код, который не работает, но, надеюсь, даст вам более четкое представление о том, что я пытаюсь.

var angle:Number = 90;
var previousAngle:Number = 0;

var distanceObject:Object = new Object();
distanceObject.distance = line.width;

distanceTween = new Tween(distanceObject, "distance", None.easeNone, 0, distanceObject.distance, 5, true);
distanceTween.addEventListener(TweenEvent.MOTION_CHANGE, tweenHandler);

function tweenHandler(evt:TweenEvent):void
    {
    var angleShift:Number = (angle / distance) * distanceObject.distance;

    //1:tween RedBox position
    redBox.x = line.x + line.width * distanceObject.distance;

    //2:tween RedBox angle
    var externalPointMatrix:Matrix = redBox.transform.matrix;
    MatrixTransformer.rotateAroundExternalPoint(externalPointMatrix, 0 + redBox.width * distanceObject.distance, 0, angleShift - previousAngle);
    redBox.transform.matrix = externalPointMatrix;

    previousAngle = angleShift;
    }

1 Ответ

2 голосов
/ 22 июня 2010

Не думаю, что вы достаточно хорошо определили проблему для общего решения. Здесь меняются три вещи: x, y и вращение. Каждый из них рассчитывается как результат точки на прямоугольнике (синий «х» на вашей диаграмме), которая меняется со временем. Это означает, что на 1001 * first нужно сосредоточиться, это точка на прямоугольнике, которая меняется со временем. Далее вам нужно знать, что x и y можно вычислить, используя эту точку вместе с вращением.

Так разбейте его на шаги.

  1. найти местоположение точки "x" на линии
  2. повернуть объект
  3. найти местоположение точки "x" по отношению к прямоугольнику
  4. на основе угла поворота и известного местоположения точки "x", вычислить положение x и y прямоугольника ( SOHCAHTOA )

Вот некоторый код для иллюстрации:

package
{

import com.greensock.TweenNano;

import flash.display.Sprite;
import flash.events.Event;

[SWF(width='500', height='300', backgroundColor='#ffffff', frameRate='30')]
public class BoxAnim extends Sprite
{
    private static const LINE_WIDTH:int = 350;
    private static const RECT_WIDTH:int = 150;
    private static const RECT_HEIGHT:int = 100;
    private static const FINAL_ROTATION:Number = Math.PI/2;

    public var point:Number;

    private var line:Sprite;
    private var rect:Sprite;
    private var cross:Sprite;

    public function BoxAnim()
    {
        addEventListener(Event.ADDED_TO_STAGE, addedToStage);
    }

    private function addedToStage(event:Event):void
    {
        line = new Sprite();
        addChild(line);
        line.graphics.lineStyle(10, 0x0);
        line.graphics.lineTo(LINE_WIDTH, 0);
        line.x = 50;
        line.y = 175;

        rect = new Sprite();
        addChild(rect);
        rect.graphics.lineStyle(4, 0xFF0000);
        rect.graphics.beginFill(0xFF0000, 0.5);
        rect.graphics.drawRect(0, 0, RECT_WIDTH, RECT_HEIGHT);
        rect.x = 50;
        rect.y = 175;

        cross = new Sprite();
        addChild(cross);
        cross.graphics.lineStyle(5, 0x41a9f4);
        cross.graphics.moveTo(-5, -5);
        cross.graphics.lineTo(5, 5);
        cross.graphics.moveTo(5, -5);
        cross.graphics.lineTo(-5, 5);
        cross.x = 50;
        cross.y = 175;

        point = 0;
        TweenNano.to(this, 3, {point: 1, onUpdate: tick});
    }

    private function tick():void
    {
        // first calculate where the point should be on the line
        cross.x = (point * LINE_WIDTH) + line.x;

        // calculate the angle of rotation
        var rotationRadians:Number = (point * FINAL_ROTATION);
        rect.rotation = rotationRadians*180/Math.PI;

        // calculate where on the rectangle the point would be
        var rectCrossX:Number = (point * RECT_WIDTH);
        // use trig to find the x & y points
        rect.x = cross.x - Math.cos(rotationRadians)*rectCrossX;
        rect.y = cross.y - Math.sin(rotationRadians)*rectCrossX;
    }
}

}

Я просто использую переменную point в процентах от 0 до 1. Затем я масштабирую ее, чтобы найти положение точки «x» на линии. Масштабируйте это снова, чтобы выяснить вращение. Масштабируйте его снова, чтобы найти, где оно лежит вдоль вершины прямоугольника. Затем trig решает расположение угла прямоугольника относительно точки.

...