import { ChartInternal } from './core' function c3LogScale(d3, linearScale?, logScale?) { var PROJECTION = [0.01, 10] if (!linearScale) { linearScale = d3.scaleLinear() linearScale.range(PROJECTION) } if (!logScale) { logScale = d3.scaleLog() logScale.domain(PROJECTION) logScale.nice() } // copied from https://github.com/compute-io/logspace function logspace(a, b, len) { var arr, end, tmp, d if (arguments.length < 3) { len = 10 } else { if (len === 0) { return [] } } // Calculate the increment: end = len - 1 d = (b - a) / end // Build the output array... arr = new Array(len) tmp = a arr[0] = Math.pow(10, tmp) for (var i = 1; i < end; i++) { tmp += d arr[i] = Math.pow(10, tmp) } arr[end] = Math.pow(10, b) return arr } function scale(x) { return logScale(linearScale(x)) } scale.domain = function(x) { if (!arguments.length) { return linearScale.domain() } linearScale.domain(x) return scale } scale.range = function(x) { if (!arguments.length) { return logScale.range() } logScale.range(x) return scale } scale.ticks = function(m) { return logspace(-2, 1, m || 10).map(function(v) { return linearScale.invert(v) }) } scale.copy = function() { return c3LogScale(d3, linearScale.copy(), logScale.copy()) } return scale } ChartInternal.prototype.getScale = function(min, max, forTimeseries) { return (forTimeseries ? this.d3.scaleTime() : this.d3.scaleLinear()).range([ min, max ]) } ChartInternal.prototype.getX = function(min, max, domain, offset) { var $$ = this, scale = $$.getScale(min, max, $$.isTimeSeries()), _scale = domain ? scale.domain(domain) : scale, key // Define customized scale if categorized axis if ($$.isCategorized()) { offset = offset || function() { return 0 } scale = function(d, raw) { var v = _scale(d) + offset(d) return raw ? v : Math.ceil(v) } } else { scale = function(d, raw) { var v = _scale(d) return raw ? v : Math.ceil(v) } } // define functions for (key in _scale) { scale[key] = _scale[key] } scale.orgDomain = function() { return _scale.domain() } // define custom domain() for categorized axis if ($$.isCategorized()) { scale.domain = function(domain) { if (!arguments.length) { domain = this.orgDomain() return [domain[0], domain[1] + 1] } _scale.domain(domain) return scale } } return scale } /** * Creates and configures a D3 scale instance for the given type. * * By defaults it returns a Linear scale. * * @param {String} type Type of d3-scale to create. Type can be 'linear', 'time', 'timeseries' or 'log'. * @param {Array} domain The scale domain such as [from, to] * @param {Array} range The scale's range such as [from, to] * * @return A d3-scale instance */ ChartInternal.prototype.getY = function(type, domain, range) { let scale if (type === 'timeseries' || type === 'time') { scale = this.d3.scaleTime() } else if (type === 'log') { scale = c3LogScale(this.d3) } else if (type === 'linear' || type === undefined) { scale = this.d3.scaleLinear() } else { throw new Error(`Invalid Y axis type: "${type}"`) } if (domain) { scale.domain(domain) } if (range) { scale.range(range) } return scale } ChartInternal.prototype.getYScale = function(id) { return this.axis.getId(id) === 'y2' ? this.y2 : this.y } ChartInternal.prototype.getSubYScale = function(id) { return this.axis.getId(id) === 'y2' ? this.subY2 : this.subY } ChartInternal.prototype.updateScales = function() { var $$ = this, config = $$.config, forInit = !$$.x // update edges $$.xMin = config.axis_rotated ? 1 : 0 $$.xMax = config.axis_rotated ? $$.height : $$.width $$.yMin = config.axis_rotated ? 0 : $$.height $$.yMax = config.axis_rotated ? $$.width : 1 $$.subXMin = $$.xMin $$.subXMax = $$.xMax $$.subYMin = config.axis_rotated ? 0 : $$.height2 $$.subYMax = config.axis_rotated ? $$.width2 : 1 // update scales $$.x = $$.getX( $$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function() { return $$.xAxis.tickOffset() } ) $$.y = $$.getY( config.axis_y_type, forInit ? config.axis_y_default : $$.y.domain(), [$$.yMin, $$.yMax] ) $$.y2 = $$.getY( config.axis_y2_type, forInit ? config.axis_y2_default : $$.y2.domain(), [$$.yMin, $$.yMax] ) $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function(d) { return d % 1 ? 0 : $$.subXAxis.tickOffset() }) $$.subY = $$.getY( config.axis_y_type, forInit ? config.axis_y_default : $$.subY.domain(), [$$.subYMin, $$.subYMax] ) $$.subY2 = $$.getY( config.axis_y2_type, forInit ? config.axis_y2_default : $$.subY2.domain(), [$$.subYMin, $$.subYMax] ) // update axes $$.xAxisTickFormat = $$.axis.getXAxisTickFormat() $$.xAxisTickValues = $$.axis.getXAxisTickValues() $$.yAxisTickValues = $$.axis.getYAxisTickValues() $$.y2AxisTickValues = $$.axis.getY2AxisTickValues() $$.xAxis = $$.axis.getXAxis( $$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer ) $$.subXAxis = $$.axis.getXAxis( $$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer ) $$.yAxis = $$.axis.getYAxis( 'y', $$.y, $$.yOrient, $$.yAxisTickValues, config.axis_y_tick_outer ) $$.y2Axis = $$.axis.getYAxis( 'y2', $$.y2, $$.y2Orient, $$.y2AxisTickValues, config.axis_y2_tick_outer ) // Set initialized scales to brush and zoom if (!forInit) { if ($$.brush) { $$.brush.updateScale($$.subX) } } // update for arc if ($$.updateArc) { $$.updateArc() } }