Created a new React component based on the Recharts library (recharts.org/), which is in turn based on the D3 charting library. Recharts was selected due to its React compatibility and performance, but it soon became apparent that the provided features were insufficient, so on top of the library the following functionality was built:

  • A mini map (or brush) below the main chart that displays the entire chart at a high level (without zooming) and indicates the displayed area. The brush provided by the Recharts library only functions as a scrollbar (does not display the chart overview) and, also, it only works on intervals starting and ending at a data point (i.e. it is not possible to maintain the same visible area length when scrolling).
  • Zooming in the main chart that updates the displayed area in the mini map and trims the data so that only the displayed area is passed to the chart.
  • Scrolling in the mini map that updates the main chart and provides it with the updated chart data, according to the displayed area.
  • The X axis ticks algorithm so that ticks remain fixed relative to the overall start and end of the chart. The default mechanism places ticks depending on the provided data, which does not provide high-quality user experience.
  • The Y axis ticks algorithm that provides reasonable intervals for easy viewing according to the chart data. Again, the default Y ticks do not facilitate easy chart reading.
  • Custom Tooltips that appear for the point nearest the mouse pointer and combine point information when multiple points coincide. The default tooltips appear according to distance on the X axis and only for the first point that is found, even if multiple points coincide.

Technical highlights:

  • The chart component was written as a function component using React hooks (the new paradigm for writing React apps), using a reducer for state changes (the state is changed in a controlled fashion via commands rather than directly by the user code).
  • The chart component that accepts two axes parameters and an arbitrary number of line series along with the associated axis and data, so it is generalized for use without requiring any internal changes.
  • The main chart and mini map are synchronized in a custom way by subscribing to the provided events.
  • When zooming and dragging the main chart data is limited only to the shown points so as to increase efficiency, exploiting the fact that points are sorted on the X values. When zooming, the algorithm starts from the data array extremes and works its way inward until it locates exactly the shown data points based on the X axis values. When dragging, the algorithm starts from the shown data point indices and works its way in the direction of the scrolling until it finds the right indices for each series at the new scroll position.
  • The Y axes ticks are calculated based on some reasonable heuristics for readability. Obstacles related to floating point arithmetic and the lack of a “decimal” datatype in Javascript had to be overcome.