יום רביעי, דצמבר 15

גרפיקה 2D: ציור על ה-Canvas

נתחיל בגרפיקה בסיסית. נקשקש קצת  על הבד. כדי לעשות את זה נשתמש בכלים הבאים:

Bitmap - זהו המשטח עליו מציירים. הוא מכיל את הפיקסלים.
 Canvas - ה- canvas משמש כממשק למשטח העבודה. דרך המתודות של ה-canvas מתבצע הציור על גבי המשטח
Paint - זה הכלי איתו מציירים. הוא קובע את הצבע, הגודל, גודל וצורת הטקסט וכו".
Path- זהו class המאפשר הגדרה של קבוצת אלמנטים גרפיים ביחד: צורות, עקומות, טקסט וכו. נדגים שילוב טקסט וצורות בעזרת ה-path.

אז לעבודה. נצייר את המסך הבא:
תמונה מס 1: ציור על bitmap.



תמונה מס 2: ציור על bitmap שמיוצר מתמונה (jpg).






הדרך הפשוטה לציור, היא לעבוד עם class מסוג view. ה-class הזה כולל את המתודה
(onDraw(Canvas canvas . היא מקבלת את ה-canvas המוכן לציור. אין צורך לטפל ב-bitmap. נדגים גם טיפול ב-bitmap כדי לצור רקע מבוסס על תמונה, כמו בתמונה מס 2 למעלה.

הנה הקוד. המתודה onCreate קצת ארוכה, אבל אל דאגה -היא ממש טריוויאלית, פשוט מדגימה ציור של מספר צורות שדי חוזר על עצמו.

  1. public class MyGraphicsBasics extends Activity {
  2.     Bitmap bmp;
  3.        /** Called when the activity is first created. */
  4.     @Override
  5.     public void onCreate(Bundle savedInstanceState) {
  6.         super.onCreate(savedInstanceState);
  7.          DrawOnView myCanvasView = new DrawOnView(this);
  8.         setContentView(myCanvasView);
  9.     }
  10.    
  11.     private class DrawOnView extends View{
  12.         public drawOnView(Context context) {
  13.         super(context);
  14.         }
  15.         @Override
  16.         protected void onDraw(Canvas canvas) {
  17.                Paint myPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  18.             myPaint.setColor(Color.RED);
  19.             canvas.drawPaint(myPaint);
  20.             myPaint.setStyle(Paint.Style.STROKE);
  21.             myPaint.setColor(Color.GREEN);
  22.             myPaint.setStrokeWidth(5);
  23.             canvas.drawRect(10, 10, 100, 100, myPaint);
  24.             canvas.drawCircle(55,55 , 45 , myPaint);
  25.             myPaint.setColor(Color.YELLOW);
  26.             myPaint.setStyle(Paint.Style.STROKE);
  27.             final int SHIFT1 = 100;
  28.             canvas.drawRect(SHIFT1 + 10,SHIFT1 +  10,SHIFT1 +  100, SHIFT1 + 100, myPaint);
  29.             myPaint.setStyle(Paint.Style.FILL);
  30.             canvas.drawCircle(SHIFT1 + 55,SHIFT1 + 55 , 45 , myPaint);
  31.             myPaint.setColor(Color.BLUE);
  32.             canvas.drawRoundRect (new RectF(SHIFT1+100,SHIFT1+100,2*SHIFT1+100,2*SHIFT1+100),20,20,myPaint);
  33.             myPaint.setColor(Color.WHITE);
  34.             canvas.drawText("Round Rectangular", SHIFT1+100,1.5f*SHIFT1+100,myPaint);
  35.             Path path = new Path();
  36.             path.addCircle(SHIFT1 + 55,SHIFT1 + 55, 30, Direction.CW);
  37.             canvas.drawPath(path, myPaint);
  38.             myPaint.setColor(Color.BLACK);
  39.             canvas.drawTextOnPath("In God We Trust...", path, 100, 10, myPaint);
  40.             Path path2 = new Path();
  41.             path2.addOval(new RectF(10,SHIFT1+120,150,SHIFT1+240),Direction.CW);
  42.             myPaint.setColor(Color.BLACK);
  43.             canvas.drawPath(path2, myPaint);
  44.             myPaint.setColor(Color.WHITE);
  45.             myPaint.setTextSize(16);
  46.             canvas.drawTextOnPath("Some nice text on an oval ", path2, 200, 20, myPaint);
  47.         }
  48.     }
  49. }


הקוד מכיל שני classes.
  • class מסוג Activity, שמטפל כרגיל ב-UI. במסגרת תהליך זה הוא יוצר את האובייקט השני.
  • class מסוג View. בו נתרכז.

נציץ ב-class הראשון:
המתודה onCreate בלבד ממומשת כאן:
  1. public class MyGraphicsBasics extends Activity {
  2.     Bitmap bmp;
  3.        /** Called when the activity is first created. */
  4.     @Override
  5.     public void onCreate(Bundle savedInstanceState) {
  6.         super.onCreate(savedInstanceState);
  7.          DrawOnView myCanvasView = new DrawOnView(this);
  8.         setContentView(myCanvasView);
  9.     }

שורות 7 ו-8 מענינות:
  • שורה 7 יוצרת ומאתחלת אובייקט מסוג DrawOnView. זהו האובייקט שנסקור כאן.
  • שורה 8 מפנה לתצוגה את ה-view הנ"ל.

נעבור ל-class השני. ה-superclass שלו הוא View, והוא מממש שתי מתודות:
  • constructor - רק מפעיל את ה-constructor של ה-superclass.
  • onDraw - זו המתודה שמצירת על הצג. היא נקראת כ-callback בכל פעם שיש שינוי בתצוגה, שיכול להגרם ע"י invalidate או setContentView.
onDraw מקבלת את ה-canvas כפרמטר מוכן, כך שאפשר לגשת ישר למלאכת הציור.
היה ניתן לייצר גם canvas עצמאית, אם למשל היינו רוצים לבסס את ה- bitmap על drawable קיים.
כדי לעשות זאת יש להוסיף את השורות הבאות בתחילת המתודה:

  1.             Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.p35);
  2.             canvas.drawBitmap(bmp, null, new RectF(0,0,getWidth(), getHeight()), null);

שורה 1 מייצרת את תמונת ה-bitmap מתוך התמונה p35 שנמצאת ב-drawable (התמונה אכן מוכנה שם עם קבצי המקור המצורפים).
שורה 2 מחברת את ה-canvas ל-bitmap.

נחזור למתודה שלנו. כל שנותר הוא לצור אובייקט מסוג Paint ולהתחיל לצייר על גבי ה-Canvas.
יצור ואיתחול ה-Paint:
               Paint myPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
ה-Paint.ANTI_ALIAS_FLAG נותן תמונה עם צורות חלקות יותר.
 מכאן כאמור התחלתי לשחק עם המתודות של Paint:
 קביעת צבע:
  myPaint.setColor(Color.RED); 

צורות חלולות (STROKE) או מלאות (FILL):
            myPaint.setStyle(Paint.Style.STROKE);
קביעת עובי הקו:

            myPaint.setStrokeWidth(5);

קביעת גודל הטקסט:
            myPaint.setTextSize(16);

שיחקתי עם יצירת Path והוספת אובייקטים אליו:

  1. Path path = new Path();
  2. path.addCircle(SHIFT1 + 55,SHIFT1 + 55, 30, Direction.CW);
  3. path2.addOval(new RectF(10,SHIFT1+120,150,SHIFT1+240),Direction.CW);
בשורה 2, הוספת העיגול נעשית על פי הקואורדינטות של מרכז העיגול, רדיוס וכיוון העיגול.  הטקסט שיכתב על העיגול יפנה לפי הכיוון הנ"ל. הכיוון יכול להיות עם כיוון השעון (CW), או נגדו CCW. 
בשורה 3 מתווספת אליפסה ל-Path. היא מוגדרת ע"י הקודקוד השמאלי עליון והימני תחתון של המלבן החסום, והכיוון.



 וגם עם המתודות של Canvas:

 צביעת המשטח:
   canvas.drawPaint(myPaint);
ציור מלבן על סמך הקואורדינטות של הקודקוד העליון משמאל והתחתון מימין + אובייקט Paint:
          
            canvas.drawRect(10, 10, 100, 100, myPaint);
ציור עיגול על פי הקואורדינטות של המרכז והרדיוס + Paint:

            canvas.drawCircle(55,55 , 45 , myPaint);
     
ציור מלבן עם מעוגל על פי קואורדינטות של מלבן (RectF), רדיוס העקמומיות של הצלעות האופקיות והאנכיות + Paint.
canvas.drawRoundRect (new RectF(SHIFT1+100,SHIFT1+100,2*SHIFT1+100,2*SHIFT1+100),20,20,myPaint);
כתיבת טקסט, מיקומו על פי קואורדינטות נקודת ההתחלה + Paint.
  canvas.drawText("Round Rectangular", SHIFT1+100,1.5f*SHIFT1+100,myPaint);
ציור Path:


 canvas.drawPath(path, myPaint);
שילוב טקסט ב-Path: (ראה בתמונות למעלה את הטקסט בתוך העיגול הלבן ואת זה שבאליפסה השחורה):
canvas.drawTextOnPath("In God We Trust...", path, 100, 10, myPaint);


 

אין תגובות:

הוסף רשומת תגובה