Android 编辑图片 Canvas画图,涂鸦,马赛克等(二)

2019-02-27  本文已影响0人  BigP

需求功能详解

单纯的编辑图片的功能,能够在界面上进行图形的绘制,线条的涂鸦,和画马赛克的绘制,并且有撤销的功能。

画图形

继续上一篇的内容,涂鸦已经完成,接下来我们一起来完成画图形的操作:这里看到我暂时提供了四种图形的绘制:

图形种类
可以看到有矩形椭圆圆形箭头四种图形,除了箭头,其他三种图形都很简单。

实现思路

这里先说除了箭头的三种图形的绘制吧。要想绘制一个图形,只需要明白两个知识点就行了:


下面已绘制矩形为例
首先设置基础画笔:

if (mode == MODE.GRAPH_MODE) {
        mTempPaint = new Paint();
        mTempPaint.setAntiAlias(true);
        mTempPaint.setColor(mPaintColor);
        mTempPaint.setStrokeWidth(mPaintWidth);
        mTempPaint.setStrokeCap(Paint.Cap.ROUND);
        mTempPaint.setStrokeJoin(Paint.Join.ROUND);
}

创建保存图形绘制的队列,同样是为了更好的管理绘制和撤销操作:

private ArrayList<DrawGraphBean> mGraphPath = new ArrayList<>();

这里存储的实例与之前涂鸦功能的略有不同,需要记录按下时的坐标,和不断移动的结束坐标,以及所画图形的种类:

class DrawGraphBean {
    public float startX, startY, endX, endY;
    public GRAPH_TYPE type;
    public Paint paint;

    DrawGraphBean(float startX, float startY, float endx, float endY, GRAPH_TYPE type, Paint paint) {
        this.startX = startX;
        this.startY = startY;
        this.endX = endx;
        this.endY = endY;
        this.type = type;
        this.paint = paint;
    }
}

给图形种类给出枚举(不进行设置,默认是矩形):

public enum GRAPH_TYPE {
    RECT, CIRCLE, OVAL, ARROW
}

明白了原理和思路,真正画起来,就简单多了,同样在Action_Down中记下起始点,画笔,然后添加到队列中:

if (mMode == MODE.GRAPH_MODE) {
    mStartX = event.getX();
    mStartY = event.getY();
    setModePaint(mMode);

    // 添加到队列中
    DrawGraphBean graphBean = new DrawGraphBean(mStartX, mStartY, mStartX, mStartY, mCurrentGraphType, mTempPaint);

    mPaths.add(mMode);
    mGraphPath.add(graphBean);
}

然后在Action_Move中,取出队列的最后一条数据,将他的终点坐标进行更新,那么在onDraw()绘制时,就能画出不断跟随手指改变的图形了:

if (mMode == MODE.GRAPH_MODE && mGraphPath.size() > 0) {
    DrawGraphBean tempBean = mGraphPath.get(mGraphPath.size() - 1);
    tempBean.endX = mMoveX;
    tempBean.endY = mMoveY;
}

Action_Up中只需要将新建的画笔置空即可:

mTempPaint = null;

最后,在onDraw()中,将队列中的图形一一绘制出来即可:

/**
 * 画图形
*/
private void drawGraphs(Canvas canvas) {
    if (mGraphPath.size() > 0) {
        for (DrawGraphBean graphBean : mGraphPath) {
            if (graphBean.type == GRAPH_TYPE.RECT) {
                graphBean.paint.setStyle(Paint.Style.STROKE);
                canvas.drawRect(graphBean.startX, graphBean.startY, graphBean.endX, graphBean.endY, graphBean.paint);
            } else if (graphBean.type == GRAPH_TYPE.OVAL) {
                graphBean.paint.setStyle(Paint.Style.STROKE);
                canvas.drawOval(new RectF(graphBean.startX, graphBean.startY, graphBean.endX, graphBean.endY), graphBean.paint);
            } else if (graphBean.type == GRAPH_TYPE.CIRCLE) {
                graphBean.paint.setStyle(Paint.Style.STROKE);
                // 计算半径
                float radius = Math.min(Math.abs(graphBean.startX - graphBean.endX), Math.abs(graphBean.startY - graphBean.endY)) / 2;
                float centerX, centerY;
                centerX = graphBean.endX >= graphBean.startX ? graphBean.startX + radius : graphBean.startX - radius;
                centerY = graphBean.endY >= graphBean.startY ? graphBean.startY + radius : graphBean.startY - radius;
                canvas.drawCircle(centerX, centerY, radius, graphBean.paint);
            } else if (graphBean.type == GRAPH_TYPE.ARROW) {
                graphBean.paint.setStyle(Paint.Style.FILL);
                drawArrow(graphBean.startX, graphBean.startY, graphBean.endX, graphBean.endY, canvas, graphBean.paint);
            }
        }
    }
}

代码粗解:onDraw()中画图形的部分可以看出,根据图形的种类,分别进行了对应的绘制操作:除了箭头的图形,Canvas都已经给我们提供了系统方法,分别是drawRect,drawOvaldrawCircle,只有画圆形,需要简单的计算,其他都是一句话搞定~


/**
 * 画箭头
*/
private void drawArrow(float sx, float sy, float ex, float ey, Canvas canvas, Paint paint) {
    int size = 8;
    int count = 30;
    float x = ex - sx;
    float y = ey - sy;
    double d = x * x + y * y;
    double r = Math.sqrt(d);
    float zx = (float) (ex - (count * x / r));
    float zy = (float) (ey - (count * y / r));
    float xz = zx - sx;
    float yz = zy - sy;
    double zd = xz * xz + yz * yz;
    double zr = Math.sqrt(zd);
    Path triangle = new Path();
    triangle.moveTo(sx, sy);
    triangle.lineTo((float) (zx + size * yz / zr), (float) (zy - size * xz / zr));
    triangle.lineTo((float) (zx + size * 2 * yz / zr), (float) (zy - size * 2 * xz / zr));
    triangle.lineTo(ex, ey);
    triangle.lineTo((float) (zx - size * 2 * yz / zr), (float) (zy + size * 2 * xz / zr));
    triangle.lineTo((float) (zx - size * yz / zr), (float) (zy + size * xz / zr));
    triangle.close();
    canvas.drawPath(triangle, paint);
}

只需要给出起点和终点坐标,还有一点需要注意的是,箭头的画笔需要设置成实心的,那么箭头就绘制完成了~

相关文章

Android 编辑图片 Canvas画图,涂鸦,马赛克等(一)
Android 编辑图片 Canvas画图,涂鸦,马赛克等(三)

上一篇下一篇

猜你喜欢

热点阅读