ImageEditor库详解—————StickerView详解

ImageEditorLibrary是安卓中一款图形编辑的开源控件,支持自定义贴图,图片滤镜,图片旋转以及图片裁剪的操作,正好由于最近项目中也需要使用到一些这样的功能,最近就将这个库中的一些代码进行分析一下。
首先作者的项目地址如下:
https://github.com/siwangqishiq/ImageEditor-Android
今儿就来分析下他其中核心部件之一的StickerView及StickerItem的内容。首先介绍一下这两个类实现的功能:通过这两个类可以实现添加多张图片,并提供对这其中的每张图片进行缩放,旋转及移动的功能,具体的功能可以通过下图有个大致的了解:
这里写图片描述
从图中就可以看出可以添加好几张图片,所以就需要对每张图片进行一下封装处理,这就促成了StickerItem的生成,同时,我们又能看到这个图片的外边框带有四个功能键,所以这就需要我们在这个item中将这几个功能图标给画出来,画的画就是canvas的drawbitmap方法了,没什么好说的,主要的还是这几行功能图的位置,所以我们定义了几个矩形:

public RectF desRectF;//内容区域
public RectF deleteRectF;//删除
public RectF rotateRectF;//旋转
public RectF editRectF;//编辑
public RectF scaleRectF;//缩放
public RectF helpBoxRectF;//辅助线

通过这些矩阵,对于接下来的需要操作的图片平移,缩放以及旋转还是很好操作的,对于平移操作,就只需要传入x和y的偏移量dx,dy:

 //位置移动
    public void updatePos(float dx,float dy){
        matrix.postTranslate(dx,dy);

        desRectF.offset(dx,dy);

        helpBoxRectF.offset(dx,dy);
        deleteRectF.offset(dx,dy);
        editRectF.offset(dx,dy);
        scaleRectF.offset(dx,dy);
        rotateRectF.offset(dx,dy);

        deleteRealRect.offset(dx,dy);
        editRealRect.offset(dx,dy);
        scaleRealRect.offset(dx,dy);
        rotateRealRect.offset(dx,dy);
    }

之后关于缩放,就需要计算一下缩放比,其中需要使用到以前学过的三角函数的知识:

float c_x=desRectF.centerX();
float c_y=desRectF.centerY();
float x=scaleRealRect.centerX();
float y=scaleRealRect.centerY();
float n_x=x+dx;
float n_y=y+dy;
float xa=x-c_x;
float ya=y-c_y;
float xb=n_x-c_x;
float yb=n_y-c_y;
float srcLen= (float) Math.sqrt(xa*xa+ya*ya);
float curLen= (float) Math.sqrt(xb*xb+yb*yb);
float scale = curLen/srcLen;

其中scaleRealRect只图形的右下角缩放按钮的位置矩形,计算出缩放比就可以比较容易的进行缩放操作,矩形的话就是它们的各边乘上改缩放比,其中他的写法中需要注意的一点是我们需要在额外写四个矩阵一记录这四个按钮的真实坐标,具体原因后面他在进行旋转绘制的时候是将整个画布进行了旋转的操作,所以如果还是拿原始的矩形坐标会出现问题。
对于之后的旋转操作,需要注意的是其中计算旋转角度的固定公式:

 double cos = (xa * xb + ya * yb) / (srcLen * curLen);
 if (cos > 1 || cos < -1)
     return;
 float angle = (float) Math.toDegrees(Math.acos(cos));

 // 定理
 float calMatrix = xa * yb - xb * ya;// 行列式计算 确定转动方向

 int flag = calMatrix > 0 ? 1 : -1;
 angle = flag * angle;

之后对这些矩形进行相应的旋转操作,主要还是用到三角函数来计算,具体的方式可以自己去推导一下:

 float x = rect.centerX();
 float y = rect.centerY();
 float sinA = (float) Math.sin(Math.toRadians(roatetAngle));
 float cosA = (float) Math.cos(Math.toRadians(roatetAngle));
 float newX = center_x + (x - center_x) * cosA - (y - center_y) * sinA;
 float newY = center_y + (y - center_y) * cosA + (x - center_x) * sinA;

 float dx = newX - x;
 float dy = newY - y;

 rect.offset(dx, dy);

至此,图形的缩放,旋转和平移的功能都已写完,之后就是处理何时调用这些相应的方法了,这就是StickerView的作用了,就是重写它的onTouchEvent方法,并在其中对我们所接触的点坐标与那四个功能按钮坐标的比较了,其中主要的一个方法就是矩形RectF具有一个contains(float x,float y)方法用来判断该点是否在这个矩形范围之内,让后就是在对应的范围内进行对应的操作就可以了。
突然这么回顾一下,发现这个功能也不是特别的繁琐嘛,其实对看个几遍代码也就能搞懂了他的操作逻辑,需要注意的是他库中提供出来的将缩放和旋转集中到了一起去了,而我们的项目需要把这两个功能分开,所以以上内容其实是按照我改了一点逻辑后来总结的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值