【问题标题】:how to scale using canvas如何使用画布进行缩放
【发布时间】:2016-07-22 09:22:43
【问题描述】:

我正在使用此代码围绕焦点缩放我的画布

 private class MyScaleDetector
            extends ScaleGestureDetector.SimpleOnScaleGestureListener {


        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            float focusx=detector.getFocusX();
            float focusy=detector.getFocusY();
             return super.onScaleBegin(detector);

        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float factor=detector.getScaleFactor();

              scale *= factor;


            scale = Math.max(0.4f, Math.min(scale, 20.0f));


            return true;
        }
    }

这是我用来在 ondraw 方法中缩放的代码

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

       canvas.scale(scale,scale,focusx,focusy);
}

我的问题是,例如,当我开始围绕焦点 (200,200) 进行缩放时,起初它开始到那里,但在增加比例时它开始远离该点。所以我的问题是我如何向特定点缩放,以便在缩放时该点成为视口的中心。

我认为我应该使用 canvas.translate() 但我不知道在缩放时我应该移动画布的 x 和 y 位置。

编辑:下图总结了我想说的话

image

【问题讨论】:

    标签: java android math canvas coordinate-transformation


    【解决方案1】:

    这里有几件事要记住:

    1. ScaleDetector 只检测缩放事件;这听起来不错,但它本身不足以处理 2D 中的捏合/缩放(例如在图片中)。
    2. 检测器返回的“焦点”是两个指针(手指)之间的中点;这不太有用,因为当您开始缩放时的自然假设是您手指下的图像像素将在您缩放时保持在您的手指下。人们经常以不同的速度移动手指(或故意保持一根手指不动),这使中点的使用无效。
    3. 您(可能)也想处理旋转。

    我过去使用的广泛方法是:

    • 手动检测第一次和第二次触摸事件;记录第二个指针触摸事件发生时两个指针的坐标。这些要点是从现在开始在逻辑上“遵循”指针。
    • 当运动事件发生且两个指针持续向下(即两指旋转、缩放或拖动)时,确定平移、缩放和旋转如下:
      • 比例基于新点与原始点之间的距离(在开始时记录)
      • 旋转基于前两点之间的角度与最近点之间的角度的差异
      • 翻译基于任意一个点(通常是第一个点) - 仅基于原始点和最新点之间的像素进行翻译
      • 这些值可以在运动事件期间计算和存储,然后在 onDraw() 方法中使用

    注意在onDraw()中:

    • 首先执行转换很重要,因为您正在处理两个参考点的屏幕像素。
    • 然后您可以按任意顺序旋转和缩放,因为缩放在 X 和 Y 方向上始终相等

    编辑以解决更具体的要求:

    如果您真正需要做的只是简单地将特定重新定义的点 p (px, py) 缩放 s,并保持 p 可见,那么您可以执行以下操作:

    canvas.translate(px, py);
    canvas.scale(s,s);
    canvas.translate(-px*s, py*s);
    

    这应该使 p 保持在缩放之前相同的像素位置。这将受到上述所有问题的影响,以及由于围绕移动焦点的连续缩放事件(基于您的原始代码)而导致的漂移风险。你最好按照我上面的描述做。

    【讨论】:

    • 感谢详细信息,但您没有提到如何围绕特定点进行缩放,这是个问题,我已经知道可以缩放多少并且效果很好,我测试了它以围绕中点缩放屏幕的高度和宽度,它工作得非常好,但是如果我围绕另一个点进行缩放,它会在缩放开始时开始到达那里,但它开始远离该点,所以你可以看到我需要找到一种方法,所以我可以在缩放时使这个焦点成为视口的中心
    • 您完全按照您的做法围绕特定点进行缩放。为确保这一点仍然可见,还有一些工作要做,请参阅我的更新答案
    猜你喜欢
    • 2012-10-13
    • 2013-08-09
    • 2016-08-30
    • 2021-08-19
    • 1970-01-01
    • 2011-10-10
    • 2016-09-26
    • 1970-01-01
    • 2014-11-06
    相关资源
    最近更新 更多