прямая манипуляция
я сделал маленький пример прямой манипуляции объектом с использованием мультитача, потому что не нашёл общий язык с hammer.js. Зато теперь я знаю, как это работает. В правильных реализациях те точки, за которые вы «ухватили» объект, остаются строго под вашими пальцами по мере движения. Например, если один палец остаётся неподвижен, а другой движется по кругу вокруг него, то объект будет вращаться вокруг «зажатой» точки.
трюк заключается в том, чтобы при перемещении пальцев в новые координаты вычислить такое преобразование объекта, которое перенесёт в эти координаты зажатые первыми точки. Можно попробовать задать такое преобразование при помощи операторов CSS transform translate
, scale
и rotate
, но вычислять для них значения будет неудобно. Зато надёжно сработает метод с использованием матрицы, хотя и тут без вычислений не обойтись. Удивительно, что готовых формул в интернете мне найти не удалось, и пришлось самому вспоминать линейную алгебру, операции с матрицами, и решение систем линейных уравнений. Имея новые координаты S1
и S2
, матрица для переноса точек I1
и I2
к этим координатам вычисляется так:
var a = ((S1.x - S2.x) * (I1.x - I2.x) + (S1.y - S2.y) * (I1.y - I2.y)) /
(Math.pow(I1.y - I2.y, 2) + Math.pow(I1.x - I2.x, 2));
var c = ((S1.y - S2.y) - a * (I1.y - I2.y)) / (I1.x - I2.x);
var tx = S1.x - a * I1.x + c * I1.y;
var ty = S1.y - c * I1.x - a * I1.y;
return new Matrix([
[a, -c, tx],
[c, a, ty],
[0, 0, 1]
]);
а дальше всё просто: при первых касаниях мы запоминаем точки объекта, за которые ухватились, и при последующих вычисляем по этому алгоритму матрицу и вставляем её в стиль объекта.