一个很小短但是可以旋转的图片效果(我很短但是我可以旋转)

玩过LOL的人都知道,里面的英雄蛮子的5秒真男人,所以本篇文章也不会太长。。。先贴一个早上司机群里看到的搞笑图片,图片来源于夜神,有需要的可以私信他。。。
这里写图片描述

俗话说得好中午不睡下午崩溃,在这个喜大普奔的日子,我也有和大多数单身狗一样,有一个共同的想法(一大早就被喂了半年的狗粮,我的内心毫无波动,甚至想笑):白天卖花,晚上卖套。。。

抱歉今天出门没吃药,扯了半天还没说到正题。今天要写的内容呢,是一个圆形旋转的效果(渣渣表示写一个效果用了丧心病狂的半天时间),国际惯例效果图先行,请看图
这里写图片描述

本来我之前是做成的点击图片然后获取rgb,但是产品要求要能滑动,好吧做为一个有节操的程序猿,勉为其难写一个效果吧(其实我内心是拒绝的)。具体效果要求是圆环可以旋转,当手指离开的时候要获取指针棒指向图片的位置的rgb值(圆环是图片给的一张整图)。所以呢要解决的问题就2个:

  1. 指针的位置坐标相对于圆盘图片所在的坐标值;根据坐标值获取图片的rgb值
  2. 让圆环转动

    先看最主要的问题怎么让圆盘转动呢,你可以用canvas.rotate(angle, mCenterX, mCenterY)实现转动,要怎么跟随手指转动呢,这个要借用一下高中的数学姿势,由于我高中数学是体育老师教的下面方法我说得不好,不要打我。

先画一个草图讲解一下
这里写图片描述
第一步我们先算down下时候的角度值,然后move时候的角度值相减得到角度差值,用角度差值去旋转画布。看下怎么计算角度值呢

    /**
     * @return The angle of the unit circle with the image views center
     */
    private double getPositionAngle(double xTouch, double yTouch) {
        double x = xTouch - mCenterX;
        double y = mHeight - yTouch - mCenterY;

        switch (getPositionQuadrant(x, y)) {
            case 1:
                return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
            case 2:
            case 3:
                return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
            case 4:
                return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
            default:
                // ignore, does not happen
                return 0;
        }
    }

    /**
     * @return The quadrant of the position
     */
    private static int getPositionQuadrant(double x, double y) {
        if (x >= 0) {
            return y >= 0 ? 1 : 4;
        } else {
            return y >= 0 ? 2 : 3;
        }
    }


下面是重点….很简单先获取象限,然后根据象限获取到弧度值,在把弧度值转换为角度值。获取象限值getPositionQuadrant都应能够看懂,获取角度值的时候有点小问题。数学里面定义的弧度值第一象限是0- π/2,是从x轴开始然后逆时针旋转的值。那么先看1象限的时候:Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;没问题,然后2象限的时候180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);由于是要从x轴开始然后逆时针旋转的值,asin是正值减去一个正值没错;然后2象限的时候180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);由于是要从x轴开始然后逆时针旋转的值,asin是负值减去一个负值没错(相当于是180+一个正值);然后4象限的时候360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;由于是要从x轴开始然后逆时针旋转的值,asin是负值加上一个负值没错(相当于360-一个正值)。当然了你可能也注意到了角度的差值是用的touchStartAngle - currentAngle,因为Canvas旋转是相对于x轴进行顺时针旋转….

至于怎么计算指针棒在圆环对应的位置就不详细讲了,看了代码都应该能够明白
先看RotateView

package com.pd.plugin.pd.led.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.Toast;

/**
 * 详情参考 https://github.com/szugyi/Android-CircleMenu/blob/master/circlemenu/src/main/java/com/szugyi/circlemenu/view/CircleLayout.java
 * Created by Tangxb on 2016/8/8.
 */
public class RotateView extends ImageView {
    private int mWidth;
    private int mHeight;
    private float mRadius;
    private float mCenterX;
    private float mCenterY;
    private float angle;
    // Touch helpers
    private double touchStartAngle;
    private boolean didMove = false;
    private int pointX;
    private int pointY;

    public RotateView(Context context) {
        this(context, null);
    }

    public RotateView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RotateView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public RotateView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
        mRadius = Math.min(w, h) / 2F;
        mCenterX = mWidth / 2F;
        mCenterY = mHeight / 2F;
    }

    public void setNeedPoint(int x, int y) {
        pointX = x;
        pointY = y;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                touchStartAngle = getPositionAngle(event.getX(), event.getY());
                didMove = false;
                break;
            case MotionEvent.ACTION_MOVE:
                double currentAngle = getPositionAngle(event.getX(), event.getY());
                rotateButtons((float) (touchStartAngle - currentAngle));
                touchStartAngle = currentAngle;
                didMove = true;
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (didMove) {
                    rotateViewToCenter();
                }
                break;
        }
        return true;
    }

    public void rotateViewToCenter() {
        if (pointX == 0) return;
        BitmapDrawable drawable = (BitmapDrawable) getDrawable();
        Bitmap srcBitmap = drawable.getBitmap();
        Matrix matrix = new Matrix();
        matrix.postRotate(angle, mCenterX, mCenterY);
        Bitmap tempBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, false);
        int color = tempBitmap.getPixel(pointX, pointY);
        // 如果你想做的更细致的话 可以把颜色值的R G B 拿到做响应的处理
        int r = Color.red(color);
        int g = Color.green(color);
        int b = Color.blue(color);
        Toast.makeText(getContext(), "r=" + r + ",g=" + g + ",b=" + b, Toast.LENGTH_SHORT).show();
    }

    private void rotateButtons(float degrees) {
        angle += degrees;
        invalidate();
    }

    /**
     * @return The angle of the unit circle with the image views center
     */
    private double getPositionAngle(double xTouch, double yTouch) {
        double x = xTouch - mCenterX;
        double y = mHeight - yTouch - mCenterY;

        switch (getPositionQuadrant(x, y)) {
            case 1:
                return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
            case 2:
            case 3:
                return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
            case 4:
                return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
            default:
                // ignore, does not happen
                return 0;
        }
    }

    /**
     * @return The quadrant of the position
     */
    private static int getPositionQuadrant(double x, double y) {
        if (x >= 0) {
            return y >= 0 ? 1 : 4;
        } else {
            return y >= 0 ? 2 : 3;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.rotate(angle, mCenterX, mCenterY);
        super.onDraw(canvas);
    }
}

下面是计算指针位置TestFuckActivity

package com.pd.plugin.pd.led.activity;

import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.Display;
import android.widget.ImageView;

import com.pd.plugin.pd.led.R;
import com.pd.plugin.pd.led.view.RotateView;

/**
 * Created by Tangxb on 2016/8/8.
 */
public class TestFuckActivity extends BaseActivity {
    private RotateView imageView1;
    private ImageView imageView2;
    private int mScreenWidth;
    private Handler mHandler = new Handler();

    @Override
    public int getLayoutResId() {
        return R.layout.layout_fragment_play_three_part02;
    }

    @Override
    protected void initView() {
        imageView1 = getViewById(R.id.iv_color_palette);
        imageView2 = getViewById(R.id.needle);
    }

    @Override
    protected void initData() {
        Display defaultDisplay = getWindowManager().getDefaultDisplay();
        DisplayMetrics displayMetrics = new DisplayMetrics();
        defaultDisplay.getMetrics(displayMetrics);
        mScreenWidth = displayMetrics.widthPixels;
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                int[] location1 = new int[2];
                int[] location2 = new int[2];
                imageView1.getLocationInWindow(location1);
                imageView2.getLocationInWindow(location2);
                int x2 = location2[0];
                int y2 = location2[1];
                int y = y2 + imageView2.getHeight() / 2;
                int x = 0;
                if (x2 > mScreenWidth / 2) {
                    x = imageView2.getWidth() / 2 - location1[0];
                } else {
                    x = imageView1.getWidth() / 2 + x2 - mScreenWidth / 2;
                }
                imageView1.setNeedPoint(x, y);
            }
        }, 200);
    }
}

至于里面的圆环旋转加速度之类的暂时考虑。。。。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值