SciChart.js JavaScript 3D Charts API > ChartModifier 3D API > Tooltips > Tooltip Modifier 3D
Tooltip Modifier 3D

Tooltips in SciChart.js 3D are performed by the TooltipModifier3D. This is a ChartModifierBase3D derived type which executes on touch over the data point and shows tooltips for the data-points under the mouse.

Declaring a TooltipModifier3D

Declaring a TooltipModifier3D is as simple as adding one to the SciChart3DSurface.chartModifiers property. This can be done as a single modifier, or as part of a group.

// Declare a tooltip and add to the chart like this.
// Optional parameters help define tooltip operation
const tooltipModifier = new TooltipModifier3D({
    isCrosshairVisible: true,
    isTooltipVisible: true,
    crosshairStroke: "#83D2F5",
    crosshairStrokeThickness: 3,
    tooltipContainerBackground: "#537ABD",
    tooltipTextStroke: "White",
    tooltipLegendOffsetX: 10,
    tooltipLegendOffsetY: 10
  });

sciChart3DSurface.chartModifiers.add(tooltipModifier);

This results in the following behaviour added to the chart.

<div class="wrapper">
    <div id="scichart-root" ></div>
    <div class="titleWrapper">
        <p class="title">SciChart.js 3D Chart Example</p>
        <p class="subTitle">Hover the points to see tooltips</p>
    </div>
</div>

  
body { margin: 0; font-family: Arial; }
.wrapper { width: 100%; height: 100vh; position: relative; }
#scichart-root { width: 100%; height: 100%; position: relative; }
.titleWrapper { position: absolute; width: 100%; top: 35%; text-align: center; pointer-events: none; color: #ffffff77 }
.title { font-size: 20px; }
.subTitle {  font-size: 16px; }

  
async function tooltips3D(divElementId) {
  const {
    SciChart3DSurface,
    NumericAxis3D,
    Vector3,
    SciChartJsNavyTheme,
    EAutoRange,
    NumberRange,
    SpherePointMarker3D,
    ScatterRenderableSeries3D,
    XyzDataSeries3D,
    SurfaceMeshRenderableSeries3D,
    UniformGridDataSeries3D,
    GradientColorPalette,
    PointLineRenderableSeries3D,
    EDrawMeshAs,
    TooltipModifier3D,
    EMeshPaletteMode
  } = SciChart;

  // or, for npm, import { SciChart3DSurface, ... } from "scichart"

  // Create a SciChart3DSurface in the host <div id=".." />
  const { wasmContext, sciChart3DSurface } = await SciChart3DSurface.create(divElementId, {
    theme: new SciChartJsNavyTheme(),
    worldDimensions: new Vector3(300, 200, 300),
    cameraOptions: {
      position: new Vector3(-300, 300, 300),
      target: new Vector3(0, 50, 0),
    }
  });

  sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, {
    axisTitle: "X Axis",
    visibleRange: new NumberRange(0, 10),
    autoRange: EAutoRange.Never
  });
  sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, {
    axisTitle: "Y Axis",
    visibleRange: new NumberRange(0, 10),
    autoRange: EAutoRange.Never
  });
  sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, {
    axisTitle: "Z Axis",
    visibleRange: new NumberRange(0, 10),
    autoRange: EAutoRange.Never
  });

  sciChart3DSurface.renderableSeries.add(
    new ScatterRenderableSeries3D(wasmContext, {
      pointMarker: new SpherePointMarker3D(wasmContext, { size: 10, fill: "#FF6600" }),
      dataSeries: new XyzDataSeries3D(wasmContext, {
        xValues: [4, 4.1, 4.3],
        yValues: [4, 4.1, 4.3],
        zValues: [4, 4.1, 4.3],
        dataSeriesName: "Orange"
      })
    })
  );

  sciChart3DSurface.renderableSeries.add(
    new ScatterRenderableSeries3D(wasmContext, {
      pointMarker: new SpherePointMarker3D(wasmContext, { size: 10, fill: "#33AAFF" }),
      dataSeries: new XyzDataSeries3D(wasmContext, {
        xValues: [5, 5.1, 5.3],
        yValues: [5, 5.1, 5.3],
        zValues: [5, 5.1, 5.3],
        dataSeriesName: "Blue"
      })
    })
  );

  sciChart3DSurface.renderableSeries.add(
    new ScatterRenderableSeries3D(wasmContext, {
      pointMarker: new SpherePointMarker3D(wasmContext, { size: 10, fill: "#00FF00" }),
      dataSeries: new XyzDataSeries3D(wasmContext, {
        xValues: [6, 6.1, 6.3],
        yValues: [6, 6.1, 6.3],
        zValues: [6, 6.1, 6.3],
        dataSeriesName: "Green"
      })
    })
  );

  sciChart3DSurface.renderableSeries.add(
    new SurfaceMeshRenderableSeries3D(wasmContext, {
      dataSeries: new UniformGridDataSeries3D(wasmContext, {
        xStart: 5,
        zStart: 5,
        yValues: [
          [0.1, 0.4, 0.4, 0.2, 0.8],
          [0.6, 0.4, 0.6, 0.1, 0.7],
          [0.2, 0.4, 0.3, 0.4, 0.0],
          [0.6, 0.4, 0.6, 0.1, 0.7],
          [0.1, 0.4, 0.4, 0.2, 0.8],
        ],
        dataSeriesName: "Surface mesh"
      }),
      meshColorPalette: new GradientColorPalette(wasmContext, {
        gradientStops: [
          {offset: 1, color: "#EC0F6C"}, // yValues >= maximum mapped to this color
          {offset: 0.55, color: "#F48420"},
          {offset: 0.3, color: "#67BDAF"},
          {offset: 0.2, color: "#50C7E0"},
          {offset: 0.1, color: "#264B93"},
          {offset: 0, color: "#14233C"}  // yValues <= minimum mapped to this color
        ]
      }),
      minimum: 0,
      maximum: 1,
      opacity: 0.77,
      drawSkirt: false,
      stroke: "White",
      strokeThickness: 1.5,
      lightingFactor: 0.2,
      meshPaletteMode: EMeshPaletteMode.HEIGHT_MAP_SOLID_CELLS,
      drawMeshAs: EDrawMeshAs.SOLID_WIREFRAME
    })
  );

  sciChart3DSurface.renderableSeries.add(
    new PointLineRenderableSeries3D(wasmContext, {
      stroke: "#E4F5FC",
      dataSeries: new XyzDataSeries3D(wasmContext, {
        dataSeriesName: "PointLine 3D",
        xValues: [0, 0, 0, 0, 0],
        yValues: [6, 6.1, 6.3, 5.5, 6.0],
        zValues: [2, 4, 6, 8, 10]
      }),
      pointMarker: new SpherePointMarker3D(wasmContext, { size: 10, fill: "#00FF00" })
    })
  );

  // #region ExampleA
  // Declare a tooltip and add to the chart like this.
  // Optional parameters help define tooltip operation
  const tooltipModifier = new TooltipModifier3D({
      isCrosshairVisible: true,
      isTooltipVisible: true,
      crosshairStroke: "#83D2F5",
      crosshairStrokeThickness: 3,
      tooltipContainerBackground: "#537ABD",
      tooltipTextStroke: "White",
      tooltipLegendOffsetX: 10,
      tooltipLegendOffsetY: 10
    });

  sciChart3DSurface.chartModifiers.add(tooltipModifier);
  // #endregion
};

tooltips3D("scichart-root");

  

Styling the Tooltip Output

Properties which affect Tooltip style

Some simple properties which affect the tooltip style are:

Property Description
isCrosshairVisible When true (default), a crosshair is drawn from the hovered datapoint to the far axis wall
crosshairStroke The stroke color as a Hex code of the crosshair line
crosshairStrokeThickness The stroke thickness of the crosshair line
tooltipContainerBackground The background color of the tooltip container as a Hex code
tooltipLegendOffsetX / Y Offset in pixels of the tooltip from the hovered datapoint
tooltipTextStroke The text color on the tooltip

 

For further customisation of the tooltip content & container, read on.

Tooltip Text Formatting

Tooltips obey formatting rules on the Axis. These can be defined by setting axis.labelProvider.cursorPrecisioncursorNumericFormat or overriding formatCursorLabel. For more information on text formatting, see the LabelProvider documentation.

Modifying the Tooltip Content

You can modify the content output by tooltip via the TooltipModifier3D.tooltipDataTemplate property. This accepts a function with SeriesInfo3D and TooltipSvgAnnotation3D arguments where you can access data about the series that was hit.

Here's an example:

// Declare a tooltip and add to the chart
const tooltipModifier = new TooltipModifier3D({
    crosshairStroke: "#83D2F5",
    crosshairStrokeThickness: 3,
    tooltipContainerBackground: "#537ABD",
    tooltipTextStroke: "White",
    tooltipLegendOffsetX: 10,
    tooltipLegendOffsetY: 10
  });

sciChart3DSurface.chartModifiers.add(tooltipModifier);

// Customize the tooltip content
tooltipModifier.tooltipDataTemplate = (seriesInfo, svgAnnotation) => {
  // Create an array to hold strings (lines) to show in the tooltip
  const valuesWithLabels = [];
  if (seriesInfo && seriesInfo.isHit) {
    // You can access the renderableSeries which was hit via the seriesInfo
    const renderableSeries = seriesInfo.renderableSeries;
    // And the parent Chart from that
    const parentSurface = renderableSeries.parentSurface;

    // Push lines to the array to display in the tooltip
    valuesWithLabels.push(`dataSeriesName: "${seriesInfo.dataSeriesName}"`);
    valuesWithLabels.push(` ${parentSurface.xAxis.axisTitle}: ${seriesInfo.xValue.toFixed(2)}`);
    valuesWithLabels.push(` ${parentSurface.yAxis.axisTitle}: ${seriesInfo.yValue.toFixed(2)}`);
    valuesWithLabels.push(` ${parentSurface.zAxis.axisTitle}: ${seriesInfo.zValue.toFixed(2)}`);

    // access the metadata (if exists)". Any JS object on the data-points can be accessed
    // in tooltips
    const md = seriesInfo.pointMetadata;
    if (md) {
      valuesWithLabels.push(` Metadata: "${md.customString}"`);
    }
  }
  return valuesWithLabels;
}

This results in the following output.

<div class="wrapper">
    <div id="scichart-root" ></div>
    <div class="titleWrapper">
        <p class="title">SciChart.js 3D Chart Example</p>
        <p class="subTitle">Hover the points to see tooltips</p>
    </div>
</div>

  
body { margin: 0; font-family: Arial; }
.wrapper { width: 100%; height: 100vh; position: relative; }
#scichart-root { width: 100%; height: 100%; position: relative; }
.titleWrapper { position: absolute; width: 100%; top: 35%; text-align: center; pointer-events: none; color: #ffffff77 }
.title { font-size: 20px; }
.subTitle {  font-size: 16px; }

  
const generateData = (index) => {
  const gaussianRandom = (mean, stdev) => {
    const u = 1 - Math.random(); // Converting [0,1) to (0,1]
    const v = Math.random();
    const z = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
    // Transform to the desired mean and standard deviation:
    return z * stdev + mean;
  };

  const xValues = [];
  const yValues = [];
  const zValues = [];

  for (let i = 0; i < 30; i++) {
    xValues.push(i*0.1);
    yValues.push(gaussianRandom(0, 1));
    zValues.push(index);
  }
  return { xValues, yValues, zValues };
}

async function tooltips3DCustomisation(divElementId) {
  const {
    SciChart3DSurface,
    NumericAxis3D,
    Vector3,
    SciChartJsNavyTheme,
    NumberRange,
    XyzDataSeries3D,
    PointLineRenderableSeries3D,
    TooltipModifier3D,
    EllipsePointMarker3D,
    uintArgbColorLerp,
    parseColorToUIntArgb,
    parseArgbToHtmlColor
  } = SciChart;

  // or, for npm, import { SciChart3DSurface, ... } from "scichart"

  // Create a SciChart3DSurface in the host <div id=".." />
  const { wasmContext, sciChart3DSurface } = await SciChart3DSurface.create(divElementId, {
    theme: new SciChartJsNavyTheme(),
    worldDimensions: new Vector3(300, 200, 300),
    cameraOptions: {
      position: new Vector3(-300, 300, 300),
      target: new Vector3(0, 50, 0),
    }
  });

  const growBy = new NumberRange(0.2, 0.2);
  sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, { axisTitle: "Frequency (Hz)", growBy });
  sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, { axisTitle: "Power (dB)" });
  sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, { axisTitle: "Time (s)", growBy });

  // returns data in arrays of numbers e.g. xValues = [0,1,2,3,4], yValues = [0,1,2,3,4], zValues = [0,1,2,3,4]
  const { xValues, yValues, zValues } = generateData(1);

  // Add a PointLineRenderableSeries3D
  sciChart3DSurface.renderableSeries.add(new PointLineRenderableSeries3D(wasmContext, {
    dataSeries: new XyzDataSeries3D(wasmContext, { xValues, yValues, zValues, dataSeriesName: "Series A" }),
    opacity: 0.9,
    stroke: "#EC0F6C",
    strokeThickness: 3,
    pointMarker: new EllipsePointMarker3D(wasmContext, { size: 3 })
  }));

  // Repeat 2x
  const dataset1 = generateData(2);
  const colorHigh = parseColorToUIntArgb("#EC0F6C");
  const colorLow = parseColorToUIntArgb("#30BC9A");
  const yMin = Math.min(...yValues);
  const yMax = Math.max(...yValues);
  const metadata = dataset1.yValues.map((y, i) => {
    // interpolate y between colorLow and colorHigh using the helper function uintArgbColorLerp
    const t = (y - yMin) / (yMax - yMin);
    const color = uintArgbColorLerp(colorLow, colorHigh, t);
    return { vertexColor: color, customString: `Custom string ${i}` };
  });
  sciChart3DSurface.renderableSeries.add(new PointLineRenderableSeries3D(wasmContext, {
    dataSeries: new XyzDataSeries3D(wasmContext, { xValues: dataset1.xValues, yValues: dataset1.yValues, zValues: dataset1.zValues, metadata, dataSeriesName: "Series B" }),
    opacity: 0.9,
    stroke: "#50C7E0",
    strokeThickness: 3,
    pointMarker: new EllipsePointMarker3D(wasmContext, { size: 3 })
  }));

  const dataset2 = generateData(3);
  sciChart3DSurface.renderableSeries.add(new PointLineRenderableSeries3D(wasmContext, {
    dataSeries: new XyzDataSeries3D(wasmContext, { xValues: dataset2.xValues, yValues: dataset2.yValues, zValues: dataset2.zValues, dataSeriesName: "Series C" }),
    opacity: 0.9,
    stroke: "#F48420",
    strokeThickness: 3,
    pointMarker: new EllipsePointMarker3D(wasmContext, { size: 3 })
  }));


  // #region ExampleA
  // Declare a tooltip and add to the chart
  const tooltipModifier = new TooltipModifier3D({
      crosshairStroke: "#83D2F5",
      crosshairStrokeThickness: 3,
      tooltipContainerBackground: "#537ABD",
      tooltipTextStroke: "White",
      tooltipLegendOffsetX: 10,
      tooltipLegendOffsetY: 10
    });

  sciChart3DSurface.chartModifiers.add(tooltipModifier);

  // Customize the tooltip content
  tooltipModifier.tooltipDataTemplate = (seriesInfo, svgAnnotation) => {
    // Create an array to hold strings (lines) to show in the tooltip
    const valuesWithLabels = [];
    if (seriesInfo && seriesInfo.isHit) {
      // You can access the renderableSeries which was hit via the seriesInfo
      const renderableSeries = seriesInfo.renderableSeries;
      // And the parent Chart from that
      const parentSurface = renderableSeries.parentSurface;

      // Push lines to the array to display in the tooltip
      valuesWithLabels.push(`dataSeriesName: "${seriesInfo.dataSeriesName}"`);
      valuesWithLabels.push(` ${parentSurface.xAxis.axisTitle}: ${seriesInfo.xValue.toFixed(2)}`);
      valuesWithLabels.push(` ${parentSurface.yAxis.axisTitle}: ${seriesInfo.yValue.toFixed(2)}`);
      valuesWithLabels.push(` ${parentSurface.zAxis.axisTitle}: ${seriesInfo.zValue.toFixed(2)}`);

      // access the metadata (if exists)". Any JS object on the data-points can be accessed
      // in tooltips
      const md = seriesInfo.pointMetadata;
      if (md) {
        valuesWithLabels.push(` Metadata: "${md.customString}"`);
      }
    }
    return valuesWithLabels;
  }

  // #endregion
};

tooltips3DCustomisation("scichart-root");

  
The arguments to the tooltipDataTemplate function are SeriesInfo3D and TooltipSvgAnnotation3D. You can access any info about the series, parent chart or axis from SeriesInfo3D. Inspect these types in the TypeDoc to see what properties are available.

Modifying the Tooltip Container

The container of the tooltip can be modified as well. Extending the example above further, we override TooltipModifier3D.tooltipSvgTemplate to customize the background/foreground color before rendering the tooltip.

// Declare a tooltip and add to the chart
const tooltipModifier = new TooltipModifier3D({
    crosshairStroke: "#83D2F5",
    crosshairStrokeThickness: 3,
    tooltipContainerBackground: "#537ABD",
    tooltipTextStroke: "White",
    tooltipLegendOffsetX: 10,
    tooltipLegendOffsetY: 10
  });

// Customize the tooltip container like this
const defaultTemplate = tooltipModifier.tooltipSvgTemplate;
tooltipModifier.tooltipSvgTemplate = (seriesInfo, svgAnnotation) => {
  if (seriesInfo) {
    const md = seriesInfo.pointMetadata;
    const backgroundColor = md ? parseArgbToHtmlColor(md.vertexColor) : seriesInfo.renderableSeries.stroke;
    svgAnnotation.containerBackground = backgroundColor;
    svgAnnotation.textStroke = "white";
  }
  return defaultTemplate(seriesInfo, svgAnnotation);
};

sciChart3DSurface.chartModifiers.add(tooltipModifier);

This results in the following output:

<div class="wrapper">
    <div id="scichart-root" ></div>
    <div class="titleWrapper">
        <p class="title">SciChart.js 3D Chart Example</p>
        <p class="subTitle">Hover the points to see tooltips</p>
    </div>
</div>

  
body { margin: 0; font-family: Arial; }
.wrapper { width: 100%; height: 100vh; position: relative; }
#scichart-root { width: 100%; height: 100%; position: relative; }
.titleWrapper { position: absolute; width: 100%; top: 35%; text-align: center; pointer-events: none; color: #ffffff77 }
.title { font-size: 20px; }
.subTitle {  font-size: 16px; }

  
const generateData = (index) => {
  const gaussianRandom = (mean, stdev) => {
    const u = 1 - Math.random(); // Converting [0,1) to (0,1]
    const v = Math.random();
    const z = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
    // Transform to the desired mean and standard deviation:
    return z * stdev + mean;
  };

  const xValues = [];
  const yValues = [];
  const zValues = [];

  for (let i = 0; i < 30; i++) {
    xValues.push(i*0.1);
    yValues.push(gaussianRandom(0, 1));
    zValues.push(index);
  }
  return { xValues, yValues, zValues };
}

async function tooltips3DCustomisation(divElementId) {
  const {
    SciChart3DSurface,
    NumericAxis3D,
    Vector3,
    SciChartJsNavyTheme,
    NumberRange,
    XyzDataSeries3D,
    PointLineRenderableSeries3D,
    TooltipModifier3D,
    EllipsePointMarker3D,
    uintArgbColorLerp,
    parseColorToUIntArgb,
    parseArgbToHtmlColor
  } = SciChart;

  // or, for npm, import { SciChart3DSurface, ... } from "scichart"

  // Create a SciChart3DSurface in the host <div id=".." />
  const { wasmContext, sciChart3DSurface } = await SciChart3DSurface.create(divElementId, {
    theme: new SciChartJsNavyTheme(),
    worldDimensions: new Vector3(300, 200, 300),
    cameraOptions: {
      position: new Vector3(-300, 300, 300),
      target: new Vector3(0, 50, 0),
    }
  });

  const growBy = new NumberRange(0.2, 0.2);
  sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, { axisTitle: "Frequency (Hz)", growBy });
  sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, { axisTitle: "Power (dB)" });
  sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, { axisTitle: "Time (s)", growBy });

  // returns data in arrays of numbers e.g. xValues = [0,1,2,3,4], yValues = [0,1,2,3,4], zValues = [0,1,2,3,4]
  const { xValues, yValues, zValues } = generateData(1);

  // Add a PointLineRenderableSeries3D
  sciChart3DSurface.renderableSeries.add(new PointLineRenderableSeries3D(wasmContext, {
    dataSeries: new XyzDataSeries3D(wasmContext, { xValues, yValues, zValues, dataSeriesName: "Series A" }),
    opacity: 0.9,
    stroke: "#EC0F6C",
    strokeThickness: 3,
    pointMarker: new EllipsePointMarker3D(wasmContext, { size: 3 })
  }));

  // Repeat 2x
  const dataset1 = generateData(2);
  const colorHigh = parseColorToUIntArgb("#EC0F6C");
  const colorLow = parseColorToUIntArgb("#30BC9A");
  const yMin = Math.min(...yValues);
  const yMax = Math.max(...yValues);
  const metadata = dataset1.yValues.map((y, i) => {
    // interpolate y between colorLow and colorHigh using the helper function uintArgbColorLerp
    const t = (y - yMin) / (yMax - yMin);
    const color = uintArgbColorLerp(colorLow, colorHigh, t);
    return { vertexColor: color, customString: `Custom string ${i}` };
  });
  sciChart3DSurface.renderableSeries.add(new PointLineRenderableSeries3D(wasmContext, {
    dataSeries: new XyzDataSeries3D(wasmContext, { xValues: dataset1.xValues, yValues: dataset1.yValues, zValues: dataset1.zValues, metadata, dataSeriesName: "Series B" }),
    opacity: 0.9,
    stroke: "#50C7E0",
    strokeThickness: 3,
    pointMarker: new EllipsePointMarker3D(wasmContext, { size: 3 })
  }));

  const dataset2 = generateData(3);
  sciChart3DSurface.renderableSeries.add(new PointLineRenderableSeries3D(wasmContext, {
    dataSeries: new XyzDataSeries3D(wasmContext, { xValues: dataset2.xValues, yValues: dataset2.yValues, zValues: dataset2.zValues, dataSeriesName: "Series C" }),
    opacity: 0.9,
    stroke: "#F48420",
    strokeThickness: 3,
    pointMarker: new EllipsePointMarker3D(wasmContext, { size: 3 })
  }));


  // #region ExampleA
  // Declare a tooltip and add to the chart
  const tooltipModifier = new TooltipModifier3D({
      crosshairStroke: "#83D2F5",
      crosshairStrokeThickness: 3,
      tooltipContainerBackground: "#537ABD",
      tooltipTextStroke: "White",
      tooltipLegendOffsetX: 10,
      tooltipLegendOffsetY: 10
    });

  // Customize the tooltip container like this
  const defaultTemplate = tooltipModifier.tooltipSvgTemplate;
  tooltipModifier.tooltipSvgTemplate = (seriesInfo, svgAnnotation) => {
    if (seriesInfo) {
      const md = seriesInfo.pointMetadata;
      const backgroundColor = md ? parseArgbToHtmlColor(md.vertexColor) : seriesInfo.renderableSeries.stroke;
      svgAnnotation.containerBackground = backgroundColor;
      svgAnnotation.textStroke = "white";
    }
    return defaultTemplate(seriesInfo, svgAnnotation);
  };

  sciChart3DSurface.chartModifiers.add(tooltipModifier);
  // #endregion

  // Customize the tooltip content
  tooltipModifier.tooltipDataTemplate = (seriesInfo, svgAnnotation) => {
    // Create an array to hold strings (lines) to show in the tooltip
    const valuesWithLabels = [];
    if (seriesInfo && seriesInfo.isHit) {
      // You can access the renderableSeries which was hit via the seriesInfo
      const renderableSeries = seriesInfo.renderableSeries;
      // And the parent Chart from that
      const parentSurface = renderableSeries.parentSurface;

      // Push lines to the array to display in the tooltip
      valuesWithLabels.push(`dataSeriesName: "${seriesInfo.dataSeriesName}"`);
      valuesWithLabels.push(` ${parentSurface.xAxis.axisTitle}: ${seriesInfo.xValue.toFixed(2)}`);
      valuesWithLabels.push(` ${parentSurface.yAxis.axisTitle}: ${seriesInfo.yValue.toFixed(2)}`);
      valuesWithLabels.push(` ${parentSurface.zAxis.axisTitle}: ${seriesInfo.zValue.toFixed(2)}`);

      // access the metadata (if exists)". Any JS object on the data-points can be accessed
      // in tooltips
      const md = seriesInfo.pointMetadata;
      if (md) {
        valuesWithLabels.push(` Metadata: "${md.customString}"`);
      }
    }
    return valuesWithLabels;
  };
};

tooltips3DCustomisation("scichart-root");

  

 

Placing the Tooltip as a Separate Legend

The tooltip can be placed as a legend in the corner of the chart by using the TooltipModifier3D.placementDivId property. This simply changes the location in the HTML Dom where tooltips are placed.

Here's a quick example:

// Declare a tooltip and add to the chart like this.
const tooltipModifier = new TooltipModifier3D({
    crosshairStroke: "#83D2F5",
    crosshairStrokeThickness: 3,
    tooltipContainerBackground: "#537ABD",
    tooltipTextStroke: "White",
    tooltipLegendOffsetX: 10,
    tooltipLegendOffsetY: 10,

    // Allows placement of tooltip in a custom div anywhere in your app
    placementDivId: "tooltipContainerDivId"
  });

sciChart3DSurface.chartModifiers.add(tooltipModifier);

This results in the following output:

<div class="wrapper">
    <div id="scichart-root" ></div>
    <div class="titleWrapper">
        <p class="title">SciChart.js 3D Chart Example</p>
        <p class="subTitle">Hover the points to see tooltips</p>
    </div>
    <div id="tooltipContainerDivId">
        <!-- Tooltips are placed here -->
    </div>
</div>

  
body { margin: 0; font-family: Arial; }
.wrapper { width: 100%; height: 100vh; position: relative; }
#scichart-root { width: 100%; height: 100%; position: relative; }
.titleWrapper { position: absolute; width: 100%; top: 35%; text-align: center; pointer-events: none; color: #ffffff77 }
.title { font-size: 20px; }
.subTitle {  font-size: 16px; }
#tooltipContainerDivId { position: absolute; top: 10px; left: 10px; pointer-events: none; }

  
async function tooltips3D(divElementId) {
  const {
    SciChart3DSurface,
    NumericAxis3D,
    Vector3,
    SciChartJsNavyTheme,
    EAutoRange,
    NumberRange,
    SpherePointMarker3D,
    ScatterRenderableSeries3D,
    XyzDataSeries3D,
    SurfaceMeshRenderableSeries3D,
    UniformGridDataSeries3D,
    GradientColorPalette,
    PointLineRenderableSeries3D,
    EDrawMeshAs,
    TooltipModifier3D,
    EMeshPaletteMode
  } = SciChart;

  // or, for npm, import { SciChart3DSurface, ... } from "scichart"

  // Create a SciChart3DSurface in the host <div id=".." />
  const { wasmContext, sciChart3DSurface } = await SciChart3DSurface.create(divElementId, {
    theme: new SciChartJsNavyTheme(),
    worldDimensions: new Vector3(300, 200, 300),
    cameraOptions: {
      position: new Vector3(-300, 300, 300),
      target: new Vector3(0, 50, 0),
    }
  });

  sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, {
    axisTitle: "X Axis",
  });
  sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, {
    axisTitle: "Y Axis",
    visibleRange: new NumberRange(0, 3)
  });
  sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, {
    axisTitle: "Z Axis",
  });

  sciChart3DSurface.renderableSeries.add(
    new SurfaceMeshRenderableSeries3D(wasmContext, {
      dataSeries: new UniformGridDataSeries3D(wasmContext, {
        yValues: [
          [0.1, 0.4, 0.4, 0.2, 0.8],
          [0.6, 0.4, 0.6, 0.1, 0.7],
          [0.2, 0.4, 0.3, 0.4, 0.0],
          [0.6, 0.4, 0.6, 0.1, 0.7],
          [0.1, 0.4, 0.4, 0.2, 0.8],
        ],
        dataSeriesName: "Surface mesh"
      }),
      meshColorPalette: new GradientColorPalette(wasmContext, {
        gradientStops: [
          {offset: 1, color: "#EC0F6C"}, // yValues >= maximum mapped to this color
          {offset: 0.55, color: "#F48420"},
          {offset: 0.3, color: "#67BDAF"},
          {offset: 0.2, color: "#50C7E0"},
          {offset: 0.1, color: "#264B93"},
          {offset: 0, color: "#14233C"}  // yValues <= minimum mapped to this color
        ]
      }),
      minimum: 0,
      maximum: 1,
      opacity: 0.77,
      drawSkirt: false,
      stroke: "White",
      strokeThickness: 2,
      lightingFactor: 0.2,
      meshPaletteMode: EMeshPaletteMode.HEIGHT_MAP_SOLID_CELLS,
      drawMeshAs: EDrawMeshAs.SOLID_WIREFRAME
    })
  );

  // #region ExampleA
  // Declare a tooltip and add to the chart like this.
  const tooltipModifier = new TooltipModifier3D({
      crosshairStroke: "#83D2F5",
      crosshairStrokeThickness: 3,
      tooltipContainerBackground: "#537ABD",
      tooltipTextStroke: "White",
      tooltipLegendOffsetX: 10,
      tooltipLegendOffsetY: 10,

      // Allows placement of tooltip in a custom div anywhere in your app
      placementDivId: "tooltipContainerDivId"
    });

  sciChart3DSurface.chartModifiers.add(tooltipModifier);
  // #endregion
};

tooltips3D("scichart-root");