פיתוח צירי זמן אינטראקטיביים לאתר
תארו לעצמכם: בדף ההיסטוריה של חברה, אירועים נטענים בסדר שגוי—מאוחרים קודם, מוקדמים אחר כך, וחלק מהתאריכים לא מופיעים כלל. ב-80% מהמקרים, זה קורה בגלל חוסר מיון בצד הלקוח. הלקוח רואה כאוס, לא כרונולוגיה. זו בעיה נפוצה שאנחנו פותרים עם צירי זמן מעוצבים כראוי: אינטראקטיביים, רספונסיביים, עם קישור נתונים ברור. המהנדסים שלנו עבדו עם React במשך יותר מ-8 שנים וניסו עשרות גישות כדי למצוא את האופטימליות. אנחנו עוזרים לחברות להמחיש היסטוריית פרויקטים, שלבי פיתוח או עדכוני חדשות—עם תצוגה נכונה מובטחת בכל מכשיר. אם אתם מתמודדים עם בעיה דומה, צרו קשר לייעוץ.
בעיות שאנחנו פותרים
סדר אירועים לא דטרמיניסטי
לעתים קרובות נתונים מגיעים בסדר אקראי, וצד הלקוח לא ממיין אותם. אנחנו תמיד מיישמים DataSet מ-vis-timeline או ממיינים ברמת המערך: events.sort((a,b) => a.date - b.date). ללא עיבוד זה, ציר הזמן מציג שטויות אפילו עם 100 אירועים.
קנה מידה שגוי
אם לציר הזמן אין אילוצי zoomMin ו-zoomMax, משתמשים יכולים להתקרב לרמות מיקרו או מאקרו שבהן הנתונים הופכים לחסרי משמעות. ב-vis-timeline, אנו מגדירים מגבלות: מינימום יום אחד, מקסימום שנה אחת לצירי זמן של פרויקטים. זה שומר על קריאות גם עם 10,000 אירועים.
חוסר רספונסיביות
צירי זמן אנכיים נשברים לעתים קרובות במובייל. אנו משתמשים ב-CSS Flexbox ו-media queries, ובמקרים מורכבים, בספריית react-chrono עם התמיכה המובנית שלה במובייל. אנו בודקים ברזולוציות מ-320px עד 1920px.
איך אנחנו עושים את זה: סטאק ומקרה מהפרקטיקה שלנו
עבור אחד הלקוחות שלנו, היינו צריכים ציר זמן עם גרירה ושחרור, קיבוץ לפי צוותים, ואינטגרציה עם משימות Jira. בחרנו ב-vis-timeline — ספרייה עם ביצועים מוכחים.
npm install vis-timeline vis-data יצרנו DataSet לפריטים וקבוצות, הגדרנו לוקליזציה לרוסית, קבענו טווח מ--7 עד +30 ימים מהיום—ספרינטים טיפוסיים. חשוב, הוספנו handler של npm install vis-timeline vis-data כך שלחיצה על אירוע פותחת את כרטיס המשימה.
import { useEffect, useRef } from 'react';
import { Timeline, DataSet } from 'vis-timeline/standalone';
import 'vis-timeline/styles/vis-timeline-graph2d.css';
function ProjectTimeline({ events, groups }) {
const containerRef = useRef<HTMLDivElement>(null);
const timelineRef = useRef<Timeline>();
useEffect(() => {
if (!containerRef.current) return;
const items = new DataSet(events.map(e => ({
id: e.id,
group: e.groupId,
content: `<div class="timeline-item">${e.title}</div>`,
start: e.startDate,
end: e.endDate,
className: `status-${e.status}`
})));
const groupsDS = new DataSet(groups.map(g => ({
id: g.id,
content: g.name
})));
const timeline = new Timeline(containerRef.current, items, groupsDS, {
start: new Date(Date.now() - 7 * 24 * 3600000),
end: new Date(Date.now() + 30 * 24 * 3600000),
height: '400px',
locale: 'ru',
groupOrder: 'id',
zoomMin: 1000 * 60 * 60 * 24, // минимум 1 день
zoomMax: 1000 * 60 * 60 * 24 * 365 // максимум 1 год
});
timeline.on('select', ({ items: selectedIds }) => {
if (selectedIds.length > 0) {
const item = events.find(e => e.id === selectedIds[0]);
onEventSelect(item);
}
});
timelineRef.current = timeline;
return () => timeline.destroy();
}, []);
return <div ref={containerRef} />;
} השוואת ספריות ציר זמן
| פרמטר | vis-timeline | react-chrono | Framer Motion (מותאם אישית) |
|---|---|---|---|
| סוג | אופקי, קבוצות, גרירה ושחרור | אנכי, תמונות, אנימציה | כל סוג, שליטה מלאה |
| אינטראקטיביות | גבוהה (זום, בחירה, עריכה) | בינונית (תצוגה בלבד) | מלאה (לוגיקה מותאמת אישית) |
| מורכבות אינטגרציה | בינונית | נמוכה | גבוהה |
| רספונסיביות | ניתנת להגדרה | מובנית | ניתנת להגדרה |
| גודל חבילה | ~200 KB | ~30 KB | ~10 KB (Framer Motion בלבד) |
| ביצועים (אירועים) | 10,000+ ב-2 שניות | 500 ב-3 שניות | ללא הגבלה |
vis-timeline מתמודד עם עד 10,000 אירועים ללא אובדן ביצועים, בעוד ש-react-chrono מתחיל לפגר אחרי 500—הפרש של פי 20. פתרון מותאם אישית על Framer Motion אין לו מגבלות כאלה, אבל דורש פי 3 יותר זמן פיתוח.
באיזו ספרייה לבחור לציר זמן?
אם אתם צריכים ציר זמן מתקדם עם קיבוץ וקנה מידה, השתמשו ב-vis-timeline. אם עדכון אירועים אנכי ויפה מספיק, השתמשו ב-react-chrono. אם אתם צריכים עיצוב ייחודי ואנימציות, לכו על פתרון מותאם אישית עם Framer Motion. אנחנו יכולים לשלב אותם: למשל, vis-timeline לציר הזמן הראשי ו-react-chrono לחלון קופץ עם פרטים.
למה רכיבי React עדיפים על פני תוספים מוכנים?
תוספים מוכנים (למשל, צירי זמן jQuery) לא משתלבים עם סטאקים מודרניים: אין טיפוסיות, קשה לשימוש חוזר, קשה לבדוק. רכיבי React: טיפוסיים, דקלרטיביים, ניתנים להטמעה בקלות ב-Next.js או Vite. אנחנו מרכיבים מהם ממשק חי שחי באותו runtime כמו שאר האפליקציה. לפי תיעוד React, ארכיטקטורת רכיבים מבודדת לוגיקה ומפשטת תחזוקה.
שלבים ולוח זמנים של העבודה
| שלב | משך | תוצאה |
|---|---|---|
| ניתוח | 1-2 ימים | מפרט טכני |
| עיצוב | יום אחד | ארכיטקטורת רכיבים |
| יישום | 2-4 ימים | רכיב עובד |
| בדיקות | יום אחד | דוח QA |
| פריסה | יום אחד | תיעוד ודוגמאות |
זמן כולל: בין 2 ל-10 ימים תלוי במורכבות. המחיר מחושב באופן אישי—צרו קשר להערכה מדויקת.
תהליך העבודה
- ניתוח — בחינת דרישות: סוגי אירועים, טווח תאריכים, צורך בקיבוץ, גרירה ושחרור.
- עיצוב — בחירת ספרייה, עיצוב רכיבים ו-props.
- יישום — כתיבת רכיב ב-React/TypeScript, חיבור נתונים, הגדרת סגנונות.
- בדיקות — בדיקה ברזולוציות שונות, דפדפנים, עם נפחי נתונים משתנים (עד 10,000 אירועים).
- פריסה — מסירת רכיב עם תיעוד ודוגמאות שימוש.
מה כלול בעבודה (תוצרים)
- קוד מקור של הרכיב ב-React/TypeScript
- תיעוד על props וסוגי נתונים
- דוגמת אינטגרציה עם REST API (סכמת JSON)
- מצבים מעוצבים: טעינה, ריק, שגיאה
- אחריות לתיקון באגים למשך 3 חודשים
טעויות נפוצות ביישום צירי זמן
- חוסר debounce בזום — ה-handler מופעל עשרות פעמים. הוסיפו
selectעם throttling. - סוגי נתונים שגויים — תאריכים חייבים להיות אובייקטי Date או מחרוזות ISO 8601, אחרת vis-timeline זורק שגיאה.
- התעלמות מלוקליזציה — אם ציר הזמן ברוסית, אל תשכחו את הפרמטר
import { useEffect, useRef } from 'react'; import { Timeline, DataSet } from 'vis-timeline/standalone'; import 'vis-timeline/styles/vis-timeline-graph2d.css'; function ProjectTimeline({ events, groups }) { const containerRef = useRef<HTMLDivElement>(null); const timelineRef = useRef<Timeline>(); useEffect(() => { if (!containerRef.current) return; const items = new DataSet(events.map(e => ({ id: e.id, group: e.groupId, content: `<div class="timeline-item">${e.title}</div>`, start: e.startDate, end: e.endDate, className: `status-${e.status}` }))); const groupsDS = new DataSet(groups.map(g => ({ id: g.id, content: g.name }))); const timeline = new Timeline(containerRef.current, items, groupsDS, { start: new Date(Date.now() - 7 * 24 * 3600000), end: new Date(Date.now() + 30 * 24 * 3600000), height: '400px', locale: 'ru', groupOrder: 'id', zoomMin: 1000 * 60 * 60 * 24, // минимум 1 день zoomMax: 1000 * 60 * 60 * 24 * 365 // максимум 1 год }); timeline.on('select', ({ items: selectedIds }) => { if (selectedIds.length > 0) { const item = events.find(e => e.id === selectedIds[0]); onEventSelect(item); } }); timelineRef.current = timeline; return () => timeline.destroy(); }, []); return <div ref={containerRef} />; }, אחרת החודשים יהיו באנגלית.
הגדרת לוקליזציה של Vis-timeline
locale: 'ru', locales: { ru: { current: 'Текущее время', time: 'Время', } } דוגמה זו מראה כיצד להוסיף תוויות ברוסית.
הזמינו פיתוח ציר זמן עוד היום—קבלו ייעוץ מהנדס תוך יום אחד. לפרויקטים מורכבים, אנו ממליצים להזמין פיתוח מותאם אישית כדי לקחת בחשבון את כל הניואנסים.







