Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy canvas content to another canvas similar to amaziograph app of iphone

Tags:

android

canvas

I am working on an application similar to Amaziograph of iPhone also known as kaleidoscope or mandala.

Till now I have tried and have made one particular layout of that appCircular canvas

I have extended the canvas and have made a custom canvas, where I have divided canvas in 9 parts similar to image and in draw method I have rotated the canvas and copied its content in for loop. Here is my canvas class code for above circular division shape

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.madala.mandaladrawing.R;
import com.madala.mandaladrawing.model.DrawingEvent;
import com.madala.mandaladrawing.utils.Common;


public class CanvasView extends View {
private final Context context;
private Bitmap bitmap;
private Canvas bitmapCanvas;
private Paint bitmapPaint;
private Path path = new Path();
private Paint brushPaint;

private int numberOfMirror = 5;
private int cx, cy;

public CanvasView(Context context) {
    super(context);
    this.context = context;
    init();
}

public CanvasView(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    init();
}

public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    this.context = context;
    init();
}

private void init() {
    brushPaint = createPaint();
    brushPaint.setColor(0xffffffff);
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
    canvas.drawPath(path, brushPaint);

    for (int i = 1; i < numberOfMirror; i++) {
        canvas.rotate(360f / numberOfMirror, cx, cy);
        canvas.drawPath(path, brushPaint);
    }
}

public void clearCanvas(){
    bitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    invalidate();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    setLayerType(View.LAYER_TYPE_HARDWARE, null);
    bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    bitmapCanvas = new Canvas(bitmap);
    bitmapPaint = new Paint(Paint.DITHER_FLAG);
    cx = w / 2;
    cy = h / 2;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            path.moveTo(x, y);
            break;
        case MotionEvent.ACTION_MOVE:
            path.lineTo(x, y);
            break;
        case MotionEvent.ACTION_UP:
            path.lineTo(x, y);
            drawToCanvas(path, brushPaint);
            path.reset();
            break;
        default:
            return false;
    }

    invalidate();
    return true;
}


private void drawToCanvas(Path path, Paint brushPaint) {
    bitmapCanvas.drawPath(path, brushPaint);
    for (int i = 1; i < numberOfMirror; i++) {
        bitmapCanvas.rotate(360f / numberOfMirror, cx, cy);
        bitmapCanvas.drawPath(path, brushPaint);
    }
}

public int getCurrentBrushColor() {
    return brushPaint.getColor();
}

public void setCurrentBrushColor(int color) {
    brushPaint.setColor(color);
}

private Paint createPaint() {
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
    p.setStrokeWidth(8f);
    p.setStyle(Paint.Style.STROKE);
    p.setStrokeJoin(Paint.Join.ROUND);
    p.setStrokeCap(Paint.Cap.ROUND);
    return p;
}
}

I am not able to achieve the functionality for below figureWithout Drawing

I want to draw in one box and it should be copied in the other boxes. How could this be achieved a small guide will also be helpful?

With Drawing Drawing continues from one box to another

like image 693
Sanjay Hirani Avatar asked Nov 29 '16 06:11

Sanjay Hirani


2 Answers

Maybe you can save traces into array, and paste it to other drawing views

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            //save initial x,y into array or send it to other canvas
            /*public general variable*/
            String Drawing +="[[x,y]";
            path.moveTo(x, y);
            break;
        case MotionEvent.ACTION_MOVE:
            //save middle x,y into array or send it to other canvas
            String Drawing +=",[x,y]";
            path.lineTo(x, y);
            break;
        case MotionEvent.ACTION_UP:
            //save last point into array or send it to other canvas 
            String Drawing +=",[x,y]]";
            path.lineTo(x, y);
            drawToCanvas(path, brushPaint);
            path.reset();
            break;
        default:
            return false;
    }

    invalidate();
    return true;
}

the string resultant should be all user traces

[[x,y],[x,y],[x,y],[x,y],[x,y]],  trace 1
[[x,y],[x,y],[x,y],[x,y],[x,y]],  trace 2
[[x,y],[x,y],[x,y],[x,y],[x,y]],  trace 3
etc..

trace1 + trace2 +trace 3 = thing drawed by user. when you want or maybe in real time, you can send the points drawed on this view to other view... or when users end writing send the string and extract the points...

Well it's just an idea, Hope i helped ;)

like image 146
Setar Avatar answered Nov 06 '22 23:11

Setar


<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- this has changed from first answer -->
    <dimen name="translation_size">30dp</dimen>
</resources>

...

    int size = getResources().getDimensionPixelSize(R.dimen.translation_size);

...

    private void drawToCanvas(Path path, Paint brushPaint) {
        bitmapCanvas.drawPath(path, brushPaint);  // just render normally
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawPath(path, brushPaint);

        int xMax = getWidth() / size;
        int yMax = getHeight() / size;
        int xMin = -xMax;
        int yMin = -yMax;
        for (int x = xMin; x <= xMax; x++) {
            for (int y = yMin; y <= yMax; y++) {
                if ((Math.abs(x % 6) == 0 && Math.abs(y % 4) == 0) || 
                    (Math.abs(x % 6) == 3 && Math.abs(y % 4) == 2)) {
                    int xs = x * size;
                    int ys = y * size;
                    canvas.translate(xs, ys);
                    canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
                    canvas.translate(-xs, -ys);
                }
            }
        }
    }

You don't have to use resources like I did, but if you hard-code a size into your app, make sure you multiply by the screen density to get the correct pixel offsets.

like image 1
kris larson Avatar answered Nov 07 '22 00:11

kris larson