JavaScript data visualization library for creating interactive charts, graphs, and scientific visualizations
81
Functions for exporting plots as images, validating data, and managing plot lifecycle. These utilities provide essential functionality for plot management and data export.
Exports a plot as an image in various formats with customizable options.
/**
* Exports plot as image data
* @param figure - Graph div element or figure object
* @param options - Export configuration options
* @returns Promise resolving to image data URL or binary data
*/
function toImage(
figure: HTMLElement | FigureConfig,
options?: ImageExportOptions
): Promise<string>;
interface ImageExportOptions {
format?: 'png' | 'jpeg' | 'webp' | 'svg' | 'pdf' | 'eps' | 'html';
width?: number;
height?: number;
scale?: number; // DPI multiplier (1 = 72 DPI, 2 = 144 DPI, etc.)
engine?: 'auto' | 'kaleido' | 'orca';
imageDataOnly?: boolean; // Return raw image data instead of data URL
}
interface FigureConfig {
data: PlotData;
layout?: Partial<Layout>;
config?: Partial<Config>;
}Usage Examples:
import Plotly from 'plotly.js-dist';
// Basic image export as PNG
const imageData = await Plotly.toImage('my-chart', {
format: 'png',
width: 800,
height: 600,
scale: 2 // High DPI for crisp images
});
// Use the data URL (can be set as img src)
const img = document.createElement('img');
img.src = imageData;
document.body.appendChild(img);
// Export as JPEG with compression
const jpegData = await Plotly.toImage('my-chart', {
format: 'jpeg',
width: 1200,
height: 800,
scale: 1
});
// Export as SVG (vector format)
const svgData = await Plotly.toImage('my-chart', {
format: 'svg',
width: 800,
height: 600
});
// Export from figure object (without DOM element)
const figure = {
data: [{
x: [1, 2, 3, 4],
y: [10, 11, 12, 13],
type: 'scatter'
}],
layout: {
title: 'Sample Plot',
width: 600,
height: 400
}
};
const figureImage = await Plotly.toImage(figure, {
format: 'png',
scale: 2
});
// Export for print (high resolution)
const printImage = await Plotly.toImage('my-chart', {
format: 'png',
width: 3200, // 300 DPI at ~10.7 inches wide
height: 2400, // 300 DPI at 8 inches tall
scale: 1
});Downloads a plot as an image file directly to the user's device.
/**
* Downloads plot as image file
* @param graphDiv - Graph div element
* @param options - Download configuration options
* @returns Promise resolving when download completes
*/
function downloadImage(
graphDiv: HTMLElement,
options?: DownloadImageOptions
): Promise<void>;
interface DownloadImageOptions extends ImageExportOptions {
filename?: string; // Default: 'newplot'
}Usage Examples:
// Basic download as PNG
await Plotly.downloadImage('my-chart', {
filename: 'my-analysis',
format: 'png',
width: 1200,
height: 800,
scale: 2
});
// Download high-resolution PDF
await Plotly.downloadImage('my-chart', {
filename: 'report-chart',
format: 'pdf',
width: 800,
height: 600
});
// Download for web use
await Plotly.downloadImage('my-chart', {
filename: 'web-chart',
format: 'webp',
width: 800,
height: 600,
scale: 1
});
// Download SVG for editing
await Plotly.downloadImage('my-chart', {
filename: 'editable-chart',
format: 'svg'
});Validates plot data and layout against the Plotly.js schema to catch errors before plotting.
/**
* Validates plot data and layout against schema
* @param data - Array of trace objects to validate
* @param layout - Layout object to validate
* @returns Array of validation error objects
*/
function validate(
data: PlotData,
layout?: Partial<Layout>
): ValidationError[];
interface ValidationError {
code: string;
message: string;
path: string; // JSON path to invalid attribute
value: any; // The invalid value
trace?: number; // Trace index if error is in trace data
}Usage Examples:
// Validate trace data
const data = [{
x: [1, 2, 3],
y: [4, 5, 6],
type: 'scatter',
mode: 'invalid-mode' // This will cause validation error
}];
const layout = {
title: 'Test Chart',
xaxis: {
range: [0, 'invalid'] // This will cause validation error
}
};
const errors = Plotly.validate(data, layout);
if (errors.length > 0) {
console.error('Validation errors found:');
errors.forEach(error => {
console.error(`${error.code}: ${error.message}`);
console.error(`Path: ${error.path}`);
console.error(`Value: ${error.value}`);
});
} else {
console.log('Data is valid!');
await Plotly.newPlot('chart', data, layout);
}
// Common validation patterns
function validateBeforePlot(data, layout) {
const errors = Plotly.validate(data, layout);
if (errors.length > 0) {
const errorMessages = errors.map(e => `${e.path}: ${e.message}`);
throw new Error(`Validation failed:\n${errorMessages.join('\n')}`);
}
return true;
}
// Validate individual traces
function validateTrace(trace, traceIndex) {
const errors = Plotly.validate([trace]);
return errors.filter(error => error.trace === 0);
}
// Validate layout only
function validateLayout(layout) {
return Plotly.validate([], layout);
}Completely removes a plot and cleans up all associated resources to prevent memory leaks.
/**
* Completely removes plot and cleans up resources
* @param graphDiv - Graph div element to purge
* @returns The graph div element
*/
function purge(graphDiv: HTMLElement): HTMLElement;Usage Examples:
// Clean up single plot
const chartDiv = document.getElementById('my-chart');
Plotly.purge(chartDiv);
// Clean up before removing from DOM
function removeChart(chartId) {
const chartDiv = document.getElementById(chartId);
if (chartDiv && chartDiv.data) {
Plotly.purge(chartDiv);
}
chartDiv.remove();
}
// Clean up in React component
class PlotComponent extends React.Component {
componentWillUnmount() {
if (this.chartRef.current) {
Plotly.purge(this.chartRef.current);
}
}
render() {
return <div ref={this.chartRef} />;
}
}
// Clean up multiple charts
function purgeAllCharts() {
const charts = document.querySelectorAll('[data-plotly]');
charts.forEach(chart => {
Plotly.purge(chart);
});
}
// Memory leak prevention pattern
async function createTemporaryChart(data, layout) {
const tempDiv = document.createElement('div');
document.body.appendChild(tempDiv);
try {
await Plotly.newPlot(tempDiv, data, layout);
// Do something with the chart
const imageData = await Plotly.toImage(tempDiv);
return imageData;
} finally {
// Always clean up
Plotly.purge(tempDiv);
tempDiv.remove();
}
}Access to the complete Plotly.js schema for programmatic inspection of available attributes.
/**
* Complete Plotly.js schema with all trace types and attributes
*/
interface PlotSchema {
traces: {
[traceType: string]: TraceSchema;
};
layout: LayoutSchema;
transforms: {
[transformType: string]: TransformSchema;
};
frames: FrameSchema;
animation: AnimationSchema;
}
interface TraceSchema {
attributes: AttributeSchema;
meta: {
description: string;
hrName: string;
};
}Usage Examples:
// Access schema information
const schema = Plotly.PlotSchema.get();
// Get available trace types
const traceTypes = Object.keys(schema.traces);
console.log('Available trace types:', traceTypes);
// Get attributes for a specific trace type
const scatterAttributes = schema.traces.scatter.attributes;
console.log('Scatter trace attributes:', Object.keys(scatterAttributes));
// Get layout attributes
const layoutAttributes = schema.layout;
console.log('Layout attributes:', Object.keys(layoutAttributes));
// Check if attribute exists
function hasAttribute(traceType, attributePath) {
const trace = schema.traces[traceType];
if (!trace) return false;
// Navigate nested attributes
const pathParts = attributePath.split('.');
let current = trace.attributes;
for (const part of pathParts) {
if (!current[part]) return false;
current = current[part];
}
return true;
}
// Example usage
console.log(hasAttribute('scatter', 'marker.color')); // true
console.log(hasAttribute('scatter', 'invalid.attribute')); // false
// Get attribute metadata
function getAttributeInfo(traceType, attributePath) {
const trace = schema.traces[traceType];
if (!trace) return null;
const pathParts = attributePath.split('.');
let current = trace.attributes;
for (const part of pathParts) {
if (!current[part]) return null;
current = current[part];
}
return {
valType: current.valType,
dflt: current.dflt,
description: current.description,
values: current.values,
min: current.min,
max: current.max
};
}Sets global configuration defaults that apply to all plots.
/**
* Sets global plot configuration defaults
* @param config - Configuration object to merge with defaults
* @returns Extended configuration object
*/
function setPlotConfig(config: Partial<Config>): Config;Usage Examples:
// Set global defaults
Plotly.setPlotConfig({
displayModeBar: false,
responsive: true,
displaylogo: false
});
// All subsequent plots will use these defaults
await Plotly.newPlot('chart1', data1, layout1);
await Plotly.newPlot('chart2', data2, layout2);
// Override global config for specific plot
await Plotly.newPlot('chart3', data3, layout3, {
displayModeBar: true // Override global setting
});
// Set organization branding defaults
Plotly.setPlotConfig({
displaylogo: false,
modeBarButtonsToRemove: ['sendDataToCloud'],
toImageButtonOptions: {
filename: 'company-chart',
format: 'png',
width: 1200,
height: 800,
scale: 2
}
});
// Set accessibility defaults
Plotly.setPlotConfig({
displayModeBar: true,
modeBarButtonsToAdd: [{
name: 'textDescription',
title: 'Get text description',
icon: '📝',
click: function(gd) {
alert(generateTextDescription(gd));
}
}]
});/**
* Get Plotly.js version information
*/
const version: string;// Safe plotting with error handling
async function safePlot(elementId, data, layout, config) {
try {
// Validate first
const errors = Plotly.validate(data, layout);
if (errors.length > 0) {
throw new Error(`Validation failed: ${errors.map(e => e.message).join(', ')}`);
}
// Create plot
await Plotly.newPlot(elementId, data, layout, config);
} catch (error) {
console.error('Plot creation failed:', error);
// Show error to user
const errorDiv = document.getElementById(elementId);
errorDiv.innerHTML = `
<div style="padding: 20px; text-align: center; color: red;">
<h3>Plot Error</h3>
<p>${error.message}</p>
</div>
`;
}
}
// Batch export with error handling
async function exportMultiplePlots(plotIds, options) {
const results = [];
for (const plotId of plotIds) {
try {
const imageData = await Plotly.toImage(plotId, options);
results.push({ plotId, success: true, data: imageData });
} catch (error) {
results.push({ plotId, success: false, error: error.message });
}
}
return results;
}// Performance monitoring utilities
function measurePlotTime(elementId, data, layout, config) {
const startTime = performance.now();
return Plotly.newPlot(elementId, data, layout, config).then(() => {
const endTime = performance.now();
const duration = endTime - startTime;
console.log(`Plot ${elementId} created in ${duration.toFixed(2)}ms`);
return duration;
});
}
// Memory usage monitoring
function getPlotMemoryUsage(elementId) {
const element = document.getElementById(elementId);
if (!element || !element.data) {
return null;
}
const dataSize = JSON.stringify(element.data).length;
const layoutSize = JSON.stringify(element.layout).length;
return {
dataSize,
layoutSize,
totalSize: dataSize + layoutSize,
traceCount: element.data.length
};
}// Export multiple charts as a single document
async function exportDashboard(chartIds, options = {}) {
const images = await Promise.all(
chartIds.map(id => Plotly.toImage(id, {
format: 'png',
width: 800,
height: 600,
scale: 2,
...options
}))
);
// Create a combined image or document
return combinImages(images);
}
// Export with custom watermark
async function exportWithWatermark(chartId, watermarkText) {
// Add watermark annotation
await Plotly.relayout(chartId, {
'annotations[0]': {
text: watermarkText,
x: 0.95,
y: 0.05,
xref: 'paper',
yref: 'paper',
xanchor: 'right',
yanchor: 'bottom',
showarrow: false,
font: { size: 10, color: 'rgba(0,0,0,0.3)' }
}
});
// Export with watermark
const imageData = await Plotly.toImage(chartId);
// Remove watermark
await Plotly.relayout(chartId, {
'annotations[0]': null
});
return imageData;
}// Optimize export settings based on use case
const exportPresets = {
web: {
format: 'webp',
scale: 1,
width: 800,
height: 600
},
print: {
format: 'pdf',
scale: 1,
width: 3200, // 300 DPI
height: 2400
},
presentation: {
format: 'png',
scale: 2,
width: 1920,
height: 1080
},
thumbnail: {
format: 'jpeg',
scale: 1,
width: 300,
height: 200
}
};
async function exportForUseCase(chartId, useCase) {
const options = exportPresets[useCase];
if (!options) {
throw new Error(`Unknown use case: ${useCase}`);
}
return await Plotly.toImage(chartId, options);
}Install with Tessl CLI
npx tessl i tessl/npm-plotly-js-distdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10