Перетаскивание повернутого текста внутри Android canvas не работает должным образом
есть что-то, чего мне не хватает, поэтому я надеюсь, что вы сможете поделиться со мной светом.
Я рисую текст внутри canvas. Для этого у меня есть класс Word
public class Word {
private int x;
private int y;
private String text;
}
приложение позволяет пользователю вращать текст, и я обрабатываю вращение withing onDraw
protected void onDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(angle, centerX, centerY)
...
canvas.drawText(word.getText(), word.getX(), word.getY())
....
canvas.restore();
}
проблема, которую я получаю, - это когда пользователь перетаскивает холст, и есть набор вращения. Когда угол=0 движение идет как ожидалось.
@Override
public boolean onTouchEvent(MotionEvent event) {
case MotionEvent.ACTION_DOWN:
initialX = (int) event.getX();
initialY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int currentX = (int) event.getX();
int currentY = (int) event.getY();
int xMovement = currentX - initialX;
int yMovement = currentY - initialY;
dragWords(xMovement, yMovement);
.....
и dragWords
для каждое слово я:
private void dragText(int xMovement, int yMovement){
for (Word word : words) {
word.setX(word.getX() + xMovement);
word.setY(word.getY() + yMovement);
}
invalidate();
}
когда угол поворота равен 0, перемещение вверх/вниз/влево/вправо заставляет слова двигаться на одинаковое расстояние. Как угол становится больше, слова начинают двигаться в пригороды, например в 60, он начинает идти по диагонали вверх, после 180 она двигается только вверх/вниз, а не влево/вправо.
Я думаю, что мне нужно вычислить какую-то разницу на основе угла и добавить ее в xMovement/yMovement... но как мне это сделать? ?
LE: вот изображение о том, как он ведет себя: Синие линии - это то, как текст перемещается по перетаскиванию, в то время как оранжевый-это перетаскивание пальца по экрану. Когда угол равен 0, он работает довольно хорошо, когда угол увеличивается, он начинает двигаться по диагонали влево/вправо, а когда угол еще больше, он движется только вверх и вниз и не реагирует на left / right
2 ответов
на ellipses
в следующий код:
dragWords(xMovement, yMovement);
..... <<<--------------------- I hope you are updating initialX and initialY
initialX = currentX;
initialY = currentY;
в противном случае ваши значения x и y не будут правильно соответствовать количеству расстояния, перемещенного во время сенсорного жеста.
как указано, вы должны использовать Matrix#mapPoints(float[])
для преобразования значений x и y. Объявить и инициализировать матрицу:
Matrix correctionMatrix;
// Your view's constructor
public MyView() {
....
correctionMatrix = new Matrix();
}
вот как ваш onDraw(Canvas)
должен выглядеть так:
@Override
protected void onDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(angle, centerX, centerY);
...
// Neutralize the rotation
correctionMatrix.setRotate(-angle, centerX, centerY);
// Initialize a float array that holds the original coordinates
float[] src = {word.getX(), word.getY()};
// Load transformed values into `src` array
correctionMatrix.mapPoints(src);
// `src[0]` and `src[1]` hold the transformed `X` and `Y` coordinates
canvas.drawText(word.text, src[0], src[1], somePaint);
....
canvas.restore();
}
это должно дать вам желаемые результаты-движение в Ось X и Y независимо от вращения холста.
вы можете, очевидно, переместить вызов в setRotate(float, float, float)
в лучшее место. Вам нужно только позвонить один раз после изменения angle
значение.
если я правильно понимаю, проблема в том, что Canvas.rotate()
не только поворачивает направление текста, но и весь холст. Поэтому координаты x-y слов также поворачиваются от указанной точки поворота.
чтобы соответствовать перемещению перетаскивания, вы можете использовать Matrix
для этого, а именно обратная матрица того, который вы используете для поворота холста. Он будет использоваться для преобразования x-y координаты слов к их первоначальным, pre-rotate положениям.
например, вычислите это один раз и обновите его, когда angle
, centerX
или centerY
изменения.
// rotMatrix is the same operation applied on the canvas.
Matrix rotMatrix = new Matrix();
rotMatrix.postRotate(mAngle, centerX, centerY);
// Invert it to convert x, y to their transformed positions.
Matrix matrix = new Matrix();
rotMatrix.invert(matrix);
затем, при рисовании каждого слова:
int wordX = ...
int wordY = ...
String text = ...
float[] coords = new float[] { wordX, wordY };
matrix.mapPoints(coords);
canvas.drawText(text, coords[0], coords[1], paint);