license import embed , { Mode , VisualizationSpec } from 'vega-embed' ; import { Drawable , Point2D , XYPlotData , XYPlotOptions } from '../types' ; import { getDrawArea } from './render_utils' ; /**
 * Renders a line chart
 *
 * ```js
 * const series1 = Array(100).fill(0)
 *   .map(y => Math.random() * 100 - (Math.random() * 50))
 *   .map((y, x) => ({ x, y, }));
 *
 * const series2 = Array(100).fill(0)
 *   .map(y => Math.random() * 100 - (Math.random() * 150))
 *   .map((y, x) => ({ x, y, }));
 *
 * const series = ['First', 'Second'];
 * const data = { values: [series1, series2], series }
 *
 * const surface = { name: 'Line chart', tab: 'Charts' };
 * tfvis.render.linechart(surface, data);
 * ```
 *
 * ```js
 * const series1 = Array(100).fill(0)
 *   .map(y => Math.random() * 100 + 50)
 *   .map((y, x) => ({ x, y, }));
 *
 * const data = { values: [series1] }
 *
 * // Render to visor
 * const surface = { name: 'Zoomed Line Chart', tab: 'Charts' };
 * tfvis.render.linechart(surface, data, { zoomToFit: true });
 * ```
 *
 */ doc export async function linechart ( container , data , opts = { } ) { let inputArray = data . values ; const _series = data . series == null ? [ ] : data . series ; inputArray = Array . isArray ( inputArray [ 0 ] ) ? inputArray as Point2D [ ] [ ] : [ inputArray ] as Point2D [ ] [ ] ; const values = [ ] ; const seriesNames = new Set ( ) ; inputArray . forEach ( ( seriesData , i ) => { const seriesName = _series [ i ] != null ? _series [ i ] : `Series ${ i + 1 }` ; seriesNames . add ( seriesName ) ; const seriesVals = seriesData . map ( v => Object . assign ( { } , v , { series : seriesName } ) ) ; values . push ( ... seriesVals ) ; } ) ; const drawArea = getDrawArea ( container ) ; const options = Object . assign ( { } , defaultOpts , opts ) ; const embedOpts = { actions : false , mode : 'vega-lite' as Mode , defaultStyle : false , } ; const yScale = ( ) : { } | undefined => { if ( options . zoomToFit ) { return { 'zero' : false } ; } else if ( options . yAxisDomain != null ) { return { 'domain' : options . yAxisDomain } ; } return undefined ; } ; const encodings = { 'x' : { 'field' : 'x' , 'type' : options . xType , 'title' : options . xLabel , } , 'y' : { 'field' : 'y' , 'type' : options . yType , 'title' : options . yLabel , 'scale' : yScale ( ) , } , 'color' : { 'field' : 'series' , 'type' : 'nominal' , 'legend' : { 'values' : Array . from ( seriesNames ) } } , } ; let domainFilter ; if ( options . yAxisDomain != null ) { domainFilter = { 'filter' : { 'field' : 'y' , 'range' : options . yAxisDomain } } ; } const spec = { 'width' : options . width || drawArea . clientWidth , 'height' : options . height || drawArea . clientHeight , 'padding' : 0 , 'autosize' : { 'type' : 'fit' , 'contains' : 'padding' , 'resize' : true , } , 'config' : { 'axis' : { 'labelFontSize' : options . fontSize , 'titleFontSize' : options . fontSize , } , 'text' : { 'fontSize' : options . fontSize } , 'legend' : { 'labelFontSize' : options . fontSize , 'titleFontSize' : options . fontSize , } } , 'data' : { 'values' : values } , 'layer' : [ { 'mark' : { 'type' : 'line' , 'clip' : true , } , 'encoding' : encodings , } , { 'mark' : { 'type' : 'point' } , 'transform' : options . yAxisDomain ? [ domainFilter ] : undefined , 'selection' : { 'nearestPoint' : { 'type' : 'single' , 'on' : 'mouseover' , 'nearest' : true , 'empty' : 'none' , 'encodings' : [ 'x' ] , } , } , 'encoding' : Object . assign ( { } , encodings , { 'opacity' : { 'value' : 0 , 'condition' : { 'selection' : 'nearestPoint' , 'value' : 1 , } , } } ) , } , { 'transform' : [ { 'filter' : { 'selection' : 'nearestPoint' } } , domainFilter ] . filter ( Boolean ) , 'mark' : { 'type' : 'text' , 'align' : 'left' , 'dx' : 5 , 'dy' : - 5 , 'color' : 'black' , } , 'encoding' : Object . assign ( { } , encodings , { 'text' : { 'type' : options . xType , 'field' : 'y' , 'format' : '.6f' , } , 'color' : undefined , } ) , } , { 'transform' : [ { 'filter' : { 'selection' : 'nearestPoint' } } ] , 'mark' : { 'type' : 'rule' , 'color' : 'gray' } , 'encoding' : { 'x' : { 'type' : options . xType , 'field' : 'x' , } } } , ] , } ; await embed ( drawArea , spec , embedOpts ) ; return Promise . resolve ( ) ; } const defaultOpts = { xLabel : 'x' , yLabel : 'y' , xType : 'quantitative' , yType : 'quantitative' , zoomToFit : false , fontSize : 11 , } ;