Trend Lines

The TrendLine class extends the regular Series class to provide a calculated series based on the data and parameters you select.

To add trend lines to a FlexChart, follow these steps:

  1. Create one or more TrendLine objects,
  2. Configure the TrendLine objects as you would a regular series, setting their binding, chartType, and style properties for example, and
  3. Set the TrendLine's fitType and order properties to determine the type of trend line you want to create.
  4. Set the TrendLine's minX & maxX property to extend trendline beyond data range by setting custom minX and maxX values

Learn about FlexChart | TrendLine Documentation | FlexChart API Reference

import 'bootstrap.css'; import '@mescius/wijmo.styles/wijmo.css'; import './styles.css'; import * as wjChart from '@mescius/wijmo.chart'; import * as wjChartAnalytics from '@mescius/wijmo.chart.analytics'; import * as wjInput from '@mescius/wijmo.input'; import { getData } from './data'; // document.readyState === 'complete' ? init() : window.onload = init; // function init() { // create the chart let theChart = new wjChart.FlexChart('#theChart', { itemsSource: getData(), chartType: 'Scatter', axisY: { axisLine: true }, bindingX: 'x', series: [ { name: 'Raw Data', binding: 'y' } ] }); // // show the equation on the chart let equation = document.getElementById('equation'); // // create a TrendLine and add it to the Chart series collection let trendLine = new wjChartAnalytics.TrendLine(); trendLine.binding = 'y'; trendLine.style = { stroke: 'darkred', strokeWidth: 3 }; trendLine.visibility = wjChart.SeriesVisibility.Hidden; function updateTrendLineRange() { let data = theChart.itemsSource; let xValues = data.map(item => item.x); let minX = Math.min(...xValues); let maxX = Math.max(...xValues); let range = maxX - minX; trendLine.minX = minX - (range * 0.1); // 10% of range below minX trendLine.maxX = maxX + (range * 0.3); // 30% of range above maxX } updateTrendLineRange(); // Initial call to set the range theChart.series.push(trendLine); // // select trendline order let order = new wjInput.InputNumber('#order', { value: trendLine.order, step: 1, min: 1, max: 6, valueChanged: (s) => { if (s.value >= s.min && s.value <= s.max) { trendLine.order = s.value; showEquation(); } } }); // // select fit type let fitType = new wjInput.ComboBox('#fitType', { isRequired: false, placeholder: 'None', textChanged: (s) => { trendLine.name = s.text; if (s.text) { // show trendline trendLine.fitType = s.text; trendLine.visibility = wjChart.SeriesVisibility.Visible; } else { // hide trendline trendLine.visibility = wjChart.SeriesVisibility.Hidden; } switch (s.text) { // enable/disable order input case 'Polynomial': case 'Fourier': order.isDisabled = false; break; default: order.isDisabled = true; break; } showEquation(); }, itemsSource: 'Linear,Exponential,Logarithmic,Power,Fourier,Polynomial,MinX,MinY,MaxX,MaxY,AverageX,AverageY'.split(',') }); // // show updated equation on a timeOut since the TrendLine update is async function showEquation() { equation.innerHTML = ''; setTimeout(() => equation.innerHTML = trendLine.getEquation(), 100); } // // randomize the data document.querySelector('#btnRandomize').addEventListener('click', () => { theChart.itemsSource = getData(); showEquation(); }); }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>MESCIUS Wijmo FlexChart Trendlines</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.21.5/system.src.js" integrity="sha512-skZbMyvYdNoZfLmiGn5ii6KmklM82rYX2uWctBhzaXPxJgiv4XBwJnFGr5k8s+6tE1pcR1nuTKghozJHyzMcoA==" crossorigin="anonymous"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <label for="fitType">Trendline Type: </label> <div id="fitType"></div><br /> <label for="order">Order: </label> <div id="order"></div><br /> <label>Equation: </label> <div id="equation" class="equation"></div><br /> <label for="btnRandomize">Randomize Data</label> <button id="btnRandomize" class="btn btn-default"> Go </button> <div id="theChart"></div> </div> </body> </html>
// data sources export function getData() { let arr = [], cnt = 50, a = Math.random(), b = Math.random(); // for (let i = 1; i < cnt; i++) { arr.push({ x: i, y: a + i * b + i * Math.random() }); } // return arr; }
.wj-flexchart { height: 250px; margin: 10px 0; } .wj-control { margin-bottom: 3px; } label { width: 120px; text-align: right; } .equation { display: inline-block; font-style: italic; font-size: 80%; } .wj-combobox, .wj-inputnumber { width: 120px; margin-right: 12px; } body { margin-bottom: 24pt; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'jszip': 'npm:jszip/dist/jszip.js', '@mescius/wijmo': 'npm:@mescius/wijmo/index.js', '@mescius/wijmo.input': 'npm:@mescius/wijmo.input/index.js', '@mescius/wijmo.styles': 'npm:@mescius/wijmo.styles', '@mescius/wijmo.cultures': 'npm:@mescius/wijmo.cultures', '@mescius/wijmo.chart': 'npm:@mescius/wijmo.chart/index.js', '@mescius/wijmo.chart.analytics': 'npm:@mescius/wijmo.chart.analytics/index.js', '@mescius/wijmo.chart.animation': 'npm:@mescius/wijmo.chart.animation/index.js', '@mescius/wijmo.chart.annotation': 'npm:@mescius/wijmo.chart.annotation/index.js', '@mescius/wijmo.chart.finance': 'npm:@mescius/wijmo.chart.finance/index.js', '@mescius/wijmo.chart.finance.analytics': 'npm:@mescius/wijmo.chart.finance.analytics/index.js', '@mescius/wijmo.chart.hierarchical': 'npm:@mescius/wijmo.chart.hierarchical/index.js', '@mescius/wijmo.chart.interaction': 'npm:@mescius/wijmo.chart.interaction/index.js', '@mescius/wijmo.chart.radar': 'npm:@mescius/wijmo.chart.radar/index.js', '@mescius/wijmo.chart.render': 'npm:@mescius/wijmo.chart.render/index.js', '@mescius/wijmo.chart.webgl': 'npm:@mescius/wijmo.chart.webgl/index.js', '@mescius/wijmo.chart.map': 'npm:@mescius/wijmo.chart.map/index.js', '@mescius/wijmo.gauge': 'npm:@mescius/wijmo.gauge/index.js', '@mescius/wijmo.grid': 'npm:@mescius/wijmo.grid/index.js', '@mescius/wijmo.grid.detail': 'npm:@mescius/wijmo.grid.detail/index.js', '@mescius/wijmo.grid.filter': 'npm:@mescius/wijmo.grid.filter/index.js', '@mescius/wijmo.grid.search': 'npm:@mescius/wijmo.grid.search/index.js', '@mescius/wijmo.grid.grouppanel': 'npm:@mescius/wijmo.grid.grouppanel/index.js', '@mescius/wijmo.grid.multirow': 'npm:@mescius/wijmo.grid.multirow/index.js', '@mescius/wijmo.grid.transposed': 'npm:@mescius/wijmo.grid.transposed/index.js', '@mescius/wijmo.grid.transposedmultirow': 'npm:@mescius/wijmo.grid.transposedmultirow/index.js', '@mescius/wijmo.grid.pdf': 'npm:@mescius/wijmo.grid.pdf/index.js', '@mescius/wijmo.grid.sheet': 'npm:@mescius/wijmo.grid.sheet/index.js', '@mescius/wijmo.grid.xlsx': 'npm:@mescius/wijmo.grid.xlsx/index.js', '@mescius/wijmo.grid.selector': 'npm:@mescius/wijmo.grid.selector/index.js', '@mescius/wijmo.grid.cellmaker': 'npm:@mescius/wijmo.grid.cellmaker/index.js', '@mescius/wijmo.nav': 'npm:@mescius/wijmo.nav/index.js', '@mescius/wijmo.odata': 'npm:@mescius/wijmo.odata/index.js', '@mescius/wijmo.olap': 'npm:@mescius/wijmo.olap/index.js', '@mescius/wijmo.rest': 'npm:@mescius/wijmo.rest/index.js', '@mescius/wijmo.pdf': 'npm:@mescius/wijmo.pdf/index.js', '@mescius/wijmo.pdf.security': 'npm:@mescius/wijmo.pdf.security/index.js', '@mescius/wijmo.viewer': 'npm:@mescius/wijmo.viewer/index.js', '@mescius/wijmo.xlsx': 'npm:@mescius/wijmo.xlsx/index.js', '@mescius/wijmo.undo': 'npm:@mescius/wijmo.undo/index.js', '@mescius/wijmo.interop.grid': 'npm:@mescius/wijmo.interop.grid/index.js', '@mescius/wijmo.touch': 'npm:@mescius/wijmo.touch/index.js', '@mescius/wijmo.cloud': 'npm:@mescius/wijmo.cloud/index.js', '@mescius/wijmo.barcode': 'npm:@mescius/wijmo.barcode/index.js', '@mescius/wijmo.barcode.common': 'npm:@mescius/wijmo.barcode.common/index.js', '@mescius/wijmo.barcode.composite': 'npm:@mescius/wijmo.barcode.composite/index.js', '@mescius/wijmo.barcode.specialized': 'npm:@mescius/wijmo.barcode.specialized/index.js', 'jszip': 'npm:jszip/dist/jszip.js', 'bootstrap.css': 'npm:bootstrap/dist/css/bootstrap.min.css', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);