Skip to content

Commit

Permalink
improv: add custom modifier example
Browse files Browse the repository at this point in the history
  • Loading branch information
bernardobelchior committed Apr 28, 2022
1 parent 4c19e73 commit c9406f2
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 5 deletions.
105 changes: 105 additions & 0 deletions example/lib/pages/polygon_custom.dart
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:graphic/graphic.dart';

Expand Down Expand Up @@ -638,6 +640,54 @@ class PolygonCustomPage extends StatelessWidget {
],
),
),
Container(
child: const Text(
'Custom Modifier',
style: TextStyle(fontSize: 20),
),
padding: const EdgeInsets.fromLTRB(20, 40, 20, 5),
),
Container(
child: const Text(
'- With dodge and size modifier that scales the interval element width to fit within its band',
),
padding: const EdgeInsets.fromLTRB(10, 5, 10, 0),
alignment: Alignment.centerLeft,
),
Container(
margin: const EdgeInsets.only(top: 10),
width: 350,
height: 300,
child: Chart(
padding: (_) => const EdgeInsets.fromLTRB(40, 5, 10, 40),
data: adjustData,
variables: {
'index': Variable(
accessor: (Map map) => map['index'].toString(),
),
'type': Variable(
accessor: (Map map) => map['type'] as String,
),
'value': Variable(
accessor: (Map map) => map['value'] as num,
),
},
elements: [
IntervalElement(
position:
Varset('index') * Varset('value') / Varset('type'),
color: ColorAttr(
variable: 'type', values: Defaults.colors10),
size: SizeAttr(value: 2),
modifiers: [DodgeSizeModifier()],
)
],
axes: [
Defaults.horizontalAxis..tickLine = TickLine(),
Defaults.verticalAxis,
],
),
),
Container(
child: const Text(
'Candlestick Chart',
Expand Down Expand Up @@ -734,3 +784,58 @@ class PolygonCustomPage extends StatelessWidget {
);
}
}

const _kBaseGroupPaddingHorizontal = 32.0;
const _kXAxis = 1;
const _kMinBarSize = 4.0;

/// Changes the position of elements while also updating their width to match
/// the number of elements in a single band. Useful for bar charts when the
/// width of the bars can be dynamic.
@immutable
class DodgeSizeModifier extends Modifier {
@override
void modify(AesGroups aesGroups, Map<String, ScaleConv<dynamic, num>> scales,
AlgForm form, Offset origin) {
final xField = form.first[0];
final band = (scales[xField]! as DiscreteScaleConv).band;

final ratio = 1 / aesGroups.length;
final numGroups = aesGroups.length;
final groupHorizontalPadding = _kBaseGroupPaddingHorizontal / numGroups;
final invertedGroupPaddingHorizontal =
coord.invertDistance(groupHorizontalPadding, _kXAxis);

final effectiveBand = band - 2 * invertedGroupPaddingHorizontal;

final maxWidth = coord.convert(const Offset(1, 0)).dx;
final maxWidthInBand = effectiveBand * maxWidth;
final maxWidthPerAes = maxWidthInBand / numGroups;
final barHorizontalPadding = groupHorizontalPadding / 2;
final size = max(maxWidthPerAes - barHorizontalPadding, _kMinBarSize);

final bias = ratio * effectiveBand;

// Negatively shift half of the total bias.
var accumulated = -bias * (numGroups + 1) / 2;

for (final group in value) {
for (final aes in group) {
final oldPosition = aes.position;
aes.position = oldPosition
.map(
(point) => Offset(point.dx + accumulated + bias, point.dy),
)
.toList();

aes.size = size;
}
accumulated += bias;
}
}

@override
bool equalTo(Object other) {
return super == other;
}
}
10 changes: 5 additions & 5 deletions lib/graphic.dart
Expand Up @@ -126,11 +126,11 @@ export 'src/variable/transform/proportion.dart' show Proportion;
export 'src/variable/transform/sort.dart' show Sort;

export 'src/scale/scale.dart' show Scale, ScaleConv;
export 'src/scale/discrete.dart' show DiscreteScale;
export 'src/scale/continuous.dart' show ContinuousScale;
export 'src/scale/linear.dart' show LinearScale;
export 'src/scale/ordinal.dart' show OrdinalScale;
export 'src/scale/time.dart' show TimeScale;
export 'src/scale/discrete.dart' show DiscreteScale, DiscreteScaleConv;
export 'src/scale/continuous.dart' show ContinuousScale, ContinuousScaleConv;
export 'src/scale/linear.dart' show LinearScale, LinearScaleConv;
export 'src/scale/ordinal.dart' show OrdinalScale, OrdinalScaleConv;
export 'src/scale/time.dart' show TimeScale, TimeScaleConv;

export 'src/geom/element.dart' show GeomElement;
export 'src/geom/function.dart' show FunctionElement;
Expand Down

0 comments on commit c9406f2

Please sign in to comment.