简体   繁体   English

如何使用画布缩放

[英]how to scale using canvas

i am using this code to scale my canvas around a focus point 我正在使用此代码围绕焦点缩放画布

 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;
        }
    }

and this is the code i use to scale inside the ondraw method 这是我用来在ondraw方法中缩放的代码

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

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

my problem is when i start scaling around the focus point (200,200) for example ,at first it start going there but than while increasing the scale it start going away from the point . 我的问题是,例如,当我开始围绕焦点(200,200)进行缩放时,起初它开始向该点移动,但是当增大缩放比例时,它开始偏离该焦点。 so my problem is how i scale toward a specific point so that that this point becomes the center of the viewport while scaling . 所以我的问题是我如何朝特定点缩放,以便在缩放时该点成为视口的中心。

I think i should use canvas.translate() with it but i don't know how much i should move the x and y position of canvas while scaling . 我想我应该将canvas.translate()与它一起使用,但是我不知道在缩放时应该移动画布的x和y位置多少。

Edit:the image below summarize what i am trying to say 编辑:下面的图像总结了我想说的

image 图片

There are several things to bear in mind here: 这里有几件事要牢记:

  1. The ScaleDetector only detects scaling events; ScaleDetector仅检测缩放事件。 this sounds good but is not sufficient by itself to handle pinch/zoom in 2D (eg. in a picture). 这听起来不错,但仅靠其本身不足以处理2D图像(例如,图片中的图像)。
  2. The 'focus' returned by the detector is the mid point between the two pointers (fingers); 检测器返回的“焦点”是两个指针(手指)之间的中点。 this is less useful since the natural assumption when you start scaling is that the image pixel under your finger will remain under your finger as you zoom. 这没什么用,因为开始缩放时的自然假设是,随着缩放,手指下方的图像像素将保留在手指下方。 People often move fingers at different speeds (or deliberately keep one finger stationary), which invalidates the use of the mid-point. 人们经常以不同的速度移动手指(或故意保持一根手指静止),这使中点的使用无效。
  3. You (probably) want to handle rotation too. 您(可能)也想处理旋转。

The broad approach I have used in the past is: 我过去使用的广泛方法是:

  • manually detect first and second touch events; 手动检测第一触摸事件和第二触摸事件; record the coordinate of the two pointers when the second pointer touch event occurs. 当第二个指针触摸事件发生时,记录两个指针的坐标。 These points are to logically 'follow' the pointers from now on. 这些要点是从现在开始逻辑上“跟随”指针。
  • when a motion event occurs that continues to have two pointers down (ie. a two fingered rotation, zoom, or drag), determine the translation, scale and rotation as follows: 当发生继续向下移动两个指针的运动事件(即,两指旋转,缩放或拖动)时,请按以下方式确定平移,缩放和旋转:
    • the scale is based on the distance between the new points compared to the original points (recorded at the start) 比例基于新点与原始点之间的距离(在开始时记录)
    • the rotation is based on the difference in the angle between the first two points and the angle between the most recent points 旋转基于前两个点之间的角度与最近点之间的角度之差
    • the translation is based arbitrarily on one of the points (usually the first) - just translate based on the pixels between the original point and the latest point 翻译是任意基于一个点(通常是第一个)-只是基于原始点和最新点之间的像素进行翻译
    • these values can be calculated and stored during the motion event, then used in onDraw() method 这些值可以在运动事件期间进行计算和存储,然后在onDraw()方法中使用

Note that in onDraw(): 注意在onDraw()中:

  • It's important to perform the translation first since you are working in screen pixels for the two reference points. 首先执行转换很重要,因为您正在为两个参考点使用屏幕像素。
  • you can then rotate & scale in any order since the scale is always equal in the X & Y direction 然后您可以按任意顺序旋转和缩放,因为缩放在X和Y方向上始终相等

Edit to address more specific request: 编辑以解决更具体的请求:

If all you really need to do is simply scale around a specific redefined point p (px, py) by an amount s, and keep p visible, then you can do the following: 如果您真正需要做的只是简单地将特定的重新定义点p(px,py)缩放s,并使p可见,那么您可以执行以下操作:

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

This should keep p in the same pixel-position it was in prior to scaling. 这应将p保持在缩放之前的相同像素位置。 This will suffer from all the problems alluded to above as well as the risks of drift due to successive scale events around a moving focus (based on your original code). 这将遭受上面提到的所有问题,以及由于围绕移动焦点的连续缩放事件(基于原始代码)而导致的漂移风险。 You are far better off doing what I described above. 您做我上面描述的事情要好得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM