Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improv: add custom modifier example #88

Merged
merged 1 commit into from
May 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions example/lib/pages/polygon_custom.dart
Original file line number Diff line number Diff line change
@@ -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,57 @@ class PolygonCustomPage extends StatelessWidget {
);
}
}

const _kBaseGroupPaddingHorizontal = 32.0;
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 groups, Map<String, ScaleConv<dynamic, num>> scales,
AlgForm form, CoordConv coord, Offset origin) {
final xField = form.first[0];
final band = (scales[xField]! as DiscreteScaleConv).band;

final ratio = 1 / groups.length;
final numGroups = groups.length;
final groupHorizontalPadding = _kBaseGroupPaddingHorizontal / numGroups;
final invertedGroupPaddingHorizontal =
coord.invertDistance(groupHorizontalPadding, Dim.x);

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 groups) {
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;
}
}
2 changes: 1 addition & 1 deletion lib/src/geom/modifier/modifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import 'package:graphic/src/shape/shape.dart';
/// Rendering customization should be in the [Shape].
abstract class Modifier extends CustomizableSpec {
/// Modifies the position of element items.
///
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Result of running flutter format ., which was failing the "ci" GitHub Action

///
/// The aesthetic attributes are in the [groups].
void modify(
AesGroups groups,
Expand Down