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

Question: How to create this chart #287

Open
Guysanches opened this issue Mar 5, 2024 · 0 comments
Open

Question: How to create this chart #287

Guysanches opened this issue Mar 5, 2024 · 0 comments

Comments

@Guysanches
Copy link

Guysanches commented Mar 5, 2024

How can I make the tooltip identify bar and line grouping data? Instead of selecting one piece of data at a time.

image

const teste = [{
'index': 0,
'year': 'Abr/23',
'type': 'type1',
'value': 12.33,
'average': 17.58
},
{
'index': 1,
'year': 'Maio/23',
'type': 'type1',
'value': 12.33,
'average': 17.82
},
{
'index': 0,
'year': 'Abr/23',
'type': 'type2',
'value': 27.28,
'average': 17.58
},
{
'index': 1,
'year': 'Maio/23',
'type': 'type2',
'value': 27.76,
'average': 17.82
},]

const _kBaseGroupPaddingHorizontal = 32.0;
const _kMinBarSize = 4.0;

/// Changes the position of marks while also updating their width to match
/// the number of marks in a single band. Useful for bar charts when the
/// width of the bars can be dynamic.
@immutable
class DodgeSizeModifier extends Modifier {
@OverRide
AttributesGroups modify(
AttributesGroups 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 maxWidthPerAttributes = maxWidthInBand / numGroups;
final barHorizontalPadding = groupHorizontalPadding / 2;
final size =
    max(maxWidthPerAttributes - barHorizontalPadding, _kMinBarSize);

final bias = ratio * effectiveBand;

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

final AttributesGroups rst = [];
for (final group in groups) {
  final groupRst = <Attributes>[];
  for (final attributes in group) {
    final oldPosition = attributes.position;

    groupRst.add(Attributes(
      index: attributes.index,
      tag: attributes.tag,
      position: oldPosition
          .map(
            (point) => Offset(point.dx + accumulated + bias, point.dy),
          )
          .toList(),
      shape: attributes.shape,
      color: attributes.color,
      gradient: attributes.gradient,
      elevation: attributes.elevation,
      label: attributes.label,
      size: size,
    ));
  }
  rst.add(groupRst);
  accumulated += bias;
}

return rst;

}

@OverRide
bool equalTo(Object other) {
return super == other;
}
}

class ChartTest extends StatelessWidget {
const ChartTest({super.key});

@OverRide
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Center(
child: Column(
children: [
Container(
margin: const EdgeInsets.only(top: 10),
width: 600,
height: 300,
child: Chart(
data: teste,
variables: {
'index': Variable(
accessor: (Map map) => map['index'].toString(),
),
'year': Variable(
accessor: (Map map) => map['year'] as String,
),
'type': Variable(
accessor: (Map map) => map['type'] as String,
),
'value': Variable(
accessor: (Map map) =>
map['value'] is num ? map['value'] as num : 0.0,
),
'average': Variable(
accessor: (Map map) =>
map['average'] is num ? map['average'] as num : 0.0,
),
},
marks: [
IntervalMark(
position: Varset('index') * Varset('value') / Varset('type'),
color: ColorEncode(
variable: 'type',
values: Defaults.colors2,
updaters: {
'tap': {false: (color) => color.withAlpha(100)}
}),
size: SizeEncode(value: 6),
modifiers: [DodgeSizeModifier()],
),
LineMark(
position:
Varset('index') * Varset('average') / Varset('type'),
color: ColorEncode(
value: Defaults.average,
//variable: 'average',
updaters: {
'tap': {false: (color) => color.withAlpha(100)}
}),
)
],
axes: [
AxisGuide(
tickLine: TickLine(),
variable: 'year',
label: LabelStyle(
rotation: 120,
textStyle: const TextStyle(
fontSize: 10,
color: Colors.black,
),
offset: const Offset(0, 7.5),
),
),
Defaults.verticalAxis,
],
selections: {
'tap': PointSelection(
dim: Dim.x,
nearest: true,
)
},
tooltip: TooltipGuide(),
),
),
],
),
)));
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant