Bagaimana cara menggambar segitiga penuh di kanvas android?


88

Jadi saya menggambar segitiga ini di peta android menggunakan kode di bawah ini dalam metode menggambar saya:

paint.setARGB(255, 153, 29, 29);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);

Path path = new Path();
path.moveTo(point1_returned.x, point1_returned.y);
path.lineTo(point2_returned.x, point2_returned.y);
path.moveTo(point2_returned.x, point2_returned.y);
path.lineTo(point3_returned.x, point3_returned.y);
path.moveTo(point3_returned.x, point3_returned.y);
path.lineTo(point1_returned.x, point1_returned.y);
path.close();

canvas.drawPath(path, paint);

PointX_returned adalah koordinat yang saya dapatkan dari ladang. Mereka pada dasarnya adalah lintang dan bujur. Hasilnya adalah segitiga yang bagus tetapi bagian dalamnya kosong dan oleh karena itu saya dapat melihat peta. Apakah ada cara untuk mengisinya?


Seperti yang saya posting dalam jawaban saya, jangan moveTo () setelah setiap lineTo (), hanya itu yang ada.
oli.G

Saya tahu ini adalah pertanyaan lama yang sudah memiliki jawaban yang diterima (salah), dan Anda juga memposting solusi akhir Anda yang berfungsi ... tetapi Anda tidak menyatakan mengapa ini berhasil, dan saya harap komentar saya dapat menghemat waktu saya ' Kami baru saja menghabiskan waktu ini :)
oli.G

Jawaban:


42

Anda mungkin perlu melakukan sesuatu seperti:

Paint red = new Paint();

red.setColor(android.graphics.Color.RED);
red.setStyle(Paint.Style.FILL);

Dan gunakan warna ini untuk jalur Anda, bukan ARGB Anda. Pastikan titik terakhir dari jalur Anda berakhir pada yang pertama, itu juga masuk akal.

Beri tahu saya jika berhasil!


Sayangnya ini tidak membantu
oli.G

@Nicolas Apa yang harus digunakan selain ARGB, jika kita harus menyesuaikan warna dengan nilai RGB daripada menggunakan nilai yang telah ditentukan sebelumnya?
pallav bohara

75

Ok saya sudah melakukannya. Saya membagikan kode ini jika ada orang lain yang membutuhkannya:

super.draw(canvas, mapView, true);

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

paint.setStrokeWidth(2);
paint.setColor(android.graphics.Color.RED);     
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);

Point point1_draw = new Point();        
Point point2_draw = new Point();    
Point point3_draw = new Point();

mapView.getProjection().toPixels(point1, point1_draw);
mapView.getProjection().toPixels(point2, point2_draw);
mapView.getProjection().toPixels(point3, point3_draw);

Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(point1_draw.x,point1_draw.y);
path.lineTo(point2_draw.x,point2_draw.y);
path.lineTo(point3_draw.x,point3_draw.y);
path.lineTo(point1_draw.x,point1_draw.y);
path.close();

canvas.drawPath(path, paint);

//canvas.drawLine(point1_draw.x,point1_draw.y,point2_draw.x,point2_draw.y, paint);

return true;

Terima kasih atas petunjuknya, Nicolas!


7
Saya cukup yakin Anda tidak membutuhkan yang terakhir lineTo(). close()melakukannya secara otomatis.
Timmmm

@Timmmm saya sudah uji, Anda benar, tidak perlu baris terakhirTo (). Terima kasih.
banxi1988

Terima kasih banyak. Saya tidak tahu mengapa saya memiliki begitu banyak masalah dalam menggambar segitiga, tetapi saya telah menghabiskan 20 menit terakhir dengan berbagai bug pada masalah kecil ini.
Achal Dave

1
Berikut metode sederhana untuk copy-paste (berdasarkan kode @ Pavel): gist.github.com/ZirconCode/59cae1e2615279eafb29
ZirconCode

1
jika Anda berubah pathke variabel instan, ingatlah untuk memanggil path.reset()setelahnya canvas.drawPath().
Sira Lam

11

Anda juga bisa menggunakan vertice:

private static final int verticesColors[] = {
    Color.LTGRAY, Color.LTGRAY, Color.LTGRAY, 0xFF000000, 0xFF000000, 0xFF000000
};
float verts[] = {
    point1.x, point1.y, point2.x, point2.y, point3.x, point3.y
};
canvas.drawVertices(Canvas.VertexMode.TRIANGLES, verts.length, verts, 0, null, 0, verticesColors,   0, null, 0, 0, new Paint());

2
Saya tidak berpikir solusi ini menangani bentuk yang diisi. (tidak dapat menguji, saya tidak memiliki IDE saya saat ini)
Nicolas C.

3
Ini sepertinya solusi yang lebih berkinerja, tetapi sayangnya metode ini tidak didukung pada tampilan yang dipercepat perangkat keras. Anda dapat menonaktifkan akselerasi perangkat keras, tetapi kemudian Anda kehilangan perolehan kinerjanya: developer.android.com/guide/topics/graphics/hardware-accel.html
SurlyDre

8

masukkan deskripsi gambar di sini

fungsi ini menunjukkan cara membuat segitiga dari bitmap. Artinya, buat gambar yang dipotong berbentuk segitiga. Coba kode di bawah ini atau unduh contoh demo

 public static Bitmap getTriangleBitmap(Bitmap bitmap, int radius) {
        Bitmap finalBitmap;
        if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
            finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                    false);
        else
            finalBitmap = bitmap;
        Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                finalBitmap.getHeight());

        Point point1_draw = new Point(75, 0);
        Point point2_draw = new Point(0, 180);
        Point point3_draw = new Point(180, 180);

        Path path = new Path();
        path.moveTo(point1_draw.x, point1_draw.y);
        path.lineTo(point2_draw.x, point2_draw.y);
        path.lineTo(point3_draw.x, point3_draw.y);
        path.lineTo(point1_draw.x, point1_draw.y);
        path.close();
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#BAB399"));
        canvas.drawPath(path, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(finalBitmap, rect, rect, paint);

        return output;
    }

Fungsi di atas mengembalikan gambar segitiga yang digambar di atas kanvas. Baca lebih banyak


7

Menggunakan jawaban @ Pavel sebagai panduan, berikut adalah metode pembantu jika Anda tidak memiliki poin tetapi memiliki awal x, y, serta tinggi dan lebar. Juga dapat menggambar terbalik / terbalik - yang berguna bagi saya karena digunakan sebagai ujung diagram batang vertikal.

 private void drawTriangle(int x, int y, int width, int height, boolean inverted, Paint paint, Canvas canvas){

        Point p1 = new Point(x,y);
        int pointX = x + width/2;
        int pointY = inverted?  y + height : y - height;

        Point p2 = new Point(pointX,pointY);
        Point p3 = new Point(x+width,y);


        Path path = new Path();
        path.setFillType(Path.FillType.EVEN_ODD);
        path.moveTo(p1.x,p1.y);
        path.lineTo(p2.x,p2.y);
        path.lineTo(p3.x,p3.y);
        path.close();

        canvas.drawPath(path, paint);
    }

4
private void drawArrows(Point[] point, Canvas canvas, Paint paint) {

    float [] points  = new float[8];             
    points[0] = point[0].x;      
    points[1] = point[0].y;      
    points[2] = point[1].x;      
    points[3] = point[1].y;         
    points[4] = point[2].x;      
    points[5] = point[2].y;              
    points[6] = point[0].x;      
    points[7] = point[0].y;

    canvas.drawVertices(VertexMode.TRIANGLES, 8, points, 0, null, 0, null, 0, null, 0, 0, paint);
    Path path = new Path();
    path.moveTo(point[0].x , point[0].y);
    path.lineTo(point[1].x,point[1].y);
    path.lineTo(point[2].x,point[2].y);
    canvas.drawPath(path,paint);

}

Ini berhasil! Jangan lupa gunakan paint.setAntiAlias ​​(true) untuk mendapatkan segitiga yang mulus.
Boldijar Paul

2
Untuk apa panggilan drawVertices?
PsiX

3

Anda perlu menghapus path.moveTo setelah inisial pertama.

Path path = new Path();
path.moveTo(point1_returned.x, point1_returned.y);
path.lineTo(point2_returned.x, point2_returned.y);
path.lineTo(point3_returned.x, point3_returned.y);
path.lineTo(point1_returned.x, point1_returned.y);
path.close();

Saya tidak memiliki 3 titik tetapi hanya memiliki satu titik x nad y bagaimana saya bisa menggambar segitiga dari titik itu.
Pranav

2

Jangan moveTo()setelah masing-masinglineTo()

Dengan kata lain, hapus semua moveTo()kecuali yang pertama.

Serius, jika saya hanya menyalin-tempel kode OP dan menghapus moveTo()panggilan yang tidak perlu , itu berhasil.

Tidak ada lagi yang perlu dilakukan.


EDIT: Saya tahu OP sudah memposting "solusi kerja terakhir", tetapi dia tidak menyatakan mengapa itu berhasil. Alasan sebenarnya cukup mengejutkan saya, jadi saya merasa perlu menambahkan jawaban.


Anda harus menambahkan komentar untuk ini. Ini bukanlah jawaban.
Angad Singh
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.