Custom Spreadsheet Overlays

Posted by: fontana on 21 October 2025, 4:42 pm EST

  • Posted 21 October 2025, 4:42 pm EST

    Are there any APIs available to be able to draw custom overlays on top of cell ranges, full columns, and full rows? Custom Cells have access to the canvas context through the paint() method to draw the cell’s content. Is there any similar API that give us the power to do this?

  • Posted 22 October 2025, 2:31 am EST

    Hi,

    There isn’t a built-in API to directly draw custom overlays on cell ranges, full columns, or rows. However, this can be implemented using a “FloatingObject” overlay. By dynamically calculating the pixel dimensions of the target range and positioning a floating object over it, you can create a custom semi-transparent overlay (or even use a canvas for custom drawings). The overlay can be fixed in position and size, and updated whenever required.

    Here’s a working sample snippet that demonstrates this approach:

    var overlay = addRangeOverlay(sheet, { row: 0, col: 0, rowCount: 3, colCount: 2 }, "myOverlay");
    
    // Function to create a range overlay
    function addRangeOverlay(sheet, range, id) {
      id = id || ("overlay_" + Date.now());
    
      function getRangeRect(s, r) {
        var top = 0, left = 0, width = 0, height = 0;
        for (var rr = 0; rr < r.row; rr++) top += s.getRowHeight(rr);
        for (var cc = 0; cc < r.col; cc++) left += s.getColumnWidth(cc);
        for (var rr = r.row; rr < r.row + r.rowCount; rr++) height += s.getRowHeight(rr);
        for (var cc = r.col; cc < r.col + r.colCount; cc++) width += s.getColumnWidth(cc);
        return { x: left, y: top, width: width, height: height };
      }
    
      var rect = getRangeRect(sheet, range);
    
      var floatObj = new GC.Spread.Sheets.FloatingObjects.FloatingObject(id, rect.x, rect.y, rect.width, rect.height);
      var container = document.createElement("div");
      container.style.width = "100%";
      container.style.height = "100%";
      container.style.pointerEvents = "none";
      container.style.boxSizing = "border-box";
      container.style.background = "rgba(255, 230, 0, 0.25)";
      
      floatObj.content(container);
      floatObj.allowResize(false);
      floatObj.allowMove(false);
      sheet.floatingObjects.add(floatObj);
    
      function updateOverlay() {
        var newRect = getRangeRect(sheet, range);
        floatObj.x(newRect.x);
        floatObj.y(newRect.y);
        floatObj.width(newRect.width);
        floatObj.height(newRect.height);
      }
    
      return {
        id: id,
        remove: function () {
          try { sheet.floatingObjects.remove(floatObj); } catch (e) { }
        },
        update: updateOverlay,
        element: container,
        floatObj: floatObj
      };
    }

    Sample: https://jscodemine.mescius.io/share/HE7UQTZQMUaKLyg3-jqvfQ/?IsEmbed=false&Theme=Unset&PreviewDirection=0&IsEditorShow=true&IsExplorerShow=true&IsPreviewShow=true&IsConsoleShow=true&IsRunBTNShow=false&IsResetBTNShow=false&IsOpenInCodemineBTNShow=false&PanelWidth=20&PanelWidth=50&PanelWidth=30&defaultOpen={"OpenedFileName"%3A["%2Findex.html"%2C"%2Fsrc%2Fdata.js"%2C"%2Fsrc%2Fapp.js"%2C"%2Fpackage.json"]%2C"ActiveFile"%3A"%2Fsrc%2Fapp.js"}

    This approach allows you to overlay visual elements across cell ranges, full rows, or columns, without modifying the underlying data.

    References:

    Regards,

    Priyam

  • Posted 22 October 2025, 10:35 am EST

    Thanks for the quick reply. Unfortunately, this makes the canvas loose all its functionality. We can no longer select cells behind the overlay. Also, this may not scale well for drawing hundreds of overlays.

  • Posted 23 October 2025, 5:29 am EST

    Hi,

    You’re correct — using floating objects or DOM elements for overlays can interfere with cell interaction (selection, editing) and may not scale efficiently with many overlays.

    A more flexible approach is to use a custom canvas overlay layered on top of the sheet. This method allows you to:

    • Draw highlights, ranges, full rows, or columns using the canvas 2D API.
    • Keep underlying cells fully interactive (selection, editing, scrolling).
    • Scale efficiently even with many overlays since you’re just drawing on a single canvas.

    Key points of this approach:

    1. Canvas placement: Insert a element as a child of the SpreadJS host element and set pointer-events: none so it doesn’t block mouse interactions.
    2. Range calculation: Use sheet.getCellRect(row, col) to get the exact x/y coordinates and width/height of each cell or range. For full rows or columns, calculate the rect based on row/column bounds.
    3. Dynamic redraw: Bind to relevant SpreadJS events (ViewZoomed, TopRowChanged, LeftColumnChanged, SheetTabChanged) to redraw overlays whenever the viewport or zoom changes.
    4. Optional per-sheet overlays: Include a sheetName property in your overlay objects and only draw overlays matching the active sheet.

    Here’s a simplified example of how overlays can be drawn on a canvas without blocking cell interactions:

    overlays.forEach(o => {
      if (o.sheetName && o.sheetName !== sheet.name()) return;
      const rect = sheet.getCellRect(o.row, o.col);
      ctx.fillStyle = o.fill || "rgba(255,230,0,0.25)";
      ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
    });

    This approach keeps the sheet fully interactive, supports zoom and scroll, and performs well even with dozens or hundreds of overlays.

    For a working demo and detailed implementation, you can refer to this sample: https://jscodemine.mescius.io/share/rICrkv4ueka4MqLNAnhBpA/?IsEmbed=false&Theme=Unset&PreviewDirection=0&IsEditorShow=true&IsExplorerShow=true&IsPreviewShow=true&IsConsoleShow=true&IsRunBTNShow=false&IsResetBTNShow=false&IsOpenInCodemineBTNShow=false&PanelWidth=20&PanelWidth=50&PanelWidth=30&defaultOpen={"OpenedFileName"%3A["%2Findex.html"%2C"%2Fsrc%2Fapp.js"]%2C"ActiveFile"%3A"%2Fsrc%2Fapp.js"}

    However, please note that the provided sample is for demonstration purposes only and may not cover all scenarios. It can be used as a reference to create a solution tailored to your specific requirements.

    References:

    Regards,

    Priyam

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels