Skip to Content
API ReferenceTime Marks

Time Marks Example

This example demonstrates how to implement time marks (chart events) in the GoCharting SDK. Time marks appear as colored circles on the chart with hover tooltips and vertical lines.

Interactive lab

Open examples/time-marks-lab.html (from the SDK package root: npm run serve, then http://127.0.0.1:8080/examples/time-marks-lab.html ) to verify:

  • datafeed getMarks / getTimescaleMarks via onDataCallback
  • multi-line tooltips, color coding, empty/off toggles
  • marks placed in the visible range
  • live demo WebSocket bars (wss://gocharting.com/sdk/ws)

Features

  • Colored circles on the chart timeline
  • Hover tooltips with custom content
  • Vertical dashed lines on hover
  • Multi-line tooltips support
  • Custom styling options

Basic Implementation

Note

Marks are provided by the optional datafeed method getMarks(symbolInfo, startDate, endDate, onDataCallback, resolution). Marks are delivered by calling onDataCallback(marks) — not by returning them. startDate/endDate are Unix timestamps in seconds, and resolution is a string (e.g. "1D", "1m"). A companion method getTimescaleMarks(symbolInfo, startDate, endDate, onDataCallback, resolution) uses the same pattern for marks rendered on the timescale.

1. Datafeed with Time Marks

// Create a datafeed object with time marks support const myDatafeed = { async getMarks(symbolInfo, startDate, endDate, onDataCallback, resolution) { try { // Fetch time marks from your API // Note: `resolution` is a string here (e.g. "1D", "1m") const response = await fetch( `/api/timemarks?symbol=${symbolInfo.name}&from=${startDate}&to=${endDate}` ); const data = await response.json(); // Deliver the marks via onDataCallback (NOT via return) onDataCallback( data.map((mark) => ({ id: mark.id, time: mark.timestamp, // Unix timestamp in seconds color: mark.color, // 'red', 'green', 'blue', etc. text: mark.description, // Tooltip content label: mark.type, // Single character (e.g., 'E', 'N', 'M') labelFontColor: "white", minSize: 25, })) ); } catch (error) { console.error("Failed to fetch time marks:", error); onDataCallback([]); } }, // ... other required methods like getBars, resolveSymbol };

2. Chart Integration

import { createChart } from "@gocharting/chart-sdk"; const chart = createChart("#chart-container", { datafeed: new MyDataProvider(), symbol: "BTCUSDT", interval: "1h", licenseKey: "YOUR_LICENSE_KEY", });

Advanced Examples

Multi-line Tooltips

async getMarks(symbolInfo, startDate, endDate, onDataCallback, resolution) { onDataCallback([ { id: 1, time: 1757193488, color: 'red', text: [ 'Earnings Report Q3 2025', 'Expected: $1.45 EPS', 'Actual: $1.57 EPS' ], label: 'E', labelFontColor: 'white', minSize: 30 }, { id: 2, time: 1757539088, color: 'green', text: [ 'FDA Approval', 'Drug XYZ approved for market' ], label: 'N', labelFontColor: 'white', minSize: 25 } ]); }

Dynamic Color Coding

async getMarks(symbolInfo, startDate, endDate, onDataCallback, resolution) { const events = await this.fetchEvents(symbolInfo.name, startDate, endDate); onDataCallback(events.map(event => ({ id: event.id, time: event.timestamp, color: this.getEventColor(event.type), text: this.formatTooltip(event), label: event.type.charAt(0).toUpperCase(), labelFontColor: 'white', minSize: this.getEventSize(event.importance) }))); } getEventColor(eventType) { const colors = { 'earnings': '#ff4444', 'news': '#4444ff', 'dividend': '#44ff44', 'split': '#ffaa44', 'merger': '#aa44ff' }; return colors[eventType] || '#888888'; } formatTooltip(event) { return [ event.title, `Date: ${new Date(event.timestamp * 1000).toLocaleDateString()}`, event.description ]; } getEventSize(importance) { return importance === 'high' ? 35 : importance === 'medium' ? 28 : 22; }

Configuration Options

Time Mark Properties

PropertyTypeRequiredDescription
idstring|numberUnique identifier
timenumberUnix timestamp in seconds
colorstringCSS color for the circle
textstring|arrayTooltip content
labelstringSingle character label
labelFontColorstringLabel text color (default: ‘white’)
minSizenumberCircle size in pixels (default: 25)

Supported Colors

// CSS color names color: "red"; color: "green"; color: "blue"; // Hex colors color: "#ff0000"; color: "#00ff00"; color: "#0000ff"; // RGB/RGBA color: "rgb(255, 0, 0)"; color: "rgba(255, 0, 0, 0.8)";

User Interactions

Hover Behavior

  • Hover over mark → Shows tooltip + vertical dashed line
  • Move away → Hides tooltip + vertical line
  • Multiple marks → Only hovered mark shows line

Tooltip Styling

The tooltip automatically styles with:

  • White background with subtle border
  • Colored left border matching the mark
  • Clean typography with proper spacing
  • Multi-line support for arrays

Real-world Example

class CryptoDataProvider { async getMarks(symbolInfo, startDate, endDate, onDataCallback, resolution) { // Fetch major crypto events const events = await this.fetchCryptoEvents( symbolInfo.name, startDate, endDate ); onDataCallback(events.map((event) => { let color, label; switch (event.type) { case "halving": color = "#f39c12"; label = "H"; break; case "upgrade": color = "#3498db"; label = "U"; break; case "listing": color = "#2ecc71"; label = "L"; break; case "delisting": color = "#e74c3c"; label = "D"; break; default: color = "#95a5a6"; label = "N"; } return { id: event.id, time: event.timestamp, color, text: [ event.title, `Impact: ${event.impact}`, event.description, ], label, labelFontColor: "white", minSize: event.impact === "high" ? 32 : 26, }; })); } }

Troubleshooting

Common Issues

  1. Marks not appearing
  • Check that getMarks delivers valid data via onDataCallback
  • Verify timestamps are in seconds (not milliseconds)
  • Ensure marks fall within the visible time range
  1. Tooltip not showing
  • Verify text property is not empty
  • Check for JavaScript errors in console
  • Ensure mark has valid id property
  1. Vertical line not appearing
  • Confirm hover detection is working
  • Check that mark has markData property
  • Verify canvas drawing context is not corrupted

Debug Tips

// Add logging to debug time marks async getMarks(symbolInfo, startDate, endDate, onDataCallback, resolution) { const marks = await this.fetchTimeMarks(symbolInfo, startDate, endDate, resolution); console.log('Time marks loaded:', marks); onDataCallback(marks); }
Last updated on