【问题标题】:Android Canvas. Moving and Rotating Bitmap along Circular Path based on Touch?安卓画布。基于触摸沿圆形路径移动和旋转位图?
【发布时间】:2014-09-07 08:12:39
【问题描述】:

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

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

【问题讨论】:

  • 我以前做过这个...让我看看我是否可以挖掘代码。
  • 你可以使用任何路径来做到这一点,为此使用 PathMeasure 类
  • 但这也会旋转图像吗?

标签: android canvas bitmap


【解决方案1】:

更新:完整示例发布在 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

现在让我们看看如何跟踪触摸坐标,以便我们始终拥有一个最新的“_rotation”变量。

所以我们的 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 之间。但要点是上面的代码是一个框架,用于计算应在视图上绘制位图的 _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();
}

【讨论】:

  • 实现代码时。我遇到了2个问题。图像正在快速移动,并且它不在我触摸屏幕的方向上。
  • @TastyLemons - 我已经在 github.com/jselbie/xkcdclock 发布了我的完整示例 Android 项目。我希望这会有所帮助。
  • @TastyLemons - 您似乎还暗示您希望位图旋转捕捉到与手指按压相同的角度位置。这应该很容易通过在 ACTION_DOWN 事件上调用 ComputeAngle 并将其设置为活动旋转来添加,然后使视图无效以便重绘。我无法为您编写代码,但只需稍加工作,您就可以根据自己的需要调整我为您提供的内容。
  • 谢谢@selbie,你救了我。这段代码就像一个魅力。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 2016-09-22
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
相关资源
最近更新 更多