מקרה לדוגמה - HTML5 MathBoard

Jeremy Chone
Jeremy Chone

מבוא

יישום MathBoard

MathBoard ב-iPad, אפליקציה של PalaSoftware, היא אפליקציה מטופחת עם הרבה אנימציות עדינות אך טבעיות ומראה ותחושה מציאותיים ייחודיים. המטרה הייתה להגיע ליציאת האיכות הגבוהה ביותר של האפליקציה ל-iPad ל-HTML5.

N2N-Apps היא חברה לפיתוח תוכנה המתמקדת ביצירת הדור הבא של אפליקציות לאינטרנט ולנייד באמצעות טכנולוגיית HTML5. החברה מימנה בשנת 2010 את ג'רמי צ'ון, ולאחר 11 שנות ניסיון בהנדסה ובניהול מ-Netscape, מ-Oracle ו-Adobe, החליטו לשתף את המומחיות שלה עם עסקים כדי לפתח אפליקציות איכותיות לאינטרנט ולנייד. N2N-Apps מתמקד באיכות ובמהירות ההעברה.

הורדת MathBoard לחנות האינטרנט של Chrome הורדת MathBoard לחנות האינטרנט של Chrome (גרסה בחינם)

דרישות

הדרישות העיקריות לפרויקט ניוד ה-HTML5 הזה היו:

  1. יציאה באיכות גבוהה של המראה והתחושה של אפליקציית iPad המקורית וממשק המשתמש.
  2. התאמה לגורם הצורה של היעד (כלומר מחשב PC/Mac עם מקלדת/עכבר לעומת מסך מגע).
  3. הטמעת 100% מהתכונות הרלוונטיות.
  4. לטרגט בעיקר דפדפני HTML5.
  5. הפוך את היישום ל "ללא שרת", כך שהיישום יפעל באופן מלא על הלקוח ותוכל להתארח בשרת סטטי או ביישום ארוז של Google Chrome.
  6. תוך פחות מחודש כדאי ליצור גרסה 1.0 עם כל התכונות מלבד פתרון הבעיות.

ארכיטקטורה

ארכיטקטורה

בהתאם לדרישות, החלטנו להשתמש בארכיטקטורה הבאה:

  1. HTML5: מכיוון שאין לנו דרישות תמיכה כלשהן ב-HTML4, החלטנו להשתמש ב-HTML5 כבסיס.
  2. jQuery: למרות ש-HTML5 כולל רבים מהסלקטורים המתקדמים שהופכים את jQuery לכל כך מעולה, החלטנו להישאר עם jQuery בכל מקרה, כי כך יש לנו דרך חזקה ובוגרת מאוד לטפל ב-DOM ובאירועים קשורים. ל-jQuery יש גם את היתרון מפני שהיא ממוקדת ב-DOM, ולכן התכנון והיישום של יישום דומים ל-HTML.
  3. SnowUI: jQuery מספק API מצוין ושיטות מומלצות לעבודה עם ה-DOM. עם זאת, כדי להשתמש ב-DOM MathBoard של אפליקציית HTML5 MathBoard, היה צורך ב-framework בסגנון MVC או MVP כדי לתזמר את כל התצוגות השונות. SnowUI היא מסגרת MVC פשוטה אך עוצמתית שמבוססת על jQuery. הוא מספק מנגנון MVC מבוסס DOM ודרך גמישה לבנות רכיבים מותאמים אישית, תוך מתן הזדמנות למפתח האפליקציות להשתמש בכל ווידג'ט/ספרייה או קוד מותאם אישית שהם סבורים שהוא אופטימלי.

שיקולים ביחס ל-iPad למחשב

במהלך ניוד האפליקציה ל-HTML5 לשימוש במחשב, היינו צריכים לבצע מספר שינויים בעיצוב ובאינטראקציה של האפליקציה.

כיוון המסך

ה-iPad MathBoard מיועד לפורמט אנכי בלבד, מה שלא היה אופטימלי לצגי מחשב, כי בדרך כלל הם מוצגים לרוחב. כתוצאה מכך, ארגנו מחדש את העיצוב של ממשק המשתמש והעברנו את חלונית ההגדרות לצד ימין, בתצוגה זזה (מונפשת על ידי מעברי CSS3).

כיוון מסך
כיוון המסך של iPad לעומת HTML5

קלט: מקלדת/עכבר לעומת מגע

הבדל משמעותי נוסף בין גרסת iPad לגרסת האינטרנט הוא ממשק הקלט. ב-iPad יש רק ממשק מגע, במחשב צריך להתחשב גם בעכבר וגם במקלדת.

פקדי הקלט של MathBoard ב-iPad מלוטשים מאוד. רצינו לקבל את אותו ייצוג ברמת דיוק גבוהה בממשק האינטרנט. במסגרת הפתרון הוספנו תמיכה במקשי קיצור ובשכפול פקדים בממשק המשתמש באמצעות מיקום CSS. היציאה ל-HTML5 הייתה מושלמת עם פיקסלים:

פקדים בממשק המשתמש
הגדרות של גרסת iPad לעומת HTML5

כמו בממשק של iPad, אנחנו מאפשרים למשתמש ללחוץ על החצים שמאלה וימינה כדי לשנות את הערך של אמצעי הבקרה. אפשר גם לגרור את הקו האנכי כדי לשנות ערכים במהירות. התנהגות חוזרת הוטמעה ב-click וב-keydown כדי שהמשתמשים יוכלו להאיץ את שינוי הערך כשלוחצים על העכבר או על המקלדת.

נוספה תמיכה ב-TAB כדי לעבור משדה קלט אחד לאחר, והחצים ← ו-← עוברים בין הערכים.

אחד הפיצ'רים בגרסת iPad לא היה כל כך הגיוני לממשק ה-PC היה לוח השרטוט. אפשר היה ליישם את זה בקלות, אבל לא ממש מעשי לצייר מספרים באמצעות עכבר. במקום זאת, החלטנו להקדיש יותר זמן לשיפור ממשק המקלדת מאשר בהטמעת לוח השרטוט.

תכונות של HTML5

בגרסת האינטרנט של MathBoard, אנחנו משתמשים בתכונות רבות של HTML5:

אחסון מקומי

ב-MathBoard המשתמשים יכולים לשמור את הבוחן שלהם כדי לחזור עליו מאוחר יותר. HTML5 MathBoard מיישם את התכונה הזו באמצעות HTML5 localStorage באמצעות ממשק SnowUI DAO.

הבחירה של localStorage הייתה טבעית, כי הנתונים היו פשוטים מספיק ולא דרשו הוספה מתקדמת לאינדקס. אנחנו מאחסנים את כל החידונים בפורמט JSON אחד, שאותו אנחנו JSON.stringify כטקסט.

ה-SnowUI DAO הוא wrapper פשוט של ממשק CRUD שמאפשר לממשק המשתמש לאחזר נתונים בלי לדאוג לגבי אופן האחסון שלהם בפועל. הטמעת ה-DAO מטפלת במפרטי האחסון.

דרישות האחסון ב-MathBoard היו פשוטות מאוד. היינו צריכים לאחסן רק את הגדרות המשתמש ואת נתוני הבחנים. שניהם מאוחסנים כמחרוזות JSON ב-localStorage.

כך, לדוגמה, ה-DAO עבור ערך ההגדרה נראה כך:

snow.dm.registerDao('settingValue', (function() {

  var _settingValues = null;

  function SettingValueDao() {};

  // ------ DAO CRUD Interface ------ //
  // get
  SettingValueDao.prototype.get = function(objectType, id) {
    return $.extend({},getSettingValues()[id]);
  };

  // find, remove

  // save
  SettingValueDao.prototype.save = function(objectType, data) {
    var storeValue = getSettingValues('settingValue')[data.id];
    if (!storeValue) {
      storeValue = {};
      getSettingValues()[data.id] = storeValue;
    }

    $.extend(storeValue, data);
    saveSettingValues();
  };
  // ------ /DAO CRUD Interface ------ //

  function getSettingValues() {
    if (_settingValues == null) {
      var settingValuesString = localStorage.getItem('settingValues');
      if (settingValuesString) {
        _settingValues = JSON.parse(settingValuesString);
      } else{
        _settingValues = {};
      }
    }

    return _settingValues;
  }

  function saveSettingValues(){
    var settingValues = getSettingValues();
    if (settingValues != null) {
      localStorage.removeItem('settingValues');
      localStorage.setItem('settingValues', JSON.stringify(settingValues)); 
    }
  }

  return new SettingValueDao();
})());

לאחר רישום ה-DAO ל-settingValue, ממשק המשתמש יכול לבצע את הקריאה הבאה בלי לדאוג ללוגיקת החנות:

var addition = snow.dm.get('settingValue', 'operator_addition');
addition.value = true; // to check the addition checkbox
snow.dm.save('settingValue', addition);

גופני CSS3

MathBoard משתמש בגופנים מותאמים אישית. בזכות התמיכה בגופנים של CSS3, היה חשוב להוסיף את הגופן האמיתי 'Chalkduster' לאפליקציה שלנו:

@font-face {
  font-family: Chalkduster;
  src: url(Chalkduster.ttf);
}

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

body {
  background: #333333;
  font-family: Chalkduster;
  color: #ffffff;
}

CSS3 הדרגתי, צל, פינות מעוגלות

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

בנוסף, השתמשנו בתכונות CSS3 מתקדמות כדי להתאים אישית את המראה והסגנון של סרגל הגלילה על מנת להפוך אותו לעדין יותר (למידע נוסף, ראו http://webkit.org/blog/363/styling-scrollbars/) לעיצוב סרגלי גלילה בדפדפני WebKit).

מעברי CSS3

ב-HTML5 MathBoard, שכפלנו את כל האנימציות של ה-iPad ואפילו הוספנו אנימציה חדשה לחלונית השמאלית המזיזת. הודות למעברי CSS3, הוספת אנימציות הייתה טריוויאלית והתאפשרה לביצועים הטובים ביותר.

האפליקציות כללו שלוש אנימציות עיקריות.

1) החלונית הנפתחת מימין

האנימציה הראשונה מופיעה בחלונית השמאלית (#rightPane), שהשקפים נסגרים כשהמשתמש מתחיל בוחן חדש והשקפים נפתחים כשהמשתמש מסיים את הבוחן. כדי ליצור את האפקט הזה, השתמשנו במעבר ה-CSS הבא והפעלנו אותו באמצעות JavaScript. סגנון ברירת המחדל של ה-rightPane פתוח:

#rightPane {
  /* look and feel, and layout property */
  position: absolute;
  width: 370px;
  height: 598px;
  top: 28px;
  left: 720px; /* open */
  -webkit-transition: all .6s ease-in-out;
}

כשהמשתמש מתחיל בוחן, הלוגיקה של JavaScript מעבירה את החלונית:

var $rightPane = $('#rightPane');
var left = $rightPane.position().left - 400;
setTimeout(function() {
  $rightPane.css('left', left + 'px');
}, 0);

כמה הערות לגבי ההטמעה הזו:

  1. מכיוון שהגדלים של האפליקציות קבועים, יכולנו להשתמש במחלקה '.close' של CSS עם קידוד קשיח של מיקום הסגירה באותו אופן שבו אנחנו מקודדים את הקוד הפתוח.
  2. יכולנו גם להשתמש ב-CSS 'Translate', שהיה יעיל יותר מהאנימציה של המאפיין 'left' של החלונית. זה נכון במיוחד למכשירים ניידים (כמו iOS) שבהם המרות בתלת-ממד מניבות האצת חומרה.
  3. במקרה הזה אין צורך בהכרח ב-setTimeout, כי המיקום המקורי הוגדר לפני השינוי. עם זאת, השינוי מאפשר לדפדפן להפוך את האנימציה לחלקה יותר על ידי הצגת הבוחן ממש לפני שמחליקים את המחוון ימינה.

2) אנימציה של תיבת הדו-שיח 'הגדרות'

כשהמשתמש לוחץ על הגדרה בצד שמאל, מופיעה תיבת הדו-שיח של ההגדרות בתחתית המסך וגולל למטה לקטע המתאים.

כדי לעשות זאת, ערכנו מעבר דומה לחלונית השמאלית. הדבר היחיד שלקח זמן הוא לפתור את הקושי בפעם הראשונה שתיבת הדו-שיח מופיעה. כדי להורות לדפדפן לשמור במטמון את ממשק המשתמש של תיבת הדו-שיח, הצגנו אותו פעם אחת וגללנו אליו. בהתחלה ניסינו עם display: none. הגישה הזו שגויה מכיוון שהדפדפן הניח שלא צריך להציג את תיבת הדו-שיח. הפתרון היה להציג את ההגדרות עם z-index: -1 באתחול, כך שהן לא גלויות למשתמשים אבל גלויות לדפדפן.

3) אנימציה של הודעה מוצלחת או הודעה שגויה

האנימציה השלישית היא למעשה שתיים בפעימה אחת. כשמופיעה ההודעה 'הצלחה' או 'שגוי', קודם כול, מגדילים את הציון, ממתינים קצת ולבסוף גדלים עוד יותר ונעלמים. לשם כך יש לנו שני סגנונות אנימציה של CSS3, ומתזמרים אותם באמצעות JavaScript באירוע webkitTransitionEnd.

.quiz-result > div.anim1 {
  opacity: 0.8;
  -webkit-transform: scale(6,6);
}
.quiz-result > div.anim2{
  opacity: 0;
  -webkit-transform: scale(9,9);
}
setTimeout(function() {
  $msg.addClass("anim1");
  $msg.bind("webkitTransitionEnd", function(){
    if ($msg.hasClass("anim1")) {
      setTimeout(function() {
        $msg.removeClass("anim1");
        $msg.addClass("anim2");
      }, 300);
    } else {
      $msg.remove();
      displayNextItem();
      freezeInput = false;
    }
  });
}, 0);

תג אודיו

כשהמשתמשים עונים על חידון, האפליקציה משמיעה הצלחה או כישלון. הבחירה הפשוטה הייתה להשתמש בתג האודיו ולהתקשר ל-play() באמצעותו. קטעי האודיו האלה מתווספים לדף הראשי של האפליקציה:

<audio id="audioCorrect" src="correct.mp3" preload="auto" autobuffer></audio>
<audio id="audioWrong" src="wrong.mp3" preload="auto" autobuffer></audio>

סיכום

HTML5 באמת מאפשר סוג חדש של אפליקציות לאינטרנט, למחשב ולנייד. ל-CSS3 היה תפקיד חשוב בהתאמה אישית של המראה והתחושה של האפליקציה כך שיתאימו עד כמה שיותר לתחכום של MathBoard ל-iPad, אחסון HTML5 היה התאמה מושלמת לשמירה על שמירת הנתונים שלנו, והפשטות של אודיו ב-HTML5 אפשרה לנו לשכפל מקרוב את האפליקציה ל-iPad.