123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- /**
- * (c) 2010-2019 Torstein Honsi
- *
- * License: www.highcharts.com/license
- *
- * Highcharts feature to make the Y axis stay fixed when scrolling the chart
- * horizontally on mobile devices. Supports left and right side axes.
- */
- 'use strict';
- import H from './Globals.js';
- var addEvent = H.addEvent,
- Chart = H.Chart;
- /**
- * Options for a scrollable plot area. This feature provides a minimum width for
- * the plot area of the chart. If the width gets smaller than this, typically
- * on mobile devices, a native browser scrollbar is presented below the chart.
- * This scrollbar provides smooth scrolling for the contents of the plot area,
- * whereas the title, legend and axes are fixed.
- *
- * @sample {highcharts} highcharts/chart/scrollable-plotarea
- * Scrollable plot area
- *
- * @since 6.1.0
- * @product highcharts gantt
- * @apioption chart.scrollablePlotArea
- */
- /**
- * The minimum width for the plot area. If it gets smaller than this, the plot
- * area will become scrollable.
- *
- * @type {number}
- * @apioption chart.scrollablePlotArea.minWidth
- */
- /**
- * The initial scrolling position of the scrollable plot area. Ranges from 0 to
- * 1, where 0 aligns the plot area to the left and 1 aligns it to the right.
- * Typically we would use 1 if the chart has right aligned Y axes.
- *
- * @type {number}
- * @apioption chart.scrollablePlotArea.scrollPositionX
- */
- addEvent(Chart, 'afterSetChartSize', function (e) {
- var scrollablePlotArea = this.options.chart.scrollablePlotArea,
- scrollableMinWidth =
- scrollablePlotArea && scrollablePlotArea.minWidth,
- scrollablePixels;
- if (scrollableMinWidth && !this.renderer.forExport) {
- // The amount of pixels to scroll, the difference between chart
- // width and scrollable width
- this.scrollablePixels = scrollablePixels = Math.max(
- 0,
- scrollableMinWidth - this.chartWidth
- );
- if (scrollablePixels) {
- this.plotWidth += scrollablePixels;
- this.clipBox.width += scrollablePixels;
- if (!e.skipAxes) {
- this.axes.forEach(function (axis) {
- if (axis.side === 1) {
- // Get the plot lines right in getPlotLinePath,
- // temporarily set it to the adjusted plot width.
- axis.getPlotLinePath = function () {
- var right = this.right,
- path;
- this.right = right - axis.chart.scrollablePixels;
- path = H.Axis.prototype.getPlotLinePath.apply(
- this,
- arguments
- );
- this.right = right;
- return path;
- };
- } else {
- // Apply the corrected plotWidth
- axis.setAxisSize();
- axis.setAxisTranslation();
- }
- });
- }
- }
- }
- });
- addEvent(Chart, 'render', function () {
- if (this.scrollablePixels) {
- if (this.setUpScrolling) {
- this.setUpScrolling();
- }
- this.applyFixed();
- } else if (this.fixedDiv) { // Has been in scrollable mode
- this.applyFixed();
- }
- });
- /**
- * @private
- * @function Highcharts.Chart#setUpScrolling
- */
- Chart.prototype.setUpScrolling = function () {
- // Add the necessary divs to provide scrolling
- this.scrollingContainer = H.createElement('div', {
- 'className': 'highcharts-scrolling'
- }, {
- overflowX: 'auto',
- WebkitOverflowScrolling: 'touch'
- }, this.renderTo);
- this.innerContainer = H.createElement('div', {
- 'className': 'highcharts-inner-container'
- }, null, this.scrollingContainer);
- // Now move the container inside
- this.innerContainer.appendChild(this.container);
- // Don't run again
- this.setUpScrolling = null;
- };
- /**
- * @private
- * @function Highcharts.Chart#applyFixed
- */
- Chart.prototype.applyFixed = function () {
- var container = this.container,
- fixedRenderer,
- scrollableWidth,
- firstTime = !this.fixedDiv;
- // First render
- if (firstTime) {
- this.fixedDiv = H.createElement(
- 'div',
- {
- className: 'highcharts-fixed'
- },
- {
- position: 'absolute',
- overflow: 'hidden',
- pointerEvents: 'none',
- zIndex: 2
- },
- null,
- true
- );
- this.renderTo.insertBefore(
- this.fixedDiv,
- this.renderTo.firstChild
- );
- this.renderTo.style.overflow = 'visible';
- this.fixedRenderer = fixedRenderer = new H.Renderer(
- this.fixedDiv,
- 0,
- 0
- );
- // Mask
- this.scrollableMask = fixedRenderer.path()
- .attr({
- fill: H.color(
- this.options.chart.backgroundColor || '#fff'
- ).setOpacity(0.85).get(),
- zIndex: -1
- })
- .addClass('highcharts-scrollable-mask')
- .add();
- // These elements are moved over to the fixed renderer and stay fixed
- // when the user scrolls the chart.
- ([
- this.inverted ?
- '.highcharts-xaxis' :
- '.highcharts-yaxis',
- this.inverted ?
- '.highcharts-xaxis-labels' :
- '.highcharts-yaxis-labels',
- '.highcharts-contextbutton',
- '.highcharts-credits',
- '.highcharts-legend',
- '.highcharts-subtitle',
- '.highcharts-title',
- '.highcharts-legend-checkbox'
- ]).forEach(function (className) {
- [].forEach.call(
- container.querySelectorAll(className),
- function (elem) {
- (
- elem.namespaceURI === fixedRenderer.SVG_NS ?
- fixedRenderer.box :
- fixedRenderer.box.parentNode
- ).appendChild(elem);
- elem.style.pointerEvents = 'auto';
- }
- );
- });
- }
- // Set the size of the fixed renderer to the visible width
- this.fixedRenderer.setSize(
- this.chartWidth,
- this.chartHeight
- );
- // Increase the size of the scrollable renderer and background
- scrollableWidth = this.chartWidth + this.scrollablePixels;
- H.stop(this.container);
- this.container.style.width = scrollableWidth + 'px';
- this.renderer.boxWrapper.attr({
- width: scrollableWidth,
- height: this.chartHeight,
- viewBox: [0, 0, scrollableWidth, this.chartHeight].join(' ')
- });
- this.chartBackground.attr({ width: scrollableWidth });
- // Set scroll position
- if (firstTime) {
- var options = this.options.chart.scrollablePlotArea;
- if (options.scrollPositionX) {
- this.scrollingContainer.scrollLeft =
- this.scrollablePixels * options.scrollPositionX;
- }
- }
- // Mask behind the left and right side
- var axisOffset = this.axisOffset,
- maskTop = this.plotTop - axisOffset[0] - 1,
- maskBottom = this.plotTop + this.plotHeight + axisOffset[2],
- maskPlotRight = this.plotLeft + this.plotWidth -
- this.scrollablePixels;
- this.scrollableMask.attr({
- d: this.scrollablePixels ? [
- // Left side
- 'M', 0, maskTop,
- 'L', this.plotLeft - 1, maskTop,
- 'L', this.plotLeft - 1, maskBottom,
- 'L', 0, maskBottom,
- 'Z',
- // Right side
- 'M', maskPlotRight, maskTop,
- 'L', this.chartWidth, maskTop,
- 'L', this.chartWidth, maskBottom,
- 'L', maskPlotRight, maskBottom,
- 'Z'
- ] : ['M', 0, 0]
- });
- };
|