Search

Multiple Time Bars

Time

Use multiple time bars to explore data.

Multiple Time Bars
View live example →

The combination of displaying a chart and a time bar simultaneously gives a user flexibility to switch between interacting with the nodes and links (and seeing their temporal distribution on the time bar) or changing the 'when' by manipulating the time bar and seeing the effect on the chart data.

This demo illustrates KeyLines' flexibility by combining two time bars with a standard chart view.

The top bar is presented without controls and shows a whole month view with granularity of a day.

The bottom bar is presented with full controls and variable sliders. It opens with a selected month to the granularity of weeks. The user is free to zoom in and out in time using the controls on the bottom bar and the top bar will automatically show a more detailed view.

Note that while the top bar has no controls it can still be interacted with – time can be dragged backwards and forwards using the top bar and the bottom bar and chart will display appropriate data.

Data set

McDiarmid, A. (Creator), Irvine, J. (Creator), Bell, S. D. (Creator), Banford, J. (Creator). (Apr 2015). Nodobo mobile phone usage data. CRAWDAD. 10.15783/C7HP4Q

Key functions used:

import KeyLines from "keylines";
import { data } from "./data.js";

let chart;
let timebar;
let timebar2;

const histogramOptions = {
  colour: "#88A6AF",
  highlightColour: "#C6524C",
};
const selectionColour = "#E2A899";

// we'll use this flag to prevent self-update changes
// from one bar to another
let isUpdating = false;
async function afterLoading() {
  await chart.layout("organic", {});
  // set initial sliders narrowed to November 2010
  timebar2.range(new Date(2010, 10, 1), new Date(2010, 11, 1), {
    animate: true,
  });
}

async function setChartRange(filterFunc) {
  await chart.filter(filterFunc, { animate: false, type: "link" });
  chart.layout("organic", { mode: "adaptive", animate: true, time: 1000 });
}

function unlockSync() {
  // We need to call it async to make it work smoothly
  setTimeout(() => {
    isUpdating = false;
  }, 20);
}
const setRanges = (origin, other) => async () => {
  if (!isUpdating) {
    isUpdating = true;
    const range = await origin.range();
    await other.range(range.dt1, range.dt2, { animate: true });
    unlockSync();
    setChartRange(origin.inRange);
  }
};

function doSelection() {
  let selection = chart.selection();
  if (selection.length > 0) {
    const neighbours = chart.graph().neighbours(selection);
    selection = selection.concat(neighbours.links);
    selection = { id: selection, c: selectionColour };
  }
  timebar.selection(selection);
  timebar2.selection(selection);
}

async function klReady(ready) {
  chart = ready[0];
  timebar = ready[1];
  timebar2 = ready[2];

  // 1. Attach the Events before loading the data

  // Sync timebars together
  timebar.on("change", setRanges(timebar, timebar2));
  timebar2.on("change", setRanges(timebar2, timebar));

  // Tell the chart to communicate the selection to the timebars
  chart.on("selection-change", doSelection);

  // 2. Now load the data

  // Be carefull when you load the data:
  // it is an expensive task, expecially with big datasets
  await timebar2.load(data);
  await timebar.load(data);
  // Load, layout and raise the flag
  await chart.load(data);
  afterLoading();
}

$(() => {
  const chartOptions = {
    logo: { u: "/public/images/Logo.png" },
    selectionColour,
    overview: { shown: false, icon: false },
  };
  const overviewOptions = {
    sliders: "free",
    histogram: histogramOptions,
    playSpeed: 20,
  };
  const detailOptions = {
    histogram: histogramOptions,
    showControlBar: false,
    scale: { showMinor: true, showMajor: false },
    sliders: "none",
  };

  KeyLines.create([
    { container: "klchart", type: "chart", options: chartOptions },
    { container: "kltimebar1", type: "timebar", options: detailOptions },
    { container: "kltimebar2", type: "timebar", options: overviewOptions },
  ]).then(klReady);
});
export const data = {
  type: "LinkChart",
  items: [
    {
      type: "node",
      c: "#c0c0c0",
      id: "9",
      t: "9",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "127",
      t: "127",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "129",
      t: "129",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "157",
      t: "157",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "192",
      t: "192",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "193",
      t: "193",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "208",
      t: "208",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "244",
      t: "244",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "372",
      t: "372",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "452",
      t: "452",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "455",
      t: "455",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "563",
      t: "563",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "901",
      t: "901",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "908",
      t: "908",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "1641",
      t: "1641",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "1740",
      t: "1740",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "2172",
      t: "2172",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "2327",
      t: "2327",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "2330",
      t: "2330",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "2367",
      t: "2367",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "2432",
      t: "2432",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "14099",
      t: "14099",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "21261",
      t: "21261",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "45347",
      t: "45347",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "2284122",
      t: "2284122",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "3305122",
      t: "3305122",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "3360769",
      t: "3360769",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "3371982",
      t: "3371982",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "3396625",
      t: "3396625",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "5505813",
      t: "5505813",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "5844903",
      t: "5844903",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "7792837",
      t: "7792837",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "8489720",
      t: "8489720",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "22400894",
      t: "22400894",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07434677419",
      t: "07434677419",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07610039694",
      t: "07610039694",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07588304495",
      t: "07588304495",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07641036117",
      t: "07641036117",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07981267897",
      t: "07981267897",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07784425582",
      t: "07784425582",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07743039441",
      t: "07743039441",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07163185791",
      t: "07163185791",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01850897526",
      t: "01850897526",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07066875066",
      t: "07066875066",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07691640598",
      t: "07691640598",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07187432175",
      t: "07187432175",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07230262224",
      t: "07230262224",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07110730864",
      t: "07110730864",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07209670163",
      t: "07209670163",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "48772130600436761996023412922286",
      t: "48772130600436761996023412922286",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07501874156",
      t: "07501874156",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07681546436",
      t: "07681546436",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07914559382",
      t: "07914559382",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07304637408",
      t: "07304637408",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07087748678",
      t: "07087748678",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07211022593",
      t: "07211022593",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01256721926",
      t: "01256721926",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07607124303",
      t: "07607124303",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07029691700",
      t: "07029691700",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07839321359",
      t: "07839321359",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07651268820",
      t: "07651268820",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01499302899",
      t: "01499302899",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07854607195",
      t: "07854607195",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07080329376",
      t: "07080329376",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07167454533",
      t: "07167454533",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07162108686",
      t: "07162108686",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07541486388",
      t: "07541486388",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07195393761",
      t: "07195393761",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01780890590",
      t: "01780890590",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07978424233",
      t: "07978424233",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07946912731",
      t: "07946912731",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07225912655",
      t: "07225912655",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07400578851",
      t: "07400578851",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01546219380",
      t: "01546219380",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07150470306",
      t: "07150470306",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07266516764",
      t: "07266516764",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07652081795",
      t: "07652081795",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07817341678",
      t: "07817341678",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07869748073",
      t: "07869748073",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07279151148",
      t: "07279151148",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07613917675",
      t: "07613917675",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07771486427",
      t: "07771486427",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07587572122",
      t: "07587572122",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "6061629169",
      t: "6061629169",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07758045718",
      t: "07758045718",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07394508492",
      t: "07394508492",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01887771702",
      t: "01887771702",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07806391587",
      t: "07806391587",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07909763438",
      t: "07909763438",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07028004429",
      t: "07028004429",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07392737002",
      t: "07392737002",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07942503106",
      t: "07942503106",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07090017672",
      t: "07090017672",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07962175133",
      t: "07962175133",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07651896055",
      t: "07651896055",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01022354521",
      t: "01022354521",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07830667924",
      t: "07830667924",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07574455931",
      t: "07574455931",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01954651441",
      t: "01954651441",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07122915122",
      t: "07122915122",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01815280008",
      t: "01815280008",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07682111000",
      t: "07682111000",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07969251842",
      t: "07969251842",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07221387474",
      t: "07221387474",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07375968743",
      t: "07375968743",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "044",
      t: "044",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07151178213",
      t: "07151178213",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07197268544",
      t: "07197268544",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07014881393",
      t: "07014881393",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07246826358",
      t: "07246826358",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07548213987",
      t: "07548213987",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "14191086749599",
      t: "14191086749599",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "14853692371599",
      t: "14853692371599",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07896182404",
      t: "07896182404",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07118310788",
      t: "07118310788",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07944968233",
      t: "07944968233",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07720520621",
      t: "07720520621",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07775682498",
      t: "07775682498",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07023552017",
      t: "07023552017",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07340142898",
      t: "07340142898",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07634569803",
      t: "07634569803",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01575974486",
      t: "01575974486",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07153234302",
      t: "07153234302",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07633839447",
      t: "07633839447",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07341891255",
      t: "07341891255",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07926168565",
      t: "07926168565",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07873904393",
      t: "07873904393",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07976349200",
      t: "07976349200",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07476886744",
      t: "07476886744",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01527646556",
      t: "01527646556",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07318250386",
      t: "07318250386",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07806980885",
      t: "07806980885",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07514503190",
      t: "07514503190",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07456622368",
      t: "07456622368",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07245763413",
      t: "07245763413",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07676963558",
      t: "07676963558",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07613569456",
      t: "07613569456",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07776253730",
      t: "07776253730",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07102745960",
      t: "07102745960",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07389444649",
      t: "07389444649",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07126482937",
      t: "07126482937",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07966846548",
      t: "07966846548",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07833688765",
      t: "07833688765",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01739521988",
      t: "01739521988",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07585377112",
      t: "07585377112",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07294484859",
      t: "07294484859",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07850316631",
      t: "07850316631",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07520192003",
      t: "07520192003",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07877889057",
      t: "07877889057",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07073084322",
      t: "07073084322",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07492710736",
      t: "07492710736",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07070949771",
      t: "07070949771",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07252637450",
      t: "07252637450",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07979079238",
      t: "07979079238",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01770637968",
      t: "01770637968",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "0126233087",
      t: "0126233087",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "01237303110",
      t: "01237303110",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "14338475884741",
      t: "14338475884741",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07873361203",
      t: "07873361203",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07189233361",
      t: "07189233361",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07497354521",
      t: "07497354521",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07541477895",
      t: "07541477895",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07690700998",
      t: "07690700998",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07351039125",
      t: "07351039125",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07529309344",
      t: "07529309344",
    },
    {
      type: "node",
      c: "#c0c0c0",
      id: "07216812571",
      t: "07216812571",
    },
    {

// ...truncated 15530 lines
<!doctype html>
<html lang="en" style="background-color: #2d383f">
  <head>
    <meta charset="utf-8" />
    <title>Multiple Time Bars</title>
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/keylines.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/minimalsdk.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/sdk-layout.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/demo.css" />
    <script src="jquery" defer type="text/javascript"></script>
  </head>
  <body>
    <div id="klchart" class="klchart klchart-timebar"></div>
    <div id="kltimebar" class="kltimebar"></div>
    <script type="module" src="./code.js"></script>
  </body>
</html>

Terms of use

These terms do not alter or supersede any existing agreements between you (or your employer) and us.

By accessing or using any Content you agree to be bound by these Terms of Use. Please review these terms carefully before using the website.

The contents of this website, including but not limited to any text, code samples, API references, schemas, interactive tools, and other materials (collectively, the 'Content'), are made available for informational and internal evaluation purposes only. All intellectual property rights in the Content are reserved. No licence is granted to use the Content for any commercial purpose, or to copy, distribute, modify, reverse-engineer, or incorporate any part of the Content into any product or service, without our prior written consent.

This Content is provided “as is” and “as available,” without any representations, warranties, or guarantees of any kind, whether express or implied, including but not limited to implied warranties of merchantability, fitness for a particular purpose, non-infringement, or accuracy. To the fullest extent permitted by applicable law, we expressly exclude and disclaim all implied warranties, conditions, and other terms that might otherwise be implied.

We disclaim all liability for any loss or damage, whether direct, indirect, incidental, consequential, or otherwise, arising from any reliance placed on the Content or from your use of it, to the fullest extent permitted by applicable law. By continuing to access or use the Content, you acknowledge and agree to these terms.