Android Canvas。基于Touch的圆形路径移动和旋转位图?

时间:2014-09-07 08:12:40

标签: android canvas bitmap

是否可以根据触摸事件沿圆形路径移动和旋转图像,如下所示: enter image description here

我看过这个问题: Moving an Image in circular motion based on touch events in android 但它只告诉我如何沿圆圈移动图像,而不是旋转它。

1 个答案:

答案 0 :(得分:6)

更新:GitHub 上发布的完整示例https://github.com/jselbie/xkcdclock

每次触摸事件时,抓住触摸点的x,y坐标并计算相对于位图中心的旋转角度。使用该值确定旋转想要绘制的位图的大小。

首先,让我们假设一个逻辑坐标系,其中上面元素的中心点位于x,y空间中的(0,0)。

因此,任何触摸点相对于中心的角度(以度为单位)可以按如下方式计算:

double ComputeAngle(float x, float y)
{
    final double RADS_TO_DEGREES = 360 / (java.lang.Math.PI*2);
    double result = java.lang.Math.atan2(y,x) * RADS_TO_DEGREES;

    if (result < 0)
    {
        result = 360 + result;
    }

    return result;
}

注意 - 负角度与正角度的归一化。因此,如果触摸点是(20,20),则上述函数将返回45度。

要使用此方法,您的Activity将需要定义以下成员变量:

float _refX;   // x coordinate of last touch event
float _refY;   // y coordinate or last touch event
float _rotation;  // what angle should the source image be rotated at
float _centerX;         // the actual center coordinate of the canvas we are drawing on
float _centerY;         // the actual center coordinate of the canvas we are drawing on

现在让我们来看看如何跟踪触摸坐标,我们总能拥有最新的&#34; _旋转&#34;变量

所以我们的&#34;触控处理器&#34;对于Android将看起来像这样:

boolean onTouch(View v, MotionEvent event)
{
    int action = event.getAction();
    int actionmasked = event.getActionMasked();

    if (!_initialized)
    {
        // if we haven't computed _centerX and _centerY yet, just bail
        return false;
    }

    if (actionmasked == MotionEvent.ACTION_DOWN)
    {
        _refX = event.getX();
        _refY = event.getY();
        return true;
    }
    else if (actionmasked == MotionEvent.ACTION_MOVE)
    {

        // normalize our touch event's X and Y coordinates to be relative to the center coordinate
        float x = event.getX() - _centerX;
        float y =  _centerY - event.getY();

        if ((x != 0) && (y != 0))
        {
            double angleB = ComputeAngle(x, y);

            x = _refX - _centerX;
            y = _centerY - _refY;
            double angleA = ComputeAngle(x,y);

            _rotation += (float)(angleA - angleB);

            this.invalidate();  // tell the view to redraw itself
        }
    }    

省略了一些精细的细节,比如绘制实际的位图。您可能还希望处理ACTION_UP和ACTION_CANCEL事件以将_rotation标准化为始终在0到360之间。但重点是上面的代码是一个框架,用于计算应在View上绘制Bitmap的_rotation。如下所示:

void DrawBitmapInCenter(Bitmap bmp, float scale, float rotation, Canvas canvas)
{
    canvas.save();
    canvas.translate(canvas.getWidth()/2, canvas.getHeight()/2);
    canvas.scale(scale, scale);
    canvas.rotate(rotation);
    canvas.translate(-bmp.getWidth()/2, -bmp.getHeight()/2);
    canvas.drawBitmap(bmp, 0, 0, _paint);
    canvas.restore();
}