Penjelasan terperinci tentang Canvas API (Bahagian 1)


Pengenalan kepada bahagian ini:

Kami menghabiskan 13 bahagian untuk menerangkan secara terperinci kebanyakan API kelas Paint yang biasa digunakan dalam Android Mari mulakan dengan bahagian ini. Beberapa API biasa Kanvas (papan lukisan), kami telah menyenaraikannya dalam

  • 8.3.1 Penjelasan terperinci tentang tiga kelas alat lukisan
  • Beberapa kaedah dibahagikan kepada kategori berikut:
    • keluarga kaedah drawXxx : Lukis gambar dalam kawasan lukisan semasa dengan nilai koordinat tertentu, dan lapisan akan ditindih. Iaitu, lapisan yang dicat kemudian akan menutup lapisan yang dicat sebelum ini.
    • keluarga kaedah clipXXX: Pangkas (klip) kawasan lukisan baharu dalam kawasan lukisan semasa, ini Kawasan lukisan ialah kawasan lukisan semasa objek kanvas. Contohnya: clipRect(new Rect()), Kemudian kawasan segi empat tepat ialah kawasan lukisan semasa kanvas
    • keluarga kaedah getXXx : Dapatkan beberapa nilai yang berkaitan dengan Kanvas, seperti lebar, tinggi, ketumpatan skrin, dsb.
    • simpan(), pulihkan(), saveLayer(), restoreToCount(), dsb. Simpan dan memulihkan lapisan Kaedah
    • terjemah(terjemahan), skala(zum), putar(putar), skew(condongkan )

    Sudah tentu terdapat kaedah bertaburan lain Baiklah, bermula dari bahagian ini, saya akan memilih beberapa API yang menarik untuk dipelajari~

    Dan bahagian ini akan memberi anda Apa. ia membawa ialah terjemah (terjemahan), skala (zum), putar (putaran), skew (condongkan) Dan penjelasan terperinci tentang simpan() dan pulihkan()!

    Dokumentasi API rasmi: Kanvas

    Selain itu, kita mesti terlebih dahulu menjelaskan arah paksi X dan paksi Y dalam Kanvas:

    1.png

1.terjemah(terjemah)

Kaedah: terjemah(float dx, float dy)

Analisis: Terjemahan, alihkan asal koordinat kanvas ke kiri dan kanan dengan x dan atas dan bawah oleh y. Kedudukan lalai kanvas ialah (0, 0)

Parameter : dx ialah jarak pergerakan dalam arah mendatar, dy ialah jarak pergerakan dalam arah menegak

Contoh penggunaan:

for(int i=0; i < 5; i++) {
    canvas.drawCircle(50, 50, 50, mPaint);
    canvas.translate(100, 100);
}
Kesan operasi :

2.png


2.putar(putar)

Kaedah :putar(darjah terapung) / putar(darjah terapung, px terapung, terapung py)

Analisis: Putar darjah sekeliling asal koordinat, nilainya adalah positif mengikut arah jam

Parameter: darjah ialah sudut putaran, px dan py ialah koordinat titik tengah putaran yang ditentukan (px, py)

Contoh penggunaan:

Rect rect = new Rect(50,0,150,50);
canvas.translate(200, 200);
for(int i = 0; i < 36;i++){
    canvas.rotate(10);
    canvas.drawRect(rect, mPaint);
}

Kesan berjalan:

3.png

Kod Analisis :

Di sini kita mula-mula memanggil terjemah(200, 200) untuk mengalihkan asal koordinat kanvas ke (200, 200), dan kemudian melukis, jadi kita Hasil lukisan boleh dipaparkan sepenuhnya pada kanvas Jika kita tetapkan (10,200,200) untuk putaran, ia akan kelihatan seperti ini Keputusan:

4.png

Anda ada soalan, bukan? Ini melibatkan konsep berbilang lapisan Kanvas, yang akan saya bincangkan nanti~


3 .skala( Skala)

kaedah: skala(float sx, float sy) / skala(float sx, float sy , float px , float py)

Analisis: Skala kanvas

Parameter: sx ialah nisbah penskalaan mendatar, sy ialah penskalaan menegak Saya juga tidak tahu nisbah, px dan py Perpuluhan bermaksud pengurangan, Integer bermaksud pembesaran

Contoh penggunaan:

canvas.drawBitmap(bmp,0,0,mPaint);
canvas.scale(0.8f, 0.8f);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.scale(0.8f, 0.8f);
canvas.drawBitmap(bmp,0,0,mPaint);

Kesan operasi:

5.png


4.skew(skew)

<> kaedah skew(float sx, float sy)

Analisis : skew, boleh juga diterjemahkan sebagai bevel, twist

Parameter : sx ialah sudut kecondongan yang sepadan dalam arah paksi-x, sy ialah sudut kecondongan yang sepadan dalam arah paksi-y, kedua-dua nilai adalah nilai tan! Mereka semua adalah nilai tan! Mereka semua adalah nilai tan! Sebagai contoh, jika anda ingin mencondongkan 60 darjah dalam arah paksi-x, maka nilai perpuluhan sepadan dengan: tan 60 = punca kuasa dua 3 = 1.732!

Contoh penggunaan:

canvas.drawBitmap(bmp,0,0,mPaint);
canvas.translate(200, 200);
canvas.skew(0.2f,-0.8f);
canvas.drawBitmap(bmp,0,0,mPaint);

Kesan operasi:

6.png

5. Konsep lapisan Kanvas dan penerangan terperinci save() dan pulihkan()

Kami biasanya suka memanggil kanvas Kanvas, dan kanak-kanak sentiasa berfikir bahawa Kanvas ialah Sekeping kertas lukisan yang ringkas, maka saya fikir Saya ingin bertanya bagaimana animasi berbilang lapisan diselesaikan menggunakan kanvas? Dalam contoh terjemahan di atas, mengapa? drawCircle(50, 50, 50, mPaint); Koordinat rujukan sentiasa (50,50), jadi mengapa kesan ini berlaku? Kanak-kanak yang keliru mungkin telah mengelirukan konsep skrin dengan konsep Kanvas Mari kita pulihkan di bawah. Tempat kejadian di mana penterjemahan dipanggil:

7.png

Seperti yang ditunjukkan dalam rajah, asal koordinat kanvas bergerak 100 pada paksi x dan y setiap kali, maka jika kita mahu kembali ke (0,0) Bagaimana pula dengan melukis grafik baharu pada titik yang berbeza? Bagaimana untuk memecahkannya, terjemah (-100,-100) perlahan-lahan menterjemah kembali? Tidak juga Keliru...8.jpg

Baiklah, jangan terlalu terbawa-bawa. Kita boleh menyimpan keadaan kanvas semasa sebelum melakukan transformasi terjemahan Kami menyediakan sokongan untuk lapisan, dan lapisan ini diuruskan mengikut "struktur tindanan"

9.png

Apabila kami memanggil kaedah save() , akan menyimpan keadaan Kanvas semasa dan menambah ia ke tindanan Kanvas sebagai Lapisan. Di samping itu, Layer ini bukan kelas tertentu, ia hanya satu perkara konsep!

Dan apabila kita memanggil kaedah restore(), keadaan Kanvas sebelumnya akan dipulihkan, dan pada masa ini tindanan lapisan Kanvas Lapisan di bahagian atas tindanan akan muncul, dan Lapisan seterusnya akan sampai ke bahagian atas tindanan Pada masa ini, Kanvas akan kembali kepada keadaan Kanvas yang disimpan di bahagian atas tindanan!

Secara ringkasnya : save() menolak Layer ke dalam tindanan, dan restore() memunculkan Layer pada bahagian atas tindanan ini. negeri! Maksudnya, anda boleh menyimpan() beberapa kali atau memulihkan() beberapa kali, tetapi bilangan panggilan pemulihan tidak boleh lebih daripada simpan Jika tidak ralat akan dilemparkan! Inilah yang kebanyakan orang katakan di Internet, tetapi tiada masalah sedemikian berlaku dalam ujian sebenar, walaupun saya memulihkan Bilangan kali lebih banyak daripada menyimpan, dan tiada ralat~ Pemeriksaan visual ialah sistem telah ditukar, saya akan tunjukkan kepada semua orang dalam ujian seterusnya~10.gifAyuh, tulis contoh untuk mengesahkan fungsi. simpan dan pulihkan!

Tulis contoh:

Contoh kod:

canvas.save();  //保存当前canvas的状态

canvas.translate(100, 100);
canvas.drawCircle(50, 50, 50, mPaint);

canvas.restore();  //恢复保存的Canvas的状态
canvas.drawCircle(50, 50, 50, mPaint);

Hasil berjalan:

11.png

Tidak perlu dikatakan, kod dan keputusan telah menjelaskan segala-galanya, mari kita buat ia lebih rumit dan cuba Simpan berbilang () dan pulihkan ()!

Kod contoh:

canvas.save();

canvas.translate(300, 300);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.save();

canvas.rotate(45);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.save();

canvas.rotate(45);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.save();

canvas.translate(0, 200);
canvas.drawBitmap(bmp, 0, 0, mPaint);

Hasil jalankan:

12.png

Hasil Analisis :

Terjemah dahulu (300,300) untuk melukis, kemudian putar 45 darjah untuk melukis, kemudian putar 45 darjah untuk melukis, kemudian terjemah (0,200), Dalam tempoh ini, save() dilakukan setiap kali sebelum melukis Anda mungkin mempunyai soalan apabila anda melihat ini. Nah, kenapa ia membelok ke kiri? Hei, adakah saya akan memberitahu anda bahawa rotate() memutarkan keseluruhan paksi koordinat? paksi koordinat Perubahan:

13.png

Nah, anda faham rotate(), kan? Tambah dua restore()!

canvas.restore();
canvas.restore();
canvas.translate(0, 200);
canvas.drawBitmap(bmp, 0, 0, mPaint);

Hasil operasi:

14.png

Jangan cakap apa-apa, alami sendiri, tambah lagi pulihkan()!

15.png

Memang menarik, mari teruskan menambah restore()

17.png

Nampaknya kita tidak boleh lagi menulis memulihkan, kan? Ini akan melaporkan ralat, adakah itu benar-benar berlaku? Di sini kami memanggil yang disediakan oleh Canvas untuk mendapatkan tindanan semasa Terdapat berapa banyak kaedah Lapisan: getSaveCount() dan kemudian sebelum dan selepas save() dan restore(); Tambah Log untuk mencetak bilangan Lapisan dalam tindanan:

18.png

Hasilnya benar-benar menggembirakan. Lagipun, amalan membawa pengetahuan yang benar diubah suai, atau atas sebab lain Di sini Anda perlu melihat kod sumber untuk mengetahui kerana kekangan masa, di sini kita tahu bahawa bilangan pemulihan boleh lebih daripada jumlah simpanan. Walau bagaimanapun, ia masih disyorkan untuk memulihkan kurang kerap daripada menyimpan untuk mengelakkan masalah yang tidak perlu~ Bagi proses masuk dan keluar dari timbunan, saya tidak akan bercakap mengenainya saya melukisnya sendiri dan ia sangat mudah untuk difahami.


6. Penjelasan SaveLayer() dan restoreToCount()

Malah, kedua-dua kaedah ini adalah serupa dengan menyimpan dan memulihkan, tetapi terdapat beberapa perkara tambahan berdasarkan yang terakhir. Sebagai contoh, saveLayer() mempunyai kaedah terlebih beban berikut:

19.png

Anda boleh memahami bahawa kaedah save() menyimpan keseluruhan Kanvas , dan saveLayer() secara terpilih boleh menyimpan keadaan kawasan tertentu. Di samping itu, kami melihat bahawa terdapat: int saveFlags di dalam bilik dan papan, ini adalah tetapan untuk menukar objek untuk disimpan! Nilai pilihan ialah:

标记说明
ALL_SAVE_FLAG保存全部的状态
CLIP_SAVE_FLAG保存裁剪的某个区域的状态
CLIP_TO_LAYER_SAVE_FLAG保存预先设置的范围里的状态
FULL_COLOR_LAYER_SAVE_FLAG保存彩色涂层
HAS_ALPHA_LAYER_SAVE_FLAG不透明图层保存
MATRIX_SAVE_FLAGMatrix信息(translate,rotate,scale,skew)的状态保存

PS: Ada sesuatu yang salah dengan penjelasan di atas tahap Bahasa Inggeris penulis adalah rendah dan saya mungkin salah jika anda tahu apa-apa, sila pastikan untuk membetulkan saya

Di sini kami menulis contoh untuk mengesahkan Seterusnya: Kami memilih mod

CLIP_TO_LAYER_SAVE_FLAG untuk menulis contoh

Kod pelaksanaan:

RectF bounds = new RectF(0, 0, 400, 400);
canvas.saveLayer(bounds, mPaint, Canvas.CLIP_TO_LAYER_SAVE_FLAG);
canvas.drawColor(getResources().getColor(R.color.moss_tide));
canvas.drawBitmap(bmp, 200, 200, mPaint);
canvas.restoreToCount(1);
canvas.drawBitmap(bmp, 300, 200, mPaint);

Hasil berjalan:

20.png

Mari kita kaji secara terperinci tentang saveLayer() kerana ia akan digunakan kemudian~ Berikut adalah idea kasar~

Kemudian pergi ke

restoreToCount(int) ini, Ini lebih mudah, cuma masukkan bilangan Lapisan yang anda ingin pulihkan. Lompat terus ke lapisan yang sepadan, dan pada masa yang sama tendang semua Lapisan di atas lapisan keluar daripada timbunan, supaya lapisan Jadilah bahagian atas timbunan~! Ia lebih mudah dan lebih pantas daripada menulis pemulihan berganda()~


7. Muat turun sampel kod dalam bahagian ini:

Nah, kod itu ditulis untuk ujian, jadi tiada perlu Ia tidak bermakna banyak, tetapi mungkin pembaca masih mahukannya, jadi hantar sahaja pautan!

Muat turun kod: CanvasDemo.zipMungkin ini gambar yang anda mahukan! Haha~

21.jpg


Ringkasan bahagian ini:

Bahagian ini mengambil masa beberapa hari untuk saya menulis kerana penulis tidak pasti tentang ia pada permulaannya Konsep lapisan Kanvas ini juga tidak begitu jelas. Saya menyelesaikan kerja saya petang ini dan memikirkan pemikiran saya. Saya bekerja lebih masa pada waktu petang dan akhirnya menulis artikel ini. Semua orang memahami Kanvas dengan lebih jelas, dan anda tidak akan keliru apabila kawalan tersuai lanjutan~ Hehe, itu sahaja untuk bahagian ini. Jika ada salah silap mohon dimaklumkan, terima kasih~

21.gif