Увеличьте точку на холсте, где все основано на определенной точке - PullRequest
0 голосов
/ 04 мая 2018

Хорошо, немного странно. Я сделаю все возможное, чтобы объяснить. Я создаю игру на Android (Java). И я сначала прорабатываю взгляды. Первое, над чем я работаю, это вид Солнечной системы (сверху вниз, 2d, без наклона). У меня все планеты и звезды отображаются правильно и пропорционально. Я могу панорамировать и масштабировать. Единственная проблема в том, как я настроил все круги для рисования, все они основаны на одной точке (где находится звезда), и когда я «масштабирую» / «панорамирую», я на самом деле не увеличиваю / панорамирование. Для панорамы я просто перемещаю точку, где все вращается, а для масштабирования я не масштабирую весь холст (пробовал, не получилось) Я корректирую размер элементов чертеж, в соответствии с зумом.

Итак, у меня есть «звезда», которая начинается в середине экрана, точка называется orbitLocation. И переменная масштабирования, которая начинается с 1f. Звезда нарисована очень просто - canvas.drawCircle((float)orbitLocation.x, (float)orbitLocation.y, this.radius * zoom, this.paint);

Каждая из планет расположена так: canvas.drawCircle(getPlanetX(angle, orbitLocation, zoom), getPlanetY(angle, orbitLocation, zoom), this.radius * zoom, this.paint);

getPlanetX и getPlanetY выглядят так:

private float getPlanetX(double angle, Point orbitingPoint, float zoom) {
        return orbitingPoint.x + (this.distance * Constants.AU * zoom) * (float)Math.sin(angle);
    }

    private float getPlanetY(double angle, Point orbitingPoint, float zoom) {
        return orbitingPoint.y + (this.distance * Constants.AU * zoom) * (float)Math.cos(angle);
    }

Constants.AU - это константа int 11507 для астрономической единицы - для правильного масштабирования.

Теперь проблема, с которой я столкнулся при масштабировании, заключается в том, что, если я перемещаюсь, а затем увеличиваю масштаб, все это масштабируется от местоположения orbit, независимо от того, где я пытаюсь увеличить масштаб, так что все, что было прямо в середине моего экран быстро сбрасывается с экрана.

Желаемый результат. Имейте все, что находится в центре экрана (или в крайнем случае между пальцами), оставайтесь в центре экрана, и точка орбиты настраивается в соответствии.

Вот соответствующая часть моего сенсорного события:

if (touchCount == 2) { // if pinch
                    if (startZoomTouchPoint != null) {
                        float newDistance = getDistance(event, 0, 1);
                        float distanceDifference = (startZoomDistance - newDistance);
                        zoom -= distanceDifference * (zoom / 100);
                        if (zoom < MIN_ZOOM) {
                            zoom = MIN_ZOOM;
                        }

//                        Point zoomCenter = getZoomCenter(event);
//                        int yOrbitOffset = orbitLocation.y - zoomCenter.y;
//                        int xOrbitOffset = orbitLocation.x - zoomCenter.x;
//                        orbitLocation.x += xOrbitOffset + Constants.AU * zoom;
//                        orbitLocation.y += yOrbitOffset + Constants.AU * zoom;

                        startZoomDistance = newDistance;
                        updateStartZoomTouchPoint(event);
                    }
                }

Эти прокомментированные строки в середине - моя последняя попытка достичь цели.

Каждый раз, когда я пытаюсь, я либо перемещаю orbitLocation слишком сильно, либо недостаточно, либо он странно движется.

getZoomCenter буквально просто получает точку между двумя пальцами. Мы можем просто использовать центр экрана, если это проще.

Хорошо, это все, что у меня есть. Дайте мне знать, если вам нужна дополнительная информация.

1 Ответ

0 голосов
/ 04 мая 2018

Пожалуйста, посмотрите следующий фрагмент кода

private ScaleGestureDetector mScaleDetector;
private float zoom = 1.f;

public MyCustomView(Context mContext){
    ...
    // View code goes here
    ...
    mScaleDetector = new ScaleGestureDetector(context, new 
    ScaleListener());
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // Let the ScaleGestureDetector inspect all events.
    mScaleDetector.onTouchEvent(ev);
    return true;
}

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.save();
    canvas.scale(zoom, zoom);
    ...
    // onDraw() code goes here
    ...
    canvas.restore();
}

private class ScaleListener
    extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        mScaleFactor *= detector.getScaleFactor();

        // Don't let the object get too small or too large.
        zoom = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

        invalidate();
        return true;
    }
}

По сути, вам нужно масштабировать холст на основе значения масштаба, полученного из события касания. Вы можете сделать это по

  1. Сохранить холст
  2. Масштаб холста
  3. Нарисуйте, что вы рисовали
  4. Восстановить холст

, и вы можете установить масштаб в ответ на детектор жестов масштаба. Позвоните, чтобы сделать недействительным впоследствии.

Для получения дополнительной информации посетите https://developer.android.com/training/gestures/scale

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