מבוא

MathBoard on iPad, אפליקציה של PalaSoftware, היא אפליקציה מבריקה עם הרבה אנימציות עדינות אך טבעיות, ומראה וסגנון ייחודיים וריאליסטיים. המטרה הייתה ליצור את ההמרה באיכות הגבוהה ביותר של אפליקציית iPad ל-HTML5.
N2N-Apps היא חברת פיתוח תוכנה שמתמקדת ביצירת אפליקציות אינטרנט ואפליקציות לנייד מדור הבא באמצעות טכנולוגיית HTML5. החברה מומנה בשנת 2010 על ידי Jeremy Chone, שבעקבות 11 שנות ניסיון בהנדסה ובניהול ב-Netscape, Oracle ו-Adobe, החליט לשתף את המומחיות שלו עם עסקים כדי ליצור אפליקציות אינטרנט ואפליקציות לנייד באיכות גבוהה. ב-N2N-Apps מתמקדים באיכות ובמהירות של העברת הנתונים.
הורדת MathBoard מחנות האינטרנט של Chrome הורדת MathBoard מחנות האינטרנט של Chrome (גרסה חינמית)
דרישות
הדרישות העיקריות לפרויקט ההעברה ל-HTML5 היו:
- גרסה באיכות גבוהה של העיצוב, הסגנון וממשק המשתמש של אפליקציית iPad המקורית.
- התאמה לגורם הצורה של היעד (כלומר, PC/Mac עם מקלדת/עכבר לעומת מסך מגע).
- להטמיע את כל התכונות הרלוונטיות.
- טירגוט בעיקר לדפדפני HTML5.
- ליצור אפליקציה 'ללא שרת', כך שהאפליקציה תפעל לגמרי בצד הלקוח ותוכל להתארח בשרת סטטי או באפליקציה ארוזת של Google Chrome.
- יצירת גרסה 1.0 עם כל התכונות, מלבד פותר הבעיות, תוך פחות מחודש.
ארכיטקטורה

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

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

בדומה לממשק של iPad, אנחנו מאפשרים למשתמש ללחוץ על החץ ימינה ושמאלה כדי לשנות את הערך של אמצעי הבקרה. אפשר גם לגרור את הקו האנכי כדי לשנות את הערכים במהירות. הופעלה התנהגות חוזרת עבור click
ו-keydown
כדי שמשתמשים יוכלו להאיץ את שינוי הערך כשהם לוחצים על העכבר או על המקלדת.
הוספנו תמיכה במקש TAB כדי לעבור משדה קלט אחד לשני, והחיצים ← ו-→ מאפשרים לעבור בין הערכים.
אחת מהתכונות בגרסה ל-iPad שלא הייתה הגיונית בממשק של המחשב הייתה לוח הציור. יכול להיות שהיה אפשר להטמיע את זה בצורה יפה, אבל ציור מספרים בעזרת עכבר לא מעשי במיוחד. במקום זאת, החלטנו להשקיע יותר זמן בשיפור ממשק המקלדת מאשר בהטמעת לוח הציור.
תכונות HTML5
בגרסה האינטרנטית של MathBoard אנחנו משתמשים בתכונות רבות של HTML5:
אחסון מקומי
ב-MathBoard, המשתמשים יכולים לשמור את המבחנים שלהם כדי להפעיל אותם מחדש מאוחר יותר. ב-HTML5 MathBoard התכונה הזו מיושמת באמצעות HTML5 localStorage
באמצעות ממשק SnowUI DAO.
localStorage
הייתה בחירה טבעית כי הנתונים היו פשוטים מספיק ולא נדרשה הוספה מתקדמת לאינדקס. אנחנו שומרים את כל הבחינות בפורמט JSON אחד, שאנחנו JSON.stringify
כטקסט.
snowUI DAO הוא מעטפת פשוטה של ממשק 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, היה קל מאוד לכלול את הגופן מסוג TrueType '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
ב-MathBoard ב-HTML5, שכפלנו את כל האנימציות של 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);
כמה הערות לגבי ההטמעה הזו:
- מכיוון שגדלי האפליקציות קבועים, היינו יכולים להשתמש בכיתה CSS '.close' ולהגדיר את מיקום הסגירה באופן קבוע בקוד, באותו אופן שבו אנחנו מגדירים באופן קבוע בקוד את מיקום הפתיחה.
- אפשר היה גם להשתמש ב-CSS 'translate', שהיה יעיל יותר מאנימציה של הנכס 'left' של החלונית. זה נכון במיוחד לגבי מכשירים ניידים (כמו iOS), שבהם טרנספורמציות תלת-ממדיות מאיצות בחומרה.
- במקרה הזה, אין צורך ב-
setTimeout
כי המיקום המקורי הוגדר לפני השינוי. עם זאת, היא מאפשרת לדפדפן להציג את הבחינה ממש לפני שהחלון הימני ייכנס, וכך להפוך את ההנפשה לחלקה יותר.
2.) אנימציה של תיבת הדו-שיח של ההגדרות
כשהמשתמש לוחץ על הגדרה בצד שמאל, תיבת הדו-שיח של ההגדרות מופיעה בחלק התחתון של המסך וגולשת למטה לקטע המתאים.
כדי לעשות זאת, ביצענו מעבר דומה לחלונית השמאלית. הדבר היחיד שלקח קצת זמן היה לפתור את התנודות בזמן ההופעה הראשונה של תיבת הדו-שיח.
כדי להורות לדפדפן לשמור במטמון את ממשק המשתמש של תיבת הדו-שיח, בסופו של דבר הצגנו אותה פעם אחת וגלשנו אליה. בהתחלה ניסינו עם display: none
.
הגישה הזו הייתה שגויה כי הדפדפן הניח שלא צריך להציג את תיבת הדו-שיח.
הפתרון היה להציג את ההגדרות באמצעות z-index: -1
במהלך האימות, כך שהן לא גלויות למשתמש אבל גלויות לדפדפן.
3.) אנימציה שגויה של הודעה על הצלחה במבחן
האנימציה השלישית היא למעשה שתי אנימציות באנימציה אחת. כשההודעה 'success' או 'incorrect' מופיעה, קודם מגדילים את ההיקף עד לנקודה מסוימת, ממתינים קצת ואז מגדילים את ההיקף עוד יותר עד שהיא נעלמת. לשם כך, יש לנו שני סגנונות אנימציה של 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.