Android中利用matrix 控制图片的旋转、缩放、移动
程序员文章站
2023-11-29 22:53:58
本文主要讲解利用android中matrix控制图形的旋转缩放移动,具体参见一下代码:复制代码 代码如下:/** * 使用矩阵控制图片移动、缩放、旋转 &nbs...
本文主要讲解利用android中matrix控制图形的旋转缩放移动,具体参见一下代码:
/**
* 使用矩阵控制图片移动、缩放、旋转
*/
public class commonimgeffectview extends view {
private context context ;
private bitmap mainbmp , controlbmp ;
private int mainbmpwidth , mainbmpheight , controlbmpwidth , controlbmpheight ;
private matrix matrix ;
private float [] srcps , dstps ;
private rectf srcrect , dstrect ;
private paint paint ,paintrect , paintframe;
private float deltax = 0, deltay = 0; //位移值
private float scalevalue = 1; //缩放值
private point lastpoint ;
private point prepivot , lastpivot;
private float predegree , lastdegree ;
private short currentselectedpointindex; //当前操作点击点
private point symmetricpoint = new point(); //当前操作点对称点
/**
* 图片操作类型
*/
public static final int oper_default = -1; //默认
public static final int oper_translate = 0; //移动
public static final int oper_scale = 1; //缩放
public static final int oper_rotate = 2; //旋转
public static final int oper_selected = 3; //选择
public int lastoper = oper_default;
/* 图片控制点
* 0---1---2
* | |
* 7 8 3
* | |
* 6---5---4
*/
public static final int ctr_none = -1;
public static final int ctr_left_top = 0;
public static final int ctr_mid_top = 1;
public static final int ctr_right_top = 2;
public static final int ctr_right_mid = 3;
public static final int ctr_right_bottom = 4;
public static final int ctr_mid_bottom = 5;
public static final int ctr_left_bottom = 6;
public static final int ctr_left_mid = 7;
public static final int ctr_mid_mid = 8;
public int current_ctr = ctr_none;
public commonimgeffectview(context context){
super(context);
this.context = context ;
}
public commonimgeffectview(context context, attributeset attrs) {
super(context, attrs);
this.context = context ;
initdata();
}
/**
* 初始化数据
* @author 张进
*/
private void initdata(){
mainbmp = bitmapfactory.decoderesource(this.context.getresources(), r.drawable.flower);
controlbmp = bitmapfactory.decoderesource(this.context.getresources(), r.drawable.control);
mainbmpwidth = mainbmp.getwidth();
mainbmpheight = mainbmp.getheight();
controlbmpwidth = controlbmp.getwidth();
controlbmpheight = controlbmp.getheight();
srcps = new float[]{
0,0,
mainbmpwidth/2,0,
mainbmpwidth,0,
mainbmpwidth,mainbmpheight/2,
mainbmpwidth,mainbmpheight,
mainbmpwidth/2,mainbmpheight,
0,mainbmpheight,
0,mainbmpheight/2,
mainbmpwidth/2,mainbmpheight/2
};
dstps = srcps.clone();
srcrect = new rectf(0, 0, mainbmpwidth, mainbmpheight);
dstrect = new rectf();
matrix = new matrix();
prepivot = new point(mainbmpwidth/2, mainbmpheight/2);
lastpivot = new point(mainbmpwidth/2, mainbmpheight/2);
lastpoint = new point(0,0);
paint = new paint();
paintrect = new paint();
paintrect.setcolor(color.red);
paintrect.setalpha(100);
paintrect.setantialias(true);
paintframe = new paint();
paintframe.setcolor(color.green);
paintframe.setantialias(true);
setmatrix(oper_default);
}
/**
* 矩阵变换,达到图形平移的目的
* @author 张进
*/
private void setmatrix(int operationtype){
switch (operationtype) {
case oper_translate:
matrix.posttranslate(deltax , deltay);
break;
case oper_scale:
matrix.postscale(scalevalue, scalevalue, symmetricpoint.x, symmetricpoint.y);
break;
case oper_rotate:
matrix.postrotate(predegree - lastdegree, dstps[ctr_mid_mid * 2], dstps[ctr_mid_mid * 2 + 1]);
break;
}
matrix.mappoints(dstps, srcps);
matrix.maprect(dstrect, srcrect);
}
private boolean isonpic(int x , int y){
if(dstrect.contains(x, y)){
return true;
}else
return false;
}
private int getoperationtype(motionevent event){
int evx = (int)event.getx();
int evy = (int)event.gety();
int curoper = lastoper;
switch(event.getaction()) {
case motionevent.action_down:
current_ctr = isoncp(evx, evy);
log.i("img", "current_ctr is "+current_ctr);
if(current_ctr != ctr_none || isonpic(evx, evy)){
curoper = oper_selected;
}
break;
case motionevent.action_move:
if(current_ctr > ctr_none && current_ctr < ctr_mid_mid ){
curoper = oper_scale;
}else if(current_ctr == ctr_mid_mid ){
curoper = oper_rotate;
}else if(lastoper == oper_selected){
curoper = oper_translate;
}
break;
case motionevent.action_up:
curoper = oper_selected;
break;
default:
break;
}
log.d("img", "curoper is "+curoper);
return curoper;
}
/**
* 判断点所在的控制点
* @param evx
* @param evy
* @return
*/
private int isoncp(int evx, int evy) {
rect rect = new rect(evx-controlbmpwidth/2,evy-controlbmpheight/2,evx+controlbmpwidth/2,evy+controlbmpheight/2);
int res = 0 ;
for (int i = 0; i < dstps.length; i+=2) {
if(rect.contains((int)dstps[i], (int)dstps[i+1])){
return res ;
}
++res ;
}
return ctr_none;
}
@override
public boolean dispatchtouchevent(motionevent event) {
int evx = (int)event.getx();
int evy = (int)event.gety();
int opertype = oper_default;
opertype = getoperationtype(event);
switch (opertype) {
case oper_translate:
translate(evx, evy);
break;
case oper_scale:
scale(event);
break;
case oper_rotate:
rotate(event);
break;
}
lastpoint.x = evx;
lastpoint.y = evy;
lastoper = opertype;
invalidate();//重绘
return true;
}
/**
* 移动
* @param evx
* @param evy
* @author zhang_jin1
*/
private void translate(int evx , int evy){
prepivot.x += evx - lastpoint.x;
prepivot.y += evy -lastpoint.y;
deltax = prepivot.x - lastpivot.x;
deltay = prepivot.y - lastpivot.y;
lastpivot.x = prepivot.x;
lastpivot.y = prepivot.y;
setmatrix(oper_translate); //设置矩阵
}
/**
* 缩放
* 0---1---2
* | |
* 7 8 3
* | |
* 6---5---4
* @param evx
* @param evy
*/
private void scale(motionevent event) {
int pointindex = current_ctr*2 ;
float px = dstps[pointindex];
float py = dstps[pointindex+1];
float evx = event.getx();
float evy = event.gety();
float oppositex = 0 ;
float oppositey = 0 ;
if(current_ctr<4 && current_ctr >= 0){
oppositex = dstps[pointindex+8];
oppositey = dstps[pointindex+9];
}else if(current_ctr >= 4){
oppositex = dstps[pointindex-8];
oppositey = dstps[pointindex-7];
}
float temp1 = getdistanceoftwopoints(px,py,oppositex,oppositey);
float temp2 = getdistanceoftwopoints(evx,evy,oppositex,oppositey);
this.scalevalue = temp2 / temp1 ;
symmetricpoint.x = (int) oppositex;
symmetricpoint.y = (int)oppositey;
log.i("img", "scalevalue is "+scalevalue);
setmatrix(oper_scale);
}
/**
* 旋转图片
* 0---1---2
* | |
* 7 8 3
* | |
* 6---5---4
* @param evx
* @param evy
*/
private void rotate(motionevent event) {
if(event.getpointercount() == 2){
predegree = computedegree(new point((int)event.getx(0), (int)event.gety(0)), new point((int)event.getx(1), (int)event.gety(1)));
}else{
predegree = computedegree(new point((int)event.getx(), (int)event.gety()), new point((int)dstps[16], (int)dstps[17]));
}
setmatrix(oper_rotate);
lastdegree = predegree;
}
/**
* 计算两点与垂直方向夹角
* @param p1
* @param p2
* @return
*/
public float computedegree(point p1, point p2){
float tran_x = p1.x - p2.x;
float tran_y = p1.y - p2.y;
float degree = 0.0f;
float angle = (float)(math.asin(tran_x/math.sqrt(tran_x*tran_x + tran_y* tran_y))*180/math.pi);
if(!float.isnan(angle)){
if(tran_x >= 0 && tran_y <= 0){//第一象限
degree = angle;
}else if(tran_x <= 0 && tran_y <= 0){//第二象限
degree = angle;
}else if(tran_x <= 0 && tran_y >= 0){//第三象限
degree = -180 - angle;
}else if(tran_x >= 0 && tran_y >= 0){//第四象限
degree = 180 - angle;
}
}
return degree;
}
/**
* 计算两个点之间的距离
* @param p1
* @param p2
* @return
*/
private float getdistanceoftwopoints(point p1, point p2){
return (float)(math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)));
}
private float getdistanceoftwopoints(float x1,float y1,float x2,float y2){
return (float)(math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
}
@override
public void ondraw(canvas canvas){
drawbackground(canvas);//绘制背景,以便测试矩形的映射
canvas.drawbitmap(mainbmp, matrix, paint);//绘制主图片
drawframe(canvas);//绘制边框,以便测试点的映射
drawcontrolpoints(canvas);//绘制控制点图片
}
private void drawbackground(canvas canvas){
canvas.drawrect(dstrect, paintrect);
}
private void drawframe(canvas canvas){
canvas.drawline(dstps[0], dstps[1], dstps[4], dstps[5], paintframe);
canvas.drawline(dstps[4], dstps[5], dstps[8], dstps[9], paintframe);
canvas.drawline(dstps[8], dstps[9], dstps[12], dstps[13], paintframe);
canvas.drawline(dstps[0], dstps[1], dstps[12], dstps[13], paintframe);
canvas.drawpoint(dstps[16], dstps[17], paintframe);
}
private void drawcontrolpoints(canvas canvas){
for (int i = 0; i < dstps.length; i+=2) {
canvas.drawbitmap(controlbmp, dstps[i]-controlbmpwidth/2, dstps[i+1]-controlbmpheight/2, paint);
}
}
}
demo效果:
复制代码 代码如下:
/**
* 使用矩阵控制图片移动、缩放、旋转
*/
public class commonimgeffectview extends view {
private context context ;
private bitmap mainbmp , controlbmp ;
private int mainbmpwidth , mainbmpheight , controlbmpwidth , controlbmpheight ;
private matrix matrix ;
private float [] srcps , dstps ;
private rectf srcrect , dstrect ;
private paint paint ,paintrect , paintframe;
private float deltax = 0, deltay = 0; //位移值
private float scalevalue = 1; //缩放值
private point lastpoint ;
private point prepivot , lastpivot;
private float predegree , lastdegree ;
private short currentselectedpointindex; //当前操作点击点
private point symmetricpoint = new point(); //当前操作点对称点
/**
* 图片操作类型
*/
public static final int oper_default = -1; //默认
public static final int oper_translate = 0; //移动
public static final int oper_scale = 1; //缩放
public static final int oper_rotate = 2; //旋转
public static final int oper_selected = 3; //选择
public int lastoper = oper_default;
/* 图片控制点
* 0---1---2
* | |
* 7 8 3
* | |
* 6---5---4
*/
public static final int ctr_none = -1;
public static final int ctr_left_top = 0;
public static final int ctr_mid_top = 1;
public static final int ctr_right_top = 2;
public static final int ctr_right_mid = 3;
public static final int ctr_right_bottom = 4;
public static final int ctr_mid_bottom = 5;
public static final int ctr_left_bottom = 6;
public static final int ctr_left_mid = 7;
public static final int ctr_mid_mid = 8;
public int current_ctr = ctr_none;
public commonimgeffectview(context context){
super(context);
this.context = context ;
}
public commonimgeffectview(context context, attributeset attrs) {
super(context, attrs);
this.context = context ;
initdata();
}
/**
* 初始化数据
* @author 张进
*/
private void initdata(){
mainbmp = bitmapfactory.decoderesource(this.context.getresources(), r.drawable.flower);
controlbmp = bitmapfactory.decoderesource(this.context.getresources(), r.drawable.control);
mainbmpwidth = mainbmp.getwidth();
mainbmpheight = mainbmp.getheight();
controlbmpwidth = controlbmp.getwidth();
controlbmpheight = controlbmp.getheight();
srcps = new float[]{
0,0,
mainbmpwidth/2,0,
mainbmpwidth,0,
mainbmpwidth,mainbmpheight/2,
mainbmpwidth,mainbmpheight,
mainbmpwidth/2,mainbmpheight,
0,mainbmpheight,
0,mainbmpheight/2,
mainbmpwidth/2,mainbmpheight/2
};
dstps = srcps.clone();
srcrect = new rectf(0, 0, mainbmpwidth, mainbmpheight);
dstrect = new rectf();
matrix = new matrix();
prepivot = new point(mainbmpwidth/2, mainbmpheight/2);
lastpivot = new point(mainbmpwidth/2, mainbmpheight/2);
lastpoint = new point(0,0);
paint = new paint();
paintrect = new paint();
paintrect.setcolor(color.red);
paintrect.setalpha(100);
paintrect.setantialias(true);
paintframe = new paint();
paintframe.setcolor(color.green);
paintframe.setantialias(true);
setmatrix(oper_default);
}
/**
* 矩阵变换,达到图形平移的目的
* @author 张进
*/
private void setmatrix(int operationtype){
switch (operationtype) {
case oper_translate:
matrix.posttranslate(deltax , deltay);
break;
case oper_scale:
matrix.postscale(scalevalue, scalevalue, symmetricpoint.x, symmetricpoint.y);
break;
case oper_rotate:
matrix.postrotate(predegree - lastdegree, dstps[ctr_mid_mid * 2], dstps[ctr_mid_mid * 2 + 1]);
break;
}
matrix.mappoints(dstps, srcps);
matrix.maprect(dstrect, srcrect);
}
private boolean isonpic(int x , int y){
if(dstrect.contains(x, y)){
return true;
}else
return false;
}
private int getoperationtype(motionevent event){
int evx = (int)event.getx();
int evy = (int)event.gety();
int curoper = lastoper;
switch(event.getaction()) {
case motionevent.action_down:
current_ctr = isoncp(evx, evy);
log.i("img", "current_ctr is "+current_ctr);
if(current_ctr != ctr_none || isonpic(evx, evy)){
curoper = oper_selected;
}
break;
case motionevent.action_move:
if(current_ctr > ctr_none && current_ctr < ctr_mid_mid ){
curoper = oper_scale;
}else if(current_ctr == ctr_mid_mid ){
curoper = oper_rotate;
}else if(lastoper == oper_selected){
curoper = oper_translate;
}
break;
case motionevent.action_up:
curoper = oper_selected;
break;
default:
break;
}
log.d("img", "curoper is "+curoper);
return curoper;
}
/**
* 判断点所在的控制点
* @param evx
* @param evy
* @return
*/
private int isoncp(int evx, int evy) {
rect rect = new rect(evx-controlbmpwidth/2,evy-controlbmpheight/2,evx+controlbmpwidth/2,evy+controlbmpheight/2);
int res = 0 ;
for (int i = 0; i < dstps.length; i+=2) {
if(rect.contains((int)dstps[i], (int)dstps[i+1])){
return res ;
}
++res ;
}
return ctr_none;
}
@override
public boolean dispatchtouchevent(motionevent event) {
int evx = (int)event.getx();
int evy = (int)event.gety();
int opertype = oper_default;
opertype = getoperationtype(event);
switch (opertype) {
case oper_translate:
translate(evx, evy);
break;
case oper_scale:
scale(event);
break;
case oper_rotate:
rotate(event);
break;
}
lastpoint.x = evx;
lastpoint.y = evy;
lastoper = opertype;
invalidate();//重绘
return true;
}
/**
* 移动
* @param evx
* @param evy
* @author zhang_jin1
*/
private void translate(int evx , int evy){
prepivot.x += evx - lastpoint.x;
prepivot.y += evy -lastpoint.y;
deltax = prepivot.x - lastpivot.x;
deltay = prepivot.y - lastpivot.y;
lastpivot.x = prepivot.x;
lastpivot.y = prepivot.y;
setmatrix(oper_translate); //设置矩阵
}
/**
* 缩放
* 0---1---2
* | |
* 7 8 3
* | |
* 6---5---4
* @param evx
* @param evy
*/
private void scale(motionevent event) {
int pointindex = current_ctr*2 ;
float px = dstps[pointindex];
float py = dstps[pointindex+1];
float evx = event.getx();
float evy = event.gety();
float oppositex = 0 ;
float oppositey = 0 ;
if(current_ctr<4 && current_ctr >= 0){
oppositex = dstps[pointindex+8];
oppositey = dstps[pointindex+9];
}else if(current_ctr >= 4){
oppositex = dstps[pointindex-8];
oppositey = dstps[pointindex-7];
}
float temp1 = getdistanceoftwopoints(px,py,oppositex,oppositey);
float temp2 = getdistanceoftwopoints(evx,evy,oppositex,oppositey);
this.scalevalue = temp2 / temp1 ;
symmetricpoint.x = (int) oppositex;
symmetricpoint.y = (int)oppositey;
log.i("img", "scalevalue is "+scalevalue);
setmatrix(oper_scale);
}
/**
* 旋转图片
* 0---1---2
* | |
* 7 8 3
* | |
* 6---5---4
* @param evx
* @param evy
*/
private void rotate(motionevent event) {
if(event.getpointercount() == 2){
predegree = computedegree(new point((int)event.getx(0), (int)event.gety(0)), new point((int)event.getx(1), (int)event.gety(1)));
}else{
predegree = computedegree(new point((int)event.getx(), (int)event.gety()), new point((int)dstps[16], (int)dstps[17]));
}
setmatrix(oper_rotate);
lastdegree = predegree;
}
/**
* 计算两点与垂直方向夹角
* @param p1
* @param p2
* @return
*/
public float computedegree(point p1, point p2){
float tran_x = p1.x - p2.x;
float tran_y = p1.y - p2.y;
float degree = 0.0f;
float angle = (float)(math.asin(tran_x/math.sqrt(tran_x*tran_x + tran_y* tran_y))*180/math.pi);
if(!float.isnan(angle)){
if(tran_x >= 0 && tran_y <= 0){//第一象限
degree = angle;
}else if(tran_x <= 0 && tran_y <= 0){//第二象限
degree = angle;
}else if(tran_x <= 0 && tran_y >= 0){//第三象限
degree = -180 - angle;
}else if(tran_x >= 0 && tran_y >= 0){//第四象限
degree = 180 - angle;
}
}
return degree;
}
/**
* 计算两个点之间的距离
* @param p1
* @param p2
* @return
*/
private float getdistanceoftwopoints(point p1, point p2){
return (float)(math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)));
}
private float getdistanceoftwopoints(float x1,float y1,float x2,float y2){
return (float)(math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)));
}
@override
public void ondraw(canvas canvas){
drawbackground(canvas);//绘制背景,以便测试矩形的映射
canvas.drawbitmap(mainbmp, matrix, paint);//绘制主图片
drawframe(canvas);//绘制边框,以便测试点的映射
drawcontrolpoints(canvas);//绘制控制点图片
}
private void drawbackground(canvas canvas){
canvas.drawrect(dstrect, paintrect);
}
private void drawframe(canvas canvas){
canvas.drawline(dstps[0], dstps[1], dstps[4], dstps[5], paintframe);
canvas.drawline(dstps[4], dstps[5], dstps[8], dstps[9], paintframe);
canvas.drawline(dstps[8], dstps[9], dstps[12], dstps[13], paintframe);
canvas.drawline(dstps[0], dstps[1], dstps[12], dstps[13], paintframe);
canvas.drawpoint(dstps[16], dstps[17], paintframe);
}
private void drawcontrolpoints(canvas canvas){
for (int i = 0; i < dstps.length; i+=2) {
canvas.drawbitmap(controlbmp, dstps[i]-controlbmpwidth/2, dstps[i+1]-controlbmpheight/2, paint);
}
}
}
demo效果: