チャート:軸のスクロールバー

コンパクトなユーザーインタフェースでは、大きなチャートの表示が難しい場合があります。そのため、AxisScrollbarにより、チャートの軸にスクロールバーを追加するオプションを提供しています。

このサンプルでは、X軸とY軸にスクロールバーを追加したチャートを示します。

import 'bootstrap.css'; import '@mescius/wijmo.styles/wijmo.css'; import './styles.css'; import * as chart from '@mescius/wijmo.chart'; import { getData } from './data'; import { AxisScrollbar } from './AxisScrollbar'; // document.readyState === 'complete' ? init() : window.onload = init; // function init() { // create the chart let theChart = new chart.FlexChart('#theChart', { plotMargin: 'NaN NaN NaN 80', bindingX: 'date', chartType: 'Line', itemsSource: getData(), tooltip: { content: '' }, axisX: { axisLine: false }, series: [ { name: 'データ', binding: 'yval' } ], }); // create Scrollbar let axisXScrollbar = new AxisScrollbar(theChart.axes[0], { minScale: 0.02 }); let axisYScrollbar = new AxisScrollbar(theChart.axes[1], { buttonsVisible: false, minScale: 0.05 }); }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>MESCIUS Wijmo FlexChart Scrolling & Range Selectors</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"> <div id="theChart"></div> </div> </body> </html>
// generate some random data export function getData() { let dataCount = 3000; let data = []; for (var i = 0; i < dataCount; i++) { var mod = Math.floor(i / 10) % 10; data.push({ date: new Date(2005, 0, i), yval: mod == 0 ? null : Math.random() * 100 }); } return data; }
.wj-flexchart { margin: 0px; padding: 0px; border-bottom: 0px; touch-action: none; -ms-touch-action: none; padding-bottom: 40px; } body { margin-bottom: 24pt; } /**** Axis Scrollbar Css *****/ .wj-flexchart .wj-axis-scrollbar-container { position: relative; } .wj-flexchart .wj-axis-scrollbar-container .wj-chart-rangeslider { border: 1px solid #EAEAEA; background-color: #EAEAEA; border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; border-top-left-radius: 6px; border-top-right-radius: 6px; } .wj-flexchart .wj-axis-scrollbar-container .wj-chart-hrangeslider { height: 20px; } .wj-flexchart .wj-axis-scrollbar-container .wj-chart-vrangeslider { width: 20px; }
import * as core from '@mescius/wijmo'; import * as chart from '@mescius/wijmo.chart'; import * as interaction from '@mescius/wijmo.chart.interaction'; 'use strict'; /** * The @see:AxisScrollbar control displays a scrollbar that allows the user to * choose the range of Axis. */ export class AxisScrollbar { /** * Initializes a new instance of the @see:AxisScrollbar control. * * @param axis The axis that displays scrollbar. * @param options A JavaScript object containing initialization data for the control. */ constructor(axis, options) { // fields this._isVisible = true; this._min = null; this._max = null; this._buttonsVisible = true; //private _minScale: number = 0.01; this._minScale = 0; // host this._chart = null; this._axis = null; this._rangeSlider = null; // elements this._slbarContainer = null; this._isXAxis = true; this._chartRefreshDelay = null; if (!chart) { core.assert(false, 'The Axis cannot be null.'); } this._axis = axis; this._chart = axis._chart; this._isXAxis = this._axis.axisType === chart.AxisType.X; core.copy(this, options); this._createScrollbar(); } /** * Gets or sets the decrease button and increase button is visible or not. */ get buttonsVisible() { return this._buttonsVisible; } set buttonsVisible(value) { if (value !== this._buttonsVisible) { this._buttonsVisible = core.asBoolean(value); if (!this._rangeSlider) { return; } this._rangeSlider.buttonsVisible = this._buttonsVisible; } } /** * Gets or sets the visibility of the Axis scrollbar. */ get isVisible() { return this._isVisible; } set isVisible(value) { if (value != this._isVisible) { this._isVisible = core.asBoolean(value); if (!this._rangeSlider) { return; } this._rangeSlider.isVisible = value; } } set minPos(value) { if (value < 0 && value > 1 && value > this._rangeSlider._maxPos) { return; } this._rangeSlider._minPos = value; this._updateAxisRange(); } set maxPos(value) { if (value < 0 && value > 1 && value < this._rangeSlider._minPos) { return; } this._rangeSlider._maxPos = value; this._updateAxisRange(); } /** * Gets or sets the minimum range scale of the Axis scrollbar. * The minimum range scale should be greater than zero. */ get minScale() { return this._minScale; } set minScale(value) { if (value > 0 && value != this._minScale) { this._minScale = core.asNumber(value); if (!this._rangeSlider) { return; } this._rangeSlider.minScale = value; } } /** * Removes the range selector from the chart. */ remove() { if (this._slbarContainer) { this._chart.hostElement.removeChild(this._slbarContainer); this._switchEvent(false); this._slbarContainer = null; } } _createScrollbar() { var chart = this._chart, chartHostEle = chart.hostElement; this._slbarContainer = core.createElement('<div class="wj-axis-scrollbar-container"></div>'); this._rangeSlider = new interaction._RangeSlider(this._slbarContainer, true, // has space click function true, // has dec and inc buttons { buttonsVisible: this._buttonsVisible, isHorizontal: this._isXAxis, isVisible: this._isVisible, minScale: this._minScale, seamless: true }); chartHostEle.appendChild(this._slbarContainer); this._switchEvent(true); } _switchEvent(isOn) { var eventListener = isOn ? 'addEventListener' : 'removeEventListener', eventHandler = isOn ? 'addHandler' : 'removeHandler'; if (this._chart.hostElement) { this._chart.rendered[eventHandler](this._refresh, this); this._rangeSlider.rangeChanged[eventHandler](this._updateAxisRange, this); this._rangeSlider.rangeChanging[eventHandler](this._updatingAxisRange, this); } } _refresh() { var chartHostEle = this._chart.hostElement, rangeSlider = this._rangeSlider, pa, pOffset, plotBox, axisRect = this._axis._axrect, axisEle, axisOffset, isBottom, isLeft, rsWidth, rOffset = core.getElementRect(this._slbarContainer); if (rangeSlider._isSliding) { return; } //init the scrollbar range if (this._min === null) { this._min = core.isDate(this._axis.actualMin) ? this._axis.actualMin.valueOf() : this._axis.actualMin; } if (this._max === null) { this._max = core.isDate(this._axis.actualMax) ? this._axis.actualMax.valueOf() : this._axis.actualMax; } pa = chartHostEle.querySelector('.' + chart.FlexChart._CSS_PLOT_AREA); pOffset = core.getElementRect(pa); plotBox = pa.getBBox(pa); //TODO: get the axis element when has multiple axes axisEle = chartHostEle.querySelector(this._isXAxis ? '.wj-axis-x' : '.wj-axis-y'); axisOffset = core.getElementRect(axisEle); if (axisOffset.height === 0) { return; } if (this._isXAxis) { isBottom = this._axis.position === chart.Position.Bottom; rangeSlider._refresh({ left: plotBox.x, top: isBottom ? axisOffset.top + axisOffset.height - rOffset.top : axisOffset.top - rOffset.top - axisOffset.height, width: plotBox.width }); } else { isLeft = this._axis.position === chart.Position.Left; rsWidth = rangeSlider._handleWidth; rangeSlider._refresh({ left: isLeft ? axisOffset.left - rOffset.left - rsWidth : axisOffset.left - rOffset.left + pOffset.width + this._axis._axrect.width, top: pOffset.top - rOffset.top, height: plotBox.height }); } } _updateAxisRange() { var chart, axis, range, rangeSlider = this._rangeSlider; chart = this._chart; axis = this._axis; range = this._max - this._min; if (axis.reversed) { axis.min = this._max - rangeSlider._maxPos * range; axis.max = this._max - rangeSlider._minPos * range; } else { axis.min = this._min + rangeSlider._minPos * range; axis.max = this._min + rangeSlider._maxPos * range; } chart.invalidate(); } _updatingAxisRange() { var self = this; this._chartRefreshDelay = window.setTimeout(function () { if (self._chartRefreshDelay) { clearTimeout(self._chartRefreshDelay); self._chartRefreshDelay = null; } self._updateAxisRange(); }, 200); } }
(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);