首页 > 解决方案 > 放大画布中的某个点,其中所有内容都基于某个点

问题描述

好吧,有点奇怪。我会尽力解释。我正在 Android (Java) 上构建游戏。我只是先制定意见。我要做的第一件事是太阳系视图(自上而下,二维,无倾斜)。我已经正确地按比例显示了所有行星和恒星。我可以平移和缩放。唯一的问题是,我设置所有要绘制的圆圈的方式,它们都基于一个点(星星所在的位置),当我“缩放”/“平移”时,我实际上并没有缩放/平移。对于平移,我只是在移动一切旋转的点,对于缩放,我没有缩放整个画布(尝试过,没有成功)我正在调整元素的大小绘图,按照缩放。

所以我有一个从屏幕中间开始的“星星”,这个点叫做轨道位置。还有一个从 开始的缩放变量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);

getPlanetXgetPlanetY看起来像这样:

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- 用于适当的缩放。

现在我在缩放时遇到的问题是,如果我平移,然后缩放,整个事情都会从轨道位置缩放,而不管我试图放大的位置,所以无论我的屏幕中间是什么,很快被扔出屏幕。

期望的结果。让屏幕中心的任何东西(或夹在手指之间,无论哪种方式),保持在屏幕的中心,并且轨道点会根据自身进行调整。

这是我的触摸事件的相关部分:

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从字面上看,只是在两根手指之间。如果这样更容易,我们可以使用屏幕的中心。

好吧,这就是我所拥有的。如果您需要更多信息,请告诉我。

标签: javaandroidcanvas

解决方案


请看下面的代码片段

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


推荐阅读