gantt

40 阅读4分钟

基础用法

docs:Getting started gantt-schedule-timeline-calendar javascript (typescript) component

如何看到最基础的效果文档里都有。 最容易踩坑的点: 就是

xxx 前面省略一些配置
const element = document.getElementById("your-element");
// 就是传入到GSTC 中的 {}  第一个参数一定是 element, 传入 别的变量名都会报错!!! 
if(!element) throw new Error("Element not found");

// Create an instance and mount the component
const gstc = GSTC({
  element,
  state,
});

config.list.column

required key:

  • id
  • data
  • width
  • header

image.png

const columnsFromDB = [
  {
    id: 'id',
    // row 这里应该获取的是本条数据的记录
    data: ({ row }) => GSTC.api.sourceID(row.id), // show original id (not internal GSTCID)
    // sortable  用于排序,类似于table 中的点击表头,排序的那种效果!!
    sortable: ({ row }) => Number(GSTC.api.sourceID(row.id)), // sort by id converted to number
    width: 80,
    header: {
      content: 'ID', // 类似于 table组件 column label|name
    },
  },
  {
    id: 'label',
    data: 'label',
    sortable: 'label',
    isHTML: false,
    width: 230,
    header: {
      content: 'Label',
    },
  },
];

config.list.rows

required key:

  • id

image.png 两种写法:一种数组,类似于table data,这时候id可以直接传数字, 一种是传入一个对象,然后key 就是 GSTCID('id')[必须是这个格式],value包含{id|GSTCID('id'),label}

one:
{
   // row with source ID === '1'
   [GSTCID('123')]: {
     id: 123, // 这里的id可以是数字123以及GSTCID('123')
     label: 'Row 122',// 非必需属性
   },
 },
 
 two:
const rowsFromDB = [
  {
    id: "1",
    label: "Row 1",
  },
  {
    id: "2",
    label: "Row 2",
  },
];

config.chart.time

image.png

image.png // calculatedZoomMode: true, 表示跟随可视区的resize事件去显示不同的calendar title

image.png

image.png

config.chart.calendarLevels

image.png

image.png 时间跨度由下面的period字段去设定!!!

image.png

const calendarLevel0 = [
  {
    zoomTo: 16,
    period: 'hour',
    main: true,
    periodIncrement: 1,
    format({ timeStart }) {
      return timeStart.format('HH:mm');
    },
  },
  {
    zoomTo: 17,
    period: 'hour',
    main: true,
    periodIncrement: 1,
    format({ timeStart }) {
      return timeStart.format('HH');
    },
  },
  {
    zoomTo: 19,
    period: 'day',
    main: true,
    periodIncrement: 1,
    classNames: ['gstc-date-medium'],
    format({ timeStart, className, vido }) {
      return vido.html`<span class="${className}-content gstc-date-bold">${timeStart.format(
        'DD'
      )}</span> <span class="${className}-content gstc-date-thin">${timeStart.format('dddd')}</span>`;
    },
  },
  {
    zoomTo: 20,
    period: 'day',
    main: true,
    periodIncrement: 1,
    format({ timeStart, vido, className }) {
      return vido.html`<div class="${className}-content gstc-date-top">${timeStart.format(
        'DD'
      )}</div><div class="${className}-content gstc-date-small">${timeStart.format('dddd')}</div>`;
    },
  },
  {
    zoomTo: 21,
    period: 'day',
    main: true,
    periodIncrement: 1,
    format({ timeStart, vido, className }) {
      return vido.html`<div class="${className}-content gstc-date-top">${timeStart.format(
        'DD'
      )}</div><div class="${className}-content gstc-date-small">${timeStart.format('ddd')}</div>`;
    },
  },
  {
    zoomTo: 22,
    period: 'day',
    main: true,
    periodIncrement: 1,
    classNames: ['gstc-date-vertical'],
    format({ timeStart, className, vido }) {
      return vido.html`<div class="${className}-content gstc-date-top">${timeStart.format(
        'DD'
      )}</div><div class="${className}-content gstc-date-extra-small">${timeStart.format('ddd')}</div>`;
    },
  },
  {
    zoomTo: 23,
    period: 'week',
    main: true,
    periodIncrement: 1,
    format({ timeStart, timeEnd, className, vido }) {
      return vido.html`<div class="${className}-content gstc-date-top">${timeStart.format('DD')} - ${timeEnd.format(
        'DD'
      )}</div><div class="${className}-content gstc-date-small gstc-date-thin">${timeStart.format(
        'ddd'
      )} - ${timeEnd.format('dd')}</div>`;
    },
  },
  {
    zoomTo: 25,
    period: 'week',
    main: true,
    periodIncrement: 1,
    classNames: ['gstc-date-vertical'],
    format({ timeStart, timeEnd, className, vido }) {
      return vido.html`<div class="${className}-content gstc-date-top gstc-date-small gstc-date-normal">${timeStart.format(
        'DD'
      )}</div><div class="gstc-dash gstc-date-small">-</div><div class="${className}-content gstc-date-small gstc-date-normal">${timeEnd.format(
        'DD'
      )}</div>`;
    },
  },
  {
    zoomTo: 26,
    period: 'month',
    main: true,
    periodIncrement: 1,
    classNames: ['gstc-date-month-level-1'],
    format({ timeStart, vido, className }) {
      return vido.html`<div class="${className}-content gstc-date-top">${timeStart.format(
        'MMM'
      )}</div><div class="${className}-content gstc-date-small gstc-date-bottom">${timeStart.format('MM')}</div>`;
    },
  },
  {
    zoomTo: 27,
    period: 'month',
    main: true,
    periodIncrement: 1,
    classNames: ['gstc-date-vertical'],
    format({ timeStart, className, vido }) {
      return vido.html`<div class="${className}-content gstc-date-top">${timeStart.format(
        'MM'
      )}</div><div class="${className}-content gstc-date-extra-small">${timeStart.format('MMM')}</div>`;
    },
  },
  {
    zoomTo: 28,
    period: 'year',
    main: true,
    periodIncrement: 1,
    classNames: ['gstc-date-big'],
    format({ timeStart }) {
      return timeStart.format('YYYY');
    },
  },
  {
    zoomTo: 29,
    period: 'year',
    main: true,
    periodIncrement: 1,
    classNames: ['gstc-date-medium'],
    format({ timeStart }) {
      return timeStart.format('YYYY');
    },
  },
  {
    zoomTo: 30,
    period: 'year',
    main: true,
    periodIncrement: 1,
    classNames: ['gstc-date-medium'],
    format({ timeStart }) {
      return timeStart.format('YY');
    },
  },
  {
    zoomTo: 100,
    period: 'year',
    main: true,
    periodIncrement: 1,
    format() {
      return null;
    },
  },
];
const calendarLevels = [calendarLevel0];

config.chart.gird

image.png 动态添加 row 会触发这个方法!!!

config.chart.items

required key:

  • id
  • rowId
  • label
  • time

image.png 【需要注意的是 items 的key 跟 rows的key对应,如下, 就表示该条item数据会出现在对应key的那一行中!!!】


chart: {
  items: {
    // item with source ID === '1'
    [GSTCID('1234')]: {
      id: GSTCID('1234'),
      rowId: GSTCID('1234'),
      label: 'Item 1',
      time: {
        start: date('2020-01-01').valueOf(),
        end: date('2020-01-02').endOf('day').valueOf(),
        },
      },
    },
  },

image.png

image.png

image.png

image.png

config.list.sort

image.png

image.png

image.png

image.png

templates

image.png

config.additionalSpace

image.png

image.png

config.templates.list

image.png image.png

//templates.list 这个里面包含了 columns 以及rows的所有的数据,比如columns 在 list.columns 配置过了:const columns = {
  data: {
    [GSTC.api.GSTCID('id')]: {
      id: GSTC.api.GSTCID('id'),
      data: ({ row }) => GSTC.api.sourceID(row.id),
      width: 80,
      sortable: ({ row }) => Number(GSTC.api.sourceID(row.id)),
      header: {
        content: 'ID',
      },
      resizer: false,
    },
    [GSTC.api.GSTCID('label')]: {
      id: GSTC.api.GSTCID('label'),
      data: 'label',
      sortable: 'label',
      expander: false,
      isHTML: false,
      width: 230,
      header: {
        content: 'Label',
      },
    },
  },
};
那么在config.templates.list 的回调函数中就可以通过listColumns接收到这个columns 数据。可以做相应的处理!!!



function listTemplate({ className, styleMap, list, listColumns, actions, slots, html, cache, vido, props }) {
  console.log(listColumns); // 这里是表头 list.columns
  console.log(list); // 这里是list.rows数据!!!
  // console.log(actions, slots, html, cache, vido, props)
  //
  const headerHeight = vido.state.get('config.headerHeight');
  return slots.html(
    'outer',
    cache(
      list.columns.percent > 0
      // percentage width of all columns (0 - 100) if 0 list will disappear (from DOM)
        ? html`
            <div class=${className} data-actions=${actions()} style=${styleMap.directive()}>
              <div
                class="list-top-content"
                style="top: ${headerHeight}px;width:100%;position:absolute;text-align:center;margin:auto;height:50px;"
              >
                top content
              </div>
              // 这里表示渲染内容区域
              ${slots.html(
                'content',
                listColumns.map((c) => c.html())
              )}
              <span style="color:blue">test12345</span>
              <div
                class="list-bottom-content"
                style="bottom:0px;width:100%;position:absolute;text-align:center;margin: auto;height:65px"
              >
                bottom content
              </div>
            </div>
          `
        : ''
    )
  );
}

config.templates.chart

image.png

function chartTemplate({
  className,
  onWheel,
  ChartCalendar,
  ChartTimeline,
  ScrollBarVertical,
  calculatedZoomMode,
  ScrollBarHorizontal,
  actions,
  slots,
  html,
  vido,
  props,
}) {
  const headerHeight = vido.state.get('config.headerHeight');
  topContentStyle.style.top = headerHeight + 'px';
  const time = state.get('$data.chart.time');
  const mainLevel = time.levels[time.level];
  
  // 假如日期是 01号 到 08号
  // time.levels 这里是一个数组【length == 2  => [arr1,arr2]】, arr1表示当前chart可视区域这个整体,arr1[0].currentView.with==当前chart可视区域的宽度,arr2 表示可视区域的所有日期单元格,如果可视区域没有,那么arr2 就是所有的单元格的集合,可视区域有四个,那么就是这四个日期的集合【通过resize 事件可以看到】
  
  //calculatedZoomMode  false => 需要水平滚动条ScrollBarHorizontal.html()
  
  return slots.html(
    'outer',
    html`
      <div class=${className} data-actions=${actions()} @wheel=${onWheel}>
        <div class="chart-top-content" style="${topContentStyle.directive()}">
          ${mainLevel
            ? mainLevel.map(
                (date) =>
                  html`<div
                    style="width: ${date.currentView
                      .width}px; border-right:1px solid #d5d9dc; overflow:hidden;text-align:center;color:#747a81;border-top:1px solid #d5d9dc;padding-top:10px"
                  >
                    ${date.leftGlobalDate.format('DD')}<br />
                    content
                  </div>`
              )
            : null}
        </div>
        ${slots.html(
          'content',
          html`
            ${ChartCalendar.html()}${ChartTimeline.html()}${ScrollBarVertical.html()}
            // 这里的secondLevel,就是给timeLine区域预留的,这也说明了 渲染顺序是 chart-calendar template =》 chart template? 
            <div class="second-level-copy">${secondLevel ? secondLevel.map((date) => date.html()) : null}</div>
            ${calculatedZoomMode ? null : ScrollBarHorizontal.html()}
          `
        )}
      </div>
    `
  );
}

【如图,这里time.levels[1] == 3 因为chart 可视区域就是就是三天!!!】 image.png

config.templates.chart.calendar

image.png

function chartCalendarTemplate({ className, styleMap, components, actions, slots, html, vido, props }) {
  // console.log(className,components, vido, props );
  // component 也是两个数组[arr1, arr2]  arr1=》表示当前整个currentView,里面的width就是当前可视区calendar的宽度, leftGlobalDate 是可视区的start date, rightGlobalDate 是可视区的 end date。 比如 可视区是01-05, 那么leftGlobalDate.$D == 1  rightGlobalDate.$D == 5
  return slots.html(
    'outer',
    html`
      <div class=${className} data-actions=${actions()} style=${styleMap.directive()}>
        ${slots.html(
          'inner',
          components.length
            ? components.map((component, level) => {
                if (level === 1) {
                  // component 是可视区的里的date 集合
                  secondLevel = component;
                  // 这里将component 赋值给外部变量。 让日期可以自定义位置,默认日期都是在top, 这里将component赋值给secondLevel后,可以在bottom 去渲染日期list
                  return html`<div>Dates moved to the bottom</div>`;
                }
                // level == 0  表示整个可视区
                return component && component.length
                  ? html`
                     <div style="color:blue">test where</div>
                      <div class=${className + '-dates ' + className + `-dates--level-${level}`}>
                        ${slots.html(
                          'content',
                          component.map((m) => { console.log(m.html() ); return m.html()})
                        )}
                      </div>
                    `
                  : null;
              })
            : null
        )}
      </div>
    `
  );
}

image.png

image.png

config.actions

 actions: {
    'chart-timeline-items-row-item': [itemAction],
    'list-column-row': [rowAction],
    'chart-calendar-date': [dateAction],
  },

image.png 【并且这些事件会在render 的时候就触发!!!主要接收两个参数,一个就是对应的element元素,第二个就是对应的那一个单元格的数据】

config.slots

  • config.slots.main {outer, content}

    • outer
      • image.png

      • tooltip event

      • 待补充

    • 待补充
  • config.slots.'chart-timeline-items-row-item'

    • outer

    • inner

    • content

      • image.png

image.png