Использование матрицы преобразования в KineticJS
У меня есть тело, смоделированное с помощью Box2Dweb, и изображение, прикрепленное к телу. Я хочу взять матрицу преобразования тела и применить преобразование к изображению (нарисовать изображение с преобразованием), чтобы его положение и ориентация (относительная) на экране совпадали с позицией тела. Я не могу найти функцию для использования с матрицей преобразования в KineticJS. Есть отдельные функции для перемещения и вращения, и есть Kinetic.Transform
класс, который содержит некоторую "матрицу" внутри, но я понятия не имею, что с этим делать. Там также есть _setTransform
где-то функционировать, но опять же, не знаю, как его использовать (и подчеркивает ли это, что я не должен вызывать его напрямую или как?).
Я использовал этот код для рисования изображений поверх тел в простом Javascript:
function drawImageOverBody(context, body, image, scale)
{
context.save();
var pos = body.GetPosition();
var center = [scale*pos.x, scale*pos.y];
var R = body.GetTransform().R;
context.translate(center[0], center[1]);
context.transform(R.col1.x, R.col1.y, R.col2.x, R.col2.y, 0, 0);
context.translate(-center[0], -center[1]);
context.drawImage(image, center[0] - image.width/2.0, center[1] - image.height/2.0);
context.restore();
}
Как мне сделать то же самое с KineticJS?
РЕДАКТИРОВАТЬ: очевидно, единственные преобразования, которые я могу получить от Box2d, это перевод и вращение, которые я могу получить, вызвав GetPosition()
а также GetAngle()
на теле Box2d, затем примените к изображению KineticJS с setX(), setY()
а также setRotation()
, Поэтому мне не нужно преобразование в матричной форме здесь. Тем не менее, любопытно.
1 ответ
Kinetic.Transform
Класс может быть использован для вычисления поворота, масштаба и смещения от заданной матрицы преобразования. Установить m
атрибут Kinetic.Transform
к матрице преобразования, затем используйте объект преобразования для вычисления поворота, масштаба и перемещения. Вращение, масштабирование и перевод могут быть применены к любому Kinetic.Node
Перевод дается непосредственно двумя последними пунктами в матрице.
Если вы приобрели преобразование из другого места, вы можете применить его к Kinetic.Transform
как это:
var tf = new Kinetic.Transform (); tf.m = [Math.sqrt (2), Math.sqrt (2), -3 / 2 * Math.sqrt (2), 3/2 * Math.sqrt (2), 4, 5];
Перевод самый простой. это дано двумя последними элементами: 4 в направлении X, 5 в направлении Y. Существует также способ получить его.
var translation = tf.getTranslation ();
Вы можете получить масштаб из матрицы преобразования:
var m = tf.getMatrix(); // or tf.m
var scaleX = Math.sqrt(m[0]*m[0] + m[1]*m[1]);
var scaleY = Math.sqrt(m[2]*m[2] + m[3]*m[3]);
Не забывайте, что изображение может быть перевернуто по оси X или Y или обоим. Рассчитайте определитель, чтобы принять это во внимание:
if(m[0]*m[3] - m[1]*m[2] < 0){
scaleY = -scaleY;
}
Отрегулируйте знак весов, чтобы легче было вращать:
if(m[0] < 0){
scaleX = -scaleX;
scaleY = -scaleY;
}
Теперь последний, вращение. Вы можете получить это с помощью Math.asin
или же Math.acos
, но вы должны принять во внимание квадрант угла поворота. Это один из способов ее решения:
var angle = Math.acos(m[3] / scaleY);
if(m[2]/scaleY > 0){
angle = -angle;
}
Обратите внимание, что порядок применения различных преобразований важен. Если вы используете метод, описанный выше, сначала примените перевод, затем вращение, затем масштабирование.