| Index: charted/lib/svg/axis.dart
|
| diff --git a/charted/lib/svg/axis.dart b/charted/lib/svg/axis.dart
|
| deleted file mode 100644
|
| index 81fc756f74f59a517b6d142d47a5a540ab7c57cc..0000000000000000000000000000000000000000
|
| --- a/charted/lib/svg/axis.dart
|
| +++ /dev/null
|
| @@ -1,233 +0,0 @@
|
| -//
|
| -// Copyright 2014 Google Inc. All rights reserved.
|
| -//
|
| -// Use of this source code is governed by a BSD-style
|
| -// license that can be found in the LICENSE file or at
|
| -// https://developers.google.com/open-source/licenses/bsd
|
| -//
|
| -
|
| -library charted.svg.axis;
|
| -
|
| -import 'dart:html' show Element;
|
| -import 'dart:math' as math;
|
| -
|
| -import 'package:charted/core/scales.dart';
|
| -import 'package:charted/core/utils.dart';
|
| -import 'package:charted/selection/selection.dart';
|
| -
|
| -///
|
| -/// [SvgAxis] helps draw chart axes based on a given scale.
|
| -///
|
| -class SvgAxis {
|
| - /// Store of axis roots mapped to currently used scales
|
| - static final _scales = new Expando<Scale>();
|
| -
|
| - /// Orientation of the axis. Defaults to [ORIENTATION_BOTTOM].
|
| - final String orientation;
|
| -
|
| - /// Scale used on this axis
|
| - final Scale scale;
|
| -
|
| - /// Size of all inner ticks
|
| - final num innerTickSize;
|
| -
|
| - /// Size of the outer two ticks
|
| - final num outerTickSize;
|
| -
|
| - /// Padding on the ticks
|
| - final num tickPadding;
|
| -
|
| - /// List of values to be used on the ticks
|
| - List _tickValues;
|
| -
|
| - /// Formatter for the tick labels
|
| - FormatFunction _tickFormat;
|
| -
|
| - SvgAxis({
|
| - this.orientation: ORIENTATION_BOTTOM,
|
| - this.innerTickSize: 6,
|
| - this.outerTickSize: 6,
|
| - this.tickPadding: 3,
|
| - Iterable tickValues,
|
| - FormatFunction tickFormat,
|
| - Scale scale }) : scale = scale == null ? new LinearScale() : scale {
|
| - _tickFormat = tickFormat == null
|
| - ? this.scale.createTickFormatter()
|
| - : tickFormat;
|
| - _tickValues = isNullOrEmpty(tickValues) ? this.scale.ticks : tickValues;
|
| - }
|
| -
|
| - Iterable get tickValues => _tickValues;
|
| -
|
| - FormatFunction get tickFormat => _tickFormat;
|
| -
|
| - /// Draw an axis on each non-null element in selection
|
| - draw(Selection g, {SvgAxisTicks axisTicksBuilder, bool isRTL: false}) =>
|
| - g.each((d, i, e) => create(
|
| - e, g.scope, axisTicksBuilder: axisTicksBuilder, isRTL: isRTL));
|
| -
|
| - /// Create an axis on [element].
|
| - create(Element element, SelectionScope scope, {
|
| - SvgAxisTicks axisTicksBuilder, bool isRTL: false}) {
|
| -
|
| - var group = scope.selectElements([element]),
|
| - older = _scales[element],
|
| - current = _scales[element] = scale.clone(),
|
| - isInitialRender = older == null;
|
| -
|
| - var isLeft = orientation == ORIENTATION_LEFT,
|
| - isRight = !isLeft && orientation == ORIENTATION_RIGHT,
|
| - isVertical = isLeft || isRight,
|
| - isBottom = !isVertical && orientation == ORIENTATION_BOTTOM,
|
| - isTop = !(isVertical || isBottom) && orientation == ORIENTATION_TOP,
|
| - isHorizontal = !isVertical;
|
| -
|
| - if (older == null) older = current;
|
| - if (axisTicksBuilder == null) {
|
| - axisTicksBuilder = new SvgAxisTicks();
|
| - }
|
| - axisTicksBuilder.init(this);
|
| -
|
| - var values = axisTicksBuilder.ticks,
|
| - formatted = axisTicksBuilder.formattedTicks,
|
| - ellipsized = axisTicksBuilder.shortenedTicks;
|
| -
|
| - var ticks = group.selectAll('.tick').data(values, current.scale),
|
| - exit = ticks.exit,
|
| - transform = isVertical ? _yAxisTransform : _xAxisTransform,
|
| - sign = isTop || isLeft ? -1 : 1,
|
| - isEllipsized = ellipsized != formatted;
|
| -
|
| - var enter = ticks.enter.appendWithCallback((d, i, e) {
|
| - var group = Namespace.createChildElement('g', e)
|
| - ..attributes['class'] = 'tick'
|
| - ..append(Namespace.createChildElement('line', e))
|
| - ..append(Namespace.createChildElement('text', e)
|
| - ..attributes['dy'] =
|
| - isVertical ? '0.32em' : (isBottom ? '0.71em' : '0'));
|
| - if (!isInitialRender) {
|
| - group.style.setProperty('opacity', EPSILON.toString());
|
| - }
|
| - return group;
|
| - });
|
| -
|
| - // All attributes/styles/classes that may change due to theme and scale.
|
| - // TODO(prsd): Order elements before updating ticks.
|
| - ticks.each((d, i, e) {
|
| - Element line = e.firstChild;
|
| - Element text = e.lastChild;
|
| - bool isRTLText = false; // FIXME(prsd)
|
| -
|
| - if (isHorizontal) {
|
| - line.attributes['y2'] = '${sign * innerTickSize}';
|
| - text.attributes['y'] =
|
| - '${sign * (math.max(innerTickSize, 0) + tickPadding)}';
|
| -
|
| - if (axisTicksBuilder.rotation != 0) {
|
| - text.attributes
|
| - ..['transform'] =
|
| - 'rotate(${(isRTL ? -1 : 1) * axisTicksBuilder.rotation})'
|
| - ..['text-anchor'] = isRTL ? 'end' : 'start';
|
| - } else {
|
| - text.attributes
|
| - ..remove('transform')
|
| - ..['text-anchor'] = 'middle';
|
| - }
|
| - } else {
|
| - line.attributes['x2'] = '${sign * innerTickSize}';
|
| - text.attributes
|
| - ..['x'] = '${sign * (math.max(innerTickSize, 0) + tickPadding)}'
|
| - ..['text-anchor'] = isLeft
|
| - ? (isRTLText ? 'start' : 'end')
|
| - : (isRTLText ? 'end' : 'start');
|
| - }
|
| -
|
| - text.text = fixSimpleTextDirection(ellipsized.elementAt(i));
|
| - if (isEllipsized) {
|
| - text.attributes['data-detail'] = formatted.elementAt(i);
|
| - } else {
|
| - text.attributes.remove('data-detail');
|
| - }
|
| -
|
| - if (isInitialRender) {
|
| - var dx = current is OrdinalScale ? current.rangeBand / 2 : 0;
|
| - e.attributes['transform'] = isHorizontal
|
| - ? 'translate(${current.scale(d) + dx},0)'
|
| - : 'translate(0,${current.scale(d) + dx})';
|
| - } else {
|
| - e.style.setProperty('opacity', '1.0');
|
| - }
|
| - });
|
| -
|
| - // Transition existing ticks to right positions
|
| - if (!isInitialRender) {
|
| - var transformFn;
|
| - if (current is OrdinalScale && current.rangeBand != 0) {
|
| - var dx = current.rangeBand / 2;
|
| - transformFn = (d) => current.scale(d) + dx;
|
| - } else if (older is OrdinalScale && older.rangeBand != 0) {
|
| - older = current;
|
| - } else {
|
| - transform(ticks, current.scale);
|
| - }
|
| -
|
| - transform(enter, transformFn != null ? transformFn : older.scale);
|
| - transform(ticks, transformFn != null ? transformFn : current.scale);
|
| - }
|
| -
|
| - exit.remove();
|
| -
|
| - // Append the outer domain.
|
| - var path = element.querySelector('.domain'),
|
| - tickSize = sign * outerTickSize,
|
| - range = current.rangeExtent;
|
| - if (path == null) {
|
| - path = Namespace.createChildElement('path', element)
|
| - ..setAttribute('class', 'domain');
|
| - }
|
| - path.attributes['d'] = isLeft || isRight
|
| - ? 'M${tickSize},${range.min}H0V${range.max}H${tickSize}'
|
| - : 'M${range.min},${tickSize}V0H${range.max}V${tickSize}';
|
| - element.append(path);
|
| - }
|
| -
|
| - _xAxisTransform(Selection selection, transformFn) {
|
| - selection.transition()
|
| - ..attrWithCallback(
|
| - 'transform', (d, i, e) => 'translate(${transformFn(d)},0)');
|
| - }
|
| -
|
| - _yAxisTransform(Selection selection, transformFn) {
|
| - selection.transition()
|
| - ..attrWithCallback(
|
| - 'transform', (d, i, e) => 'translate(0,${transformFn(d)})');
|
| - }
|
| -}
|
| -
|
| -/// Interface and the default implementation of [SvgAxisTicks].
|
| -/// SvgAxisTicks provides strategy to handle overlapping ticks on an
|
| -/// axis. Default implementation assumes that the ticks don't overlap.
|
| -class SvgAxisTicks {
|
| - int _rotation = 0;
|
| - Iterable _ticks;
|
| - Iterable _formattedTicks;
|
| -
|
| - void init(SvgAxis axis) {
|
| - _ticks = axis.tickValues;
|
| - _formattedTicks = _ticks.map((x) => axis.tickFormat(x));
|
| - }
|
| -
|
| - /// When non-zero, indicates the angle by which each tick value must be
|
| - /// rotated to avoid the overlap.
|
| - int get rotation => _rotation;
|
| -
|
| - /// List of ticks that will be displayed on the axis.
|
| - Iterable get ticks => _ticks;
|
| -
|
| - /// List of formatted ticks values.
|
| - Iterable get formattedTicks => _formattedTicks;
|
| -
|
| - /// List of clipped tick values, if they had to be clipped. Must be same
|
| - /// as the [formattedTicks] if none of the ticks were ellipsized.
|
| - Iterable get shortenedTicks => _formattedTicks;
|
| -}
|
|
|