2012-08-12

ויזואליזציה בצד הדפדפן


אני זוכר קבוצה של מפתחים שעבדו על מערכת בקרה לשרתים שנכתבה ב ++C. הם היו מפתחים ותיקים ומקצועיים ונראה היה שהם מסתדרים ללא בעיה.
אלו היו הימים המוקדמים של ג'אווה / #C כטכנולוגיות צד שרת. אני זוכר את הדיון שהתרחש: הציעו לאנשי הצוות לעבור להשתמש ב #C - אבל הם לא האמינו שזה יועיל להם. "מה יש ב #C שאין ב ++C? ניקוי זיכרון אוטומטי? אנחנו עובדים עם AutoPointers ואין לנו בעיות. #C היא טכנולוגיה למפתחים מתחילים".
- "יש לנו את ACE (ספריית תקשורת), אין שום דבר דומה ב #C" (ספריית התקשורת הבסיסית של #C הייתה טובה מספיק)
- "#C קיימת רק 3 שנים, ניתן לה כמה שנים להתבגר" (הממ... יש בזה משהו...)
- "אם נצטרך יום אחד לעשות משהו מיוחד - ++C תאפשר הכל" (אין מניעה להשתמש ב ++C בתוך תוכנת #C)
- "אין לנו זמן ללמוד שפה חדשה, אנחנו עמוסים בעבודה"
וכו'

אחרי שנתיים בערך כתבו את מערכת הבקרה מחדש ב #C - וזו הייתה הצלחה גדולה. זו הייתה מערכת לדוגמה שבה שימוש ב ++C היה מיותר.
האם מישהו היה שוקל כיום לכתוב מערכת שכזו ++C? - כנראה שלא.


תהליך דומה מתרחש כיום בעולם ה Client-Side. אחד האתגרים העומדים בעת פיתוח אפליקציות HTML5, ומובייל בפרט, הוא ליצור ויזואליזציה מושכת: משהו נעים למראה, ו"מגניב". הכלים המוכרים הם כנראה CSS3 וג'אווהסקריפט. CSS3 הוא כלי רב-עצמה ומי שמתמחה בו יכול להגיע לתוצאות מרשימות.

ויזואליזציה של טופס, שכאשר מסיימים למלא אותו הוא מחליק לתוך מעטפה. ללא JavaScript! מקור

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

כתיבת ויזואליזציה ברמה גבוהה בעזרת CSS3 הוא תרגיל מאתגר המלמד הרבה על CSS3 ו HTML - אבל הוא קשה משמעותית יותר לתחזוקה מאשר שימוש בספרייה שהיא יותר "גבוהה". כנ"ל לגבי אלמנט ה cavnas של HTML5: בעזרת קוד JavaScript ניתן לצייר על ה canvas  ברמת הפיקסל[א], וכך ליצור כל סוג של ויזואליזציה, אבל קל להגיע מהר מאוד לעשרות או אפילו מאות של קוד ג'אווהסקריפט לא-קריא.


Browser-Side Visualization Technology Stack
ברצוני להציג בפניכם את ה "Stack" טכנולוגיות הוויזואליזציה של צד-הדפדפן. זו לא הרכב אפשרי יחידי, כמובן, אך זה הרכב של כלים מוצלחים ומשלימים שיכול לתמוך במשימות ויזואליזציה מורכבות. לא מדובר ב"טוב" או "רע", כי אם בבחירת הכלי הנכון למשימה.



שתי הטכנולוגיות העיקריות לוויזואליזציה ב HTML5 הן SVG ו Canvas ומעל כל אחת יש ספריות שמרחיבות ומעשירות אותה. CSS משמש בעיקר ל Styling, כלומר לקחת את הקיים ולהוסיף לו טאץ' עיצובי. כפי שראינו למעלה, ניתן ממש "לצייר" בעזרת CSS - אך זו אינה מטרתו העיקרית.
הערה: אני מתעלם בכוונה מ WebGL וכל הנושא של תלת-מימד. באופן אישי אני מוצא את תלת-המימד פחות חשוב מוויזואליזציה דו-מימדית ולכן פוסט זה יעסוק רק בה.


HTML
כוללת בעיקר מבנה וטקסט. יכולות הוויזואליזציה הן דיי מוגבלות:
  • ניתן להשתמש בטבלאות לעימוד. ישנה תגית <hr> לקו הפרדה רוחבי.
  • ניתן ליצור ציורי ASCII מרשימים (שימוש בטקסט).
  • ישנן מספר תגיות שמשפיעות על עיצוב הטקסט כמו <h1>...<h6> או תוויות b/u/i.
ויזואליזציה מסוג זה היא מאוד ווינטג' - ומתאימה לשימושים... מאוד מסוימים.
תקן ה HTML5 Semantics מבקש להסיר מ HTML כל אלמנט של ויזואליזציה והפיכתו ל Data Only. לדוגמה:תג <b> לא אמור להשפיע על הטקסט אלא רק לסמן אותו ככזה. בקובץ ה CSS יוכלו לעצב את תג ה <b> כבולט.
בכדי לא לשבור (מיליוני) דפי HTML5 קיימים, נותרו על כנן רוב היכולות העיצוביות של דף ה HTML, אם כי ההמלצה היא להמעיט את השימוש בהן.


CSS3
ל CSS3 יש כמה יכולות ויזואליזציה מתקדמות:

Gradients & Borders
זה אולי האלמנט בעל השימוש הנפוץ ביותר בצמד HTML5+CSS3. היכולת לקחת כל אלמנט (לרוב זו תהיה תיבה פשוטה: Div או Span), לעטוף אותו במסגרת יפה ולתת לה רקע.
אפשרויות ליצור מסגרת מעוגלת בפינה השמאלית-העליונה. מקור: http://www.css3.info
את המסגרת המעוגלת, ניתן לייצר כאליפסה, ולבחור שהיא תהיה רק באחת מ4 הפינות של המרובע. עובי המסגרת יכול להיות גדול מאוד - כך שהאלמנט המרובע (כלומר ה div) יהפוך לאליפסה או עיגול.
צורות שנוצרו בעזרת משחק במסגרת של Div בעזרת CSS. מקור:  http://www.css3.info/preview/rounded-border/
הנה cheat sheet של רשימת צורות שונות והמימוש שלהם בעזרת CSS.

אם ממשיכים במשחק, מוסיפים גם רקע (gradient) והצללות, אפשר למקם כמה אלמנטים (position: relative) אחד על גבי השני ולייצר ממש "ציור". הנה דוגמה ליצירת הלוגו של דפדפן אופרה בשיטה זו:

אופס! לא עובד ב IE ישן. מקור:  http://v2.desandro.com/articles/opera-logo-css/
יתרון ל CSS על פני תמונות (שהשימוש בהן היה נפוץ בעבר) הוא ש CSS הוא ציור וקטורי: תיאור של ציור, שברגע ההצגה הדפדפן יכול להשתמש ברזולוציה המלאה של המכשיר לצייר אותו. אם מנסים להציג תמונה ברזולוציה גבוהה יותר ממה שנוצרה - ייווצר עיוות של "פיקסליזציה"[א2].

CSS מספק גם:
  • יכולות טרנספורמציה - היכולת לסובב (rotate) ולמתוח אלמנטים ב DOM.
  • יכולות מעבר (transition) המאפשרת להפוך אלמנט ממצב א' למצב ב' - הנה דוגמה (בhover על העיפרון הוא ינוע לצד ימין). יכולות אלו מקבילות במידה רבה ל"אפקטים" של jQuery. ל jQuery יש היתרון של קביעת הפרמטרים בזמן הריצה (הרי את קובצי ה CSS יש לכתוב מראש) - כך שעדיין קל יותר להשתמש ב jQuery בדפים דינמיים.
  • אנימציה, יכולת שדומה ליכולות מעבר, אך היא תכונה של האלמנט ולא אירוע חד-פעמי. הנה דוגמה לציור CSS עם אנימציה.
סה"כ CSS3 מציגה סט יפה של יכולות שיכול להספיק כדי לתת "טאץ של ויזואליזציה" בממשק "מבוסס-טופס". CSS הוא סטנדרטי ומוכר - מה שמבטיח מגוון רחב של כלים ודוגמאות באינטרנט.

אם אתם זקוקים ליכולות שמעבר לכך, אני ממליץ לכם להימנע מלהפוך ל"CSS Ninja" ופשוט להשתמש בכלי ויזואליזציה "כבדים יותר" עליהם נדבר בהמשך.


Canvas
אלמנט ה Canvas של HTML5 הוא כמו Div המכיל רשת של פיקסלים (bitmap) וניתן לצייר עליו בעזרת קוד javaScript. הנה דוגמה:
HTML:
<canvas id="myCanvas" width="120" height="120"></canvas>

JavaScript:
    function draw() {
      var canvas = document.getElementById("myCanvas");
      if (canvas.getContext) {
        var ctx = canvas.getContext("2d");
        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, 55, 50);
        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.fillRect (30, 30, 55, 50);
      }
    }


תיצור את התוצאה הבאה:

הפעולות הזמינות על הקנבס הן פעולות ברמת הפשטה נמוכה ("low level") ומזכירות מאוד 2D API (כגון זה של ג'אווה):
  • ציור צורות כגון קווים, מלבנים, עיגולים ונקודות כאשר אפשר לקבוע את צבע ועובי המסגרת ("Stroke") וצבע המילוי ("fill") - שיכול להיות גם gradient.
  • הרכבת של צורות (compositing) - ציור של צורות אחת על השנייה עם הגדרות אפשריות שונות כיצד יתנהגו הפיקסלים החופפים לשתיהן: האם הם יהיו של צורה A של צורה B, או פונקציה לוגית אחרת. ראו תרשים למטה המתאר את אפשרויות ה composting. 
  • טעינה של תמונה (קובץ PNG למשל) לתוך ה canvas בעזרת פקודת (drawImage (image,x,y
  • בכל שלב ה canvas משמש כ bitmap עליה ניתן לעשות פעולות, כגון טרנספורמציות - סיבוב, שינוי קנה המידה או שמירה כקובץ jpg / png.
  • אנימציה. ה canvas עצמו לא מספק יכולות אנימציה מפורשות, אולם בעזרת setInterval והרכבה (compositing) של שכבות canvas ניתן ליצור אנימציות מרשימות. SetInterval (סטנדרטי של JS) משמש על מנת לקרוא לפונקציית javaScript שתעדכן את ה Canvas כל פרק זמן. דרך אחת מקובלת היא לחזור על אותה פונקציית ציור על פעם עם ערכים אחרים (הזחה, סיבוב, צבעים שונים...). על מנת לא לצייר את כל המשטח מחדש בכל פעם ניתן להחזיק משטח "רקע" ומשטח "חזית", לבצע את השינויים במשטח החזית ולהרכיב אותו עם משטח הרקע.
    ל Canvas יש יכולת של שמירת מצב (פונקציות save ו restore) שמאפשרות לחזור לחזור למצב קודם של ה canvas. יכולת זו גם משמשת לעתים בבניית אנימציות.
    הנה דוגמה לאנימציית canvas טיפוסית. הנה הקוד הרלוונטי.
אפשרויות ההרכבה ב canvas בין source ל destination
בקישור זה תוכלו למצוא ריכוז ("Cheat Sheet") של היכולות העיקריות של ה Canvas.

לסיכום canvas הוא כלי רב-עצמה אך Low Level. כמות הקוד שיש לכתוב היא רבה, אם כי בניגוד ל"ציור" ב CSS שדורש הרבה יצירתיות והתחכמות - הציור ב canvas הוא פשוט וצפוי, תכונה שאני רואה בה יתרון ברור. הביצועים של canvas יכולים להיות טובים למדי - בסדרי גודל דומים לזו של אפליקציה שולחנית (לא עוד "ווב איטי"). כמובן שעל מנת להגיע לתוצאות כאלו כדאי לוודא שאתם מנצלים את האצת-החומרה האפשרית ומתייחסים לכללי בסיס של ביצועים ב canvas.


(SVG (Scalable Vector Graphics
SVG איננה טכנולוגיה חדשה. היא קיימת כעשור, החל מ 1999, אבל במשך שנים היא זכתה לאימוץ חלקי - בעיקר מצד דפדפני IE שהיו חלק משמעותי מאוד מהשוק.
התקן שאנו מדברים עליו עכשיו הוא תקן SVG גרסה 2.0 - תקן שעדיין בכתיבה אבל מכיל כמה תוספות משמעותיות מאז הגרסה הקודמת SVG 1.1. העבודה על גרסה 1.2 הופסקה באמצע עבור גרסה 2.0 אך יש באמצע גרסה בשם 1.2 Tiny - אם יצא לכם להיתקל בה.
תקן SVG 2.0 כולל אינטגרציה ל CSS3 ו HTML5 ורשימה של תוספות ושיפורים שונים ומשונים. החלק החשוב בו הוא שהתקן זוכה לתמיכה רחבה מכל הדפדפנים המודרניים (+IE9) התומכים ביכולות הבסיס (שמקורה עוד ב SVG 1.1 + כמה שיפורים) ובהדרגה גם ביכולות מתקדמות יותר של 2.0 (אפקטים, פילטרים, פונטים של SVG ועוד).

SVG עצמו הוא קובץ XML שמתאר ציור וקטורי. בקובץ ה SVG ניתן להשתמש כקובץ חיצוני ל HTML (כגון תמונה מפורמט png) או כתגית SVG שמקוננת בתוך ה markup. הנה דוגמה לתגית SVG מקוננת:

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
  <rect width="100%" height="100%" fill="red" />
  <circle cx="150" cy="100" r="80" fill="green" />
  <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>

הנה התוצאה:

כתיבת SVG ידנית יכולה להיות מתישה.
חלק מהיתרון של SVG היא היכולת לצייר את "קוד" ה SVG בעורך חיצוני כגון SVG-Edit או Google Docs Drawing - עורכים חינמיים ואונליין הנחמדים למשימות פשוטות, ועד כלים מקצועיים כגון Inskape (חינמי) או Adobe Illustrator ($$) שיכולים לייצא קובצי SVG. אם אתם רוצים ליצור ויזואליזציה וקטורית לאתר שלכם (כגון פאנל מהודר או מעטפה שטופס יחליק לתוכה) - מה יותר פשוט מלבקש מהמעצב הגרפי שיעבוד בכלי שהוא רגיל אליו ורק ישלח לכם קובץ SVG?

מלבד יכולות ציור פשוטות, SVG כולל:
  • טרנספורמציות (דומות ל CSS ו canvas שכבר ראינו)
  • יכולות הרכבה של אלמנטים / "ציורים" הנקראות Clipping and Masking והן עשירות מיכולות ה canvas.
  • היכולת להשפיע על אלמנטים בתוך ציור ה SVG בעזרת CSS (לדוגמה צבעי הקווים של אזור מסוים).
  • היכולת ליצור פונטים חדשים בעזרת SVG (יכולת שלא נתמכת היטב עדיין)
  • יכול להיסרק ע"י מנועי חיפוש (SEO) ויכול לתמוך ב Accessibility.
  • ואולי היכולת המתקדמת ביותר: להשתמש ב"פילטרים" או "אפקטים" המשפיעים על אלמנטים ב SVG. הכוונה ליכולות שמזכירות תוכנות כגון Adobe Photoshop ויכולות להשיג תוצאות שלא סביר להשיג בעזרת ציור פיקסל-פיקסל (כגון canvas) או הרכבות לוגיות של אלמנטים. דוגמאות מעניינות יכולות להיות הצללה (ניתן בלחיצה לשנות את כיוון ההצללה) או הדמייה של בוקה (Bokeh) - הטשטוש הרקע שיוצרת עדשת מצלמה איכותית וצלמים רבים אובססיביים לגביו.
    למרות ההבטחה הגדולה, SVG Filters דורשים כוח חישוב רב והפילטרים המתקדמים יותר עדיין לא נתמכים ע"י רוב הדפדפנים.

מדוע יש חפיפה בין canvas ל SVG?
קנבס הוצג לראשונה ע"י חברת אפל בגרסאת ה Webkit ששוחררה עם MacOS X. הוא שימש לייצר Desktop Widgets של מערכת ההפעלה (המקבילה ל gadget של Windows Vista) אך היה זמין גם בדפדפן הספארי.
ביקורת רבה הופנתה אל אפל שיצרה "תג" חדש ולא השתמשה בתקן הסטנדרטי - הרי הוא ה SVG. בנוסף התגלה שאפל הגנה בפטנטים על התג החדש - דבר שלא היה ברור לכל כשהציגה אותו.
האם הכוונה היה לאפשר למתחרה כלשהו לאמץ את התקן ואז למצוץ את דמו בעזרת הפטנטים? - לא ברור. אפל לא נראתה טוב בהיבט זה ולאחר זמן קצר תרמה את הפטנטים לשימוש חופשי של W3C - בתנאי שיהפוך לחלק מהתקן ה HTML. כחלק מתנאי ההסכם - התקן אומץ במלואו (גם חלקים שהיוו כפילות ליכולות SVG).


כיצד בוחרים בין Canvas, SVG ו CSS3
נראה לי שרוב הנתונים הונחו כבר לפניכם, אך ברצוני לסכם:
ראשית, יתרון של SVG, Canvas ו CSS3 מול ספריות "גבוהות יותר" הוא שלא צריך לטעון קוד ג'אווהסקריפט על מנת להשתמש בהן. הן סטנדרטיות לגמרי ומוכרות לכל.

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

SVG או Canvas
ל canvas יש יתרון משמעותי בביצועים. כאשר מדובר באנימציות או ציורים בעלי פרטים רבים - כדאי לשקול שימוש ב canvas. מסיבה זו בשימוש במשחקים כמעט ולא תמצאו SVG אלא כמעט ורק canvas.
בכל מקרה אחר - הייתי נוטה לבחור קודם כל ב SVG, אלא אם הוכח אחרת. תחזוקה של קוד canvas יכולה להיות קשה למדי (קוד עמוס פרטים ולא קריא) והיכולת לעבוד בכלי גרפי מתקדם על מנת ליצור חלק נכבד מהוויזואליזציה כ SVG מסייעת ליצור פתרונות מהירים ואמינים יותר.
עדכון: נתקלתי ב Responsive IDE שתומך ב canvas - כלומר מקום בו אתם יכולים לכתוב קוד ג'אווהסקריפט ובכל פעם שתצביעו עם העכבר על ערך מספרי (מידה או צבע) תוכלו לגרור את העכבר, לשנות את הערך ולראות את התוצאה במקום. מדהים! אם אתם מציירים ב canvas זה יכול להיות שיפור פריון אדיר.

כמובן שגם SVG וגם Canvas הם כלים "נמוכים" בהם צריך לעבוד קשה על מנת להשיג מעט. אם מדובר בוויזואליזציה רספונסיבית ומורכבת - כדאי לעבור לרמות הפשטה גבוהות כגון Raphael, Processing או אפילו D3 או Fabric. אלו רק 4 ספריות וכמובן שיש עשרות ספריות נוספות לוויזואליזציה ב JavaScript היכולות להתאים למשימות מגוונות.


----

[א] pixel = גרסך (גרגר מסך) בעברית תקנית - לחובבי העברית שבינכם.

[א2] גרסכיזציה. למרות אהבתי לשפה העברית נדמה לי לעתים ששימוש מדוקדק בה עלול לפגוע, בצורה אנושה, בתקשורת שבין בני-אנוש.


3 תגובות:

  1. פוסט מעולה!
    הייתי אומר ש canvas זה כמו gdi לוויב.

    השבמחק
  2. חשוב לציין שה CANVAS הופך את ה JavaScript לשפה שמעבר לשפת סקריפטים ואפקטים שמאפשרת כתיבת אפליקציות מסובכות (על צד הלקוח כמובן) בניגוד ל SVG שמאוד מסורבלת ומתאימה יותר לעולם הדפוס.

    פוסט מעולה.

    השבמחק
  3. אנונימי27/1/16 14:44

    פוסט מצויין!
    סוף סוף מאמר שמסביר בצורה מסודרת כל דבר!

    השבמחק