Loading...
The Timebar plugin is an essential tool for exploring time-series data. It displays data distribution over time in the form of a timeline or trend chart, supporting time range filtering and dynamic playback interactions to help users better understand how data changes over time.
const graph = new Graph({plugins: [{type: 'timebar',data: timeData, // Time datawidth: 450, // Timebar widthheight: 60, // Timebar heightposition: 'bottom', // Positionloop: false, // Whether to loop playback},],});
createGraph({data: {nodes: new Array(25).fill(0).map((_, index) => ({id: `node-${index}`,data: {timestamp: new Date('2023-08-01').getTime() + (index % 5) * 3600 * 24 * 1000,value: index % 10,label: new Date(new Date('2023-08-01').getTime() + (index % 5) * 3600 * 24 * 1000).toLocaleString(),},})),edges: new Array(25).fill(0).map((_, i) => ({id: `edge-${i}`,source: `node-${i % 12}`,target: `node-${(i % 10) + 15}`,data: {edgeType: 'e1',},})),},layout: { type: 'grid', cols: 5 },node: {style: { size: 24, fill: '#7e3feb' },palette: { field: 'cluster' },},edge: { style: { stroke: '#8b9baf' } },behaviors: ['drag-canvas'],plugins: ['grid-line',{type: 'timebar',key: 'timebar',data: [10, 2, 3, 4, 15].map((value, index) => ({time: new Date(new Date('2023-08-01').getTime() + index * 3600 * 24 * 1000),value,label: new Date(new Date('2023-08-01').getTime() + index * 3600 * 24 * 1000).toLocaleString(),})),timebarType: 'time',height: 100,},],autoFit: 'view',padding: [10, 0, 100, 0],},{ width: 600, height: 400 },(gui, graph) => {const options = {type: 'timebar',position: 'bottom',enable: true,timebarType: 'time',className: 'g6-timebar',width: 450,height: 100,zIndex: 3,elementTypes: ['node'],mode: 'modify',loop: false,};const optionFolder = gui.addFolder('Timebar Options');optionFolder.add(options, 'type').disable(true);optionFolder.add(options, 'height', 40, 100, 1);optionFolder.add(options, 'width', 200, 800, 1);optionFolder.add(options, 'position', ['bottom', 'top']);optionFolder.add(options, 'timebarType', ['time', 'chart']);optionFolder.add(options, 'loop');optionFolder.onChange(({ property, value }) => {graph.updatePlugin({key: 'timebar',[property]: value,});graph.render();});const apiFolder = gui.addFolder('Timebar API');const instance = graph.getPluginInstance('timebar');apiFolder.add(instance, 'play');apiFolder.add(instance, 'pause');apiFolder.add(instance, 'forward');apiFolder.add(instance, 'backward');apiFolder.add(instance, 'reset');},);
Property | Description | Type | Default | Required |
---|---|---|---|---|
type | Plugin type | string | timebar | ✓ |
className | Additional class name for the toolbar DOM | string | g6-timebar | |
x | X position (invalidates position when set) | number | - | |
y | Y position (invalidates position when set) | number | - | |
width | Timebar width | number | 450 | |
height | Timebar height | number | 60 | |
position | Timebar position | bottom | top | bottom | |
padding | Padding | number | number[] | 10 | |
data | Time data | number[] | { time: number; value: number }[] | - | ✓ |
timebarType | Timebar display type | time | chart | time | |
elementTypes | Filter element types | (node | edge | combo )[] | [node ] | |
mode | Filter mode | modify | visibility | modify | |
values | Current time value | number | [number, number] | Date | [Date, Date] | - | |
loop | Whether to loop playback | boolean | false | |
getTime | Method to get element time | (datum: ElementDatum) => number | - | |
labelFormatter | Custom time formatting in chart mode | (time: number | Date) => string | - | |
onChange | Callback when time range changes | (values: number | [number, number]) => void | - | |
onReset | Callback when reset | () => void | - | |
onSpeedChange | Callback when playback speed changes | (speed: number) => void | - | |
onPlay | Callback when playback starts | () => void | - | |
onPause | Callback when paused | () => void | - | |
onBackward | Callback when backward | () => void | - | |
onForward | Callback when forward | () => void | - |
The timebarType
property controls the display type of the timebar, supporting two configurations:
time
: Display as a timeline, see Time Mode Examplechart
: Display as a trend chart, in this case the data
configuration under timebar
requires an additional value
field as chart data, see Chart Mode ExampleThe mode
property controls the element filtering method, supporting two configurations:
modify
: Filter by modifying graph datavisibility
: Filter by modifying element visibilitySimplest configuration:
const graph = new Graph({layout: { type: 'grid', cols: 5 },plugins: [{type: 'timebar',data: [{time: new Date('2023-08-01').getTime(),value: 5,},{time: new Date('2023-08-02').getTime(),value: 10,},{time: new Date('2023-08-03').getTime(),value: 15,},],},],data: {nodes: [{id: 'node1',label: 'Node 1',// By default elementTypes=['node'], so nodes need to set data.timestamp to be displayed according to the timelinedata: {timestamp: new Date('2023-08-01').getTime(),},},{id: 'node2',label: 'Node 2',data: {timestamp: new Date('2023-08-02').getTime(),},},{id: 'node3',label: 'Node 3',data: {timestamp: new Date('2023-08-03').getTime(),},},],edges: [{id: 'edge1',source: 'node1',target: 'node2',// Scenario 1: By default elementTypes = ['node']// - Edges don't need to set data.timestamp, their visibility depends on their connected nodes// Scenario 2: If elementTypes includes 'edge', e.g. elementTypes = ['node', 'edge']// - Edges must set data.timestamp to control their visibility// data: {// timestamp: new Date('2023-08-01').getTime()// }},{id: 'edge2',source: 'node2',target: 'node3',},{id: 'edge3',source: 'node3',target: 'node1',},],},});
Effect as follows:
createGraph({width: 600,height: 400,layout: { type: 'grid', cols: 5 },plugins: [{type: 'timebar',data: [{time: new Date('2023-08-01').getTime(),value: 5,},{time: new Date('2023-08-02').getTime(),value: 10,},{time: new Date('2023-08-03').getTime(),value: 15,},],},],data: {nodes: [{id: 'node1',label: 'Node 1',data: {timestamp: new Date('2023-08-01').getTime(),},},{id: 'node2',label: 'Node 2',data: {timestamp: new Date('2023-08-02').getTime(),},},{id: 'node3',label: 'Node 3',data: {timestamp: new Date('2023-08-03').getTime(),},},],edges: [{id: 'edge1',source: 'node1',target: 'node2',},{id: 'edge2',source: 'node2',target: 'node3',},{id: 'edge3',source: 'node3',target: 'node1',},],},},{ width: 600, height: 400 },);
width
, height
, padding
, and className
can customize the display effect of the timebar. Note that className
only affects the outer DOM container and cannot affect the Canvas-rendered content inside the timebar (timeline, chart, playback buttons, etc.).
const graph = new Graph({plugins: [{type: 'timebar',className: 'custom-timebar', // Note: Since content is Canvas-rendered, CSS styles cannot affect the internal contentwidth: 400, // Set timebar widthheight: 80, // Set timebar heightpadding: [20, 20, 10, 20], // Set padding [top, right, bottom, left]position: 'bottom', // Keep position at bottomdata: timeData,// labelFormatter: (time) => {// return new Date(time).toLocaleDateString();// }},],});
CSS can only style the timebar container:
.custom-timebar {background-color: #f0f0f0;border: 1px solid #ccc;border-radius: 5px;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);}
Effect as follows:
createGraph({data: () => {return {nodes: [{id: 'node1',style: { x: 100, y: 100, label: 'Node 1' },data: {timestamp: new Date('2023-08-01').getTime(),},},{id: 'node2',style: { x: 200, y: 100, label: 'Node 2' },data: {timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,},},{id: 'node3',style: { x: 150, y: 200, label: 'Node 3' },data: {timestamp: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,},},],edges: [{ id: 'edge1', source: 'node1', target: 'node2' },{ id: 'edge2', source: 'node2', target: 'node3' },{ id: 'edge3', source: 'node3', target: 'node1' },],};},node: {style: {size: 20,label: true,},},edge: {style: {stroke: '#91d5ff',lineWidth: 1,},},plugins: [{type: 'timebar',className: 'custom-timebar',width: 400,height: 80,padding: [20, 20, 10, 20],position: 'bottom',data: [{time: new Date('2023-08-01').getTime(),value: 5,},{time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000,value: 10,},{time: new Date('2023-08-01').getTime() + 3600 * 24 * 1000 * 2,value: 15,},],labelFormatter: (time) => {return new Date(time).toLocaleDateString();},},],},{ width: 600, height: 400 },(gui, graph) => {gui?.hide();const style = document.createElement('style');style.innerHTML = `.custom-timebar {background-color: #f0f0f0;border: 1px solid #ccc;border-radius: 5px;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);}`;document.head.appendChild(style);},);