【发布时间】:2014-06-27 14:49:24
【问题描述】:
我正在开发一个绘图应用程序,用户可以在其中创建一个矩形、一排孔、一个孔网格和多边形。现在,我拥有移动这些对象的功能,方法是确定触摸点是否在对象的边界内,在 TouchMove 操作期间更新对象坐标,然后使用更新的坐标重新绘制对象(连同绘制的所有其他内容)。 我的下一步是实施轮换。到目前为止,我能够获得一个旋转角度,在绘制旋转对象时使用它来旋转画布,然后恢复画布以便绘制其他对象没有角度。这完美地工作。当我尝试移动/旋转旋转的对象时,问题就来了。我存储对象旋转,但我不更新它存储的坐标;因此,当我尝试确定用户是否触摸了旋转的对象时,它与用户在屏幕上看到的不匹配。 我需要的是能够修改对象坐标或触摸坐标以反映旋转。有没有办法做到这一点?我是不是搞错了?
这是我的代码的一些 sn-ps:
这会确定是否触摸了一个圆圈网格:
//retrieve touch coordinates. Adjust for matrix transformations
float currX=(event.getX()-matrixValues[2])/matrixValues[0];
float currY=(event.getY()-matrixValues[5])/matrixValues[4];
//... skip other code for snippet
else if(drawObject.getDrawAction()=="array")
{
ArrayList <DrawAction> redrawArray=drawObject.getDrawArray();
if(drawMode=="remove")
{
//determine which hole in grid was touched. "Remove" it
for(int y=0; y<redrawArray.size();y++)
{
DrawAction arrayAction=redrawArray.get(y);
if(currX>(arrayAction.getDrawX()-arrayAction.getDrawRadius()) && currX<(arrayAction.getDrawX()+arrayAction.getDrawRadius()) && currY<(arrayAction.getDrawY()+arrayAction.getDrawRadius()) && currY>(arrayAction.getDrawY()-arrayAction.getDrawRadius()))
{
arrayAction.setRemoved(true);
//add undo object for this action
DrawAction undoRemove= new DrawAction("remove", arrayAction);
undoList.add(undoRemove);
//redraw objects with updated status
redrawObjects(false);
break outerloop;
}
}
}
else
{
//determine all coordinates within the grid. If we are within the grid, then we want to move the whole grid
float holeRadius=redrawArray.get(0).getDrawRadius();
float lowestX=redrawArray.get(0).getDrawX()-holeRadius;
float lowestY=redrawArray.get(0).getDrawY()-holeRadius;
float highestX=redrawArray.get(redrawArray.size()-1).getDrawX()+holeRadius;
float highestY=redrawArray.get(redrawArray.size()-1).getDrawY()+holeRadius;
if(currX>lowestX && currX<highestX && currY>lowestY && currY<highestY)
{
touchObject=drawObject;
//store coordinates for new coordinate calculations
touchedX=currX;
touchedY=currY;
break outerloop;
}
}
}
这个 sn-p 是我确定角度的方式:
touchObject.setRotationAngle((float) getDegreesFromTouchEvent(currX, currY));
touchObject.setRotated(true);
这是返回角度的函数:
//determine rotation from touch event and screen dimensions
private double getDegreesFromTouchEvent(float x, float y){
double delta_x = x - (screenWidth) /2;
double delta_y = (screenHeight) /2 - y;
double radians = Math.atan2(delta_y, delta_x);
return (-1)*Math.toDegrees(radians);
}
这是我在移动/旋转后重绘所有内容的地方:
//redraw everything
for(int x=0; x<undoList.size();x++)
{
//retrieve next object to draw
DrawAction drawObject=undoList.get(x);
//retrieve object's brush width/paint color
this.setBrushSize(drawObject.getBrushWidth());
drawPaint.setColor(drawObject.getPaintColor());
//save state of canvas. This is so we can rotate it, draw, and then rotate back to its original state
drawCanvas.save();
//if this object has been rotated, then we need to rotate the canvas before drawing it
if(drawObject.isRotated())
{
drawCanvas.rotate(drawObject.getRotationAngle(),drawObject.getCenterX(),drawObject.getCenterY());
}
if(drawObject.getDrawAction()=="circle" && !drawObject.isRemoved())
{
drawCanvas.drawCircle(drawObject.getDrawX(), drawObject.getDrawY(), drawObject.getDrawRadius(),drawPaint);
}
if(drawObject.getDrawAction()=="rectangle")
{
if(!drawObject.isRemoved())
{
drawCanvas.drawRect(drawObject.getDrawLeft(), drawObject.getDrawTop(), drawObject.getDrawRight(), drawObject.getDrawBottom(),drawObject.getDrawPaint());
drawCanvas.drawCircle(drawObject.getCenterX(), drawObject.getCenterY(), 2, drawObject.getDrawPaint());
}
}
if(drawObject.getDrawAction()=="text" || drawObject.getDrawAction()=="delay")
{
drawCanvas.drawText(drawObject.getDrawtext(), drawObject.getDrawX(), drawObject.getDrawY(), drawObject.getDrawPaint());
}
if(drawObject.getDrawAction()=="array")
{
ArrayList <DrawAction> redrawArray=drawObject.getDrawArray();
for(int y=0; y<redrawArray.size();y++)
{
DrawAction arrayAction=redrawArray.get(y);
if(!arrayAction.isRemoved())
{
drawCanvas.drawCircle(arrayAction.getDrawX(), arrayAction.getDrawY(), arrayAction.getDrawRadius(),drawPaint);
}
}
}
if(drawObject.getDrawAction()=="path")
{
drawCanvas.drawPath(drawObject.getDrawPath(), drawPaint);
}
//restore canvas to original state
drawCanvas.restore();
}
【问题讨论】:
-
@pskink 感谢您的回复,但这需要我重新开始。一切都绘制在一个位图上,该位图绘制在 SurfaceView 画布上。这样做是为了让用户可以平移/缩放具有预定大小的单个位图。我的用户的绘图空间必须大于屏幕,所以这个功能是必不可少的。我也不确定如何绘制动态大小的矩形和路径。您的示例使用可绘制对象。
-
只需将 canvas.drawBitmap(Bitmap, Matrix, Paint) 替换为画布即可。 concat(Matrix) 并进行绘图...
-
@pskink 这就是我目前在 onDraw 方法中的内容:“canvas.concat(matrix); canvas.drawPath(drawPath, drawPaint); canvas.drawBitmap(canvasBitmap,0,0,canvasPaint); "我的问题是在这些图层位图上绘制圆圈、网格、矩形、箭头和绘画,然后将它们附加到我的主位图,然后能够处理取消绘制并将它们围绕主位图移动。这很容易做到吗?
-
是的,应该不会很难
标签: java android coordinates android-canvas surfaceview