Skip to content

Commit

Permalink
v2.0.3
Browse files Browse the repository at this point in the history
  • Loading branch information
entronad committed Apr 12, 2023
1 parent f9a9490 commit b2b3e76
Show file tree
Hide file tree
Showing 17 changed files with 251 additions and 138 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 2.0.3

**2023-04-12**

- Fix the Modifier error when updating: https://github.com/entronad/graphic/issues/206
- Rename enum property `MarkEntrance.alpha` to `MarkEntrance.opacity`.
- Fix polygon shape when there is only one datum or one value in a dim: https://github.com/entronad/graphic/issues/166

## 2.0.2

**2023-04-06**
Expand Down
10 changes: 9 additions & 1 deletion DEVLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -502,4 +502,12 @@ tagEncode 先不要搞默认值了,变量情况复杂不要弄巧成拙,只

内部工具函数,尽量保留位置参数或必选参数,哪怕填null,减少错误

dart似乎有这样一个规定:当import一般lib(import “library: ... 或文件)时,类名不能冲突。但一个是基础库(例如ui)一个是一般lib时没关系,以一般lib优先。ui.Gradient 和 painting.Gradient 是这种情况,ui.Scene 和 graphic.Scene 是这种情况。原则:凡是和官方库(ui,flutter,painting)冲突的命名都要避免,因此这里也要避免。主要采用增加前缀的方法。因此 View 改为 ChartView,Scene改为MarkScene。至于引擎里的Mark一词是否准确,现在先不想了,这里如果要变体系要变,后面3.0再说吧,这里就这样
dart似乎有这样一个规定:当import一般lib(import “library: ... 或文件)时,类名不能冲突。但一个是基础库(例如ui)一个是一般lib时没关系,以一般lib优先。ui.Gradient 和 painting.Gradient 是这种情况,ui.Scene 和 graphic.Scene 是这种情况。原则:凡是和官方库(ui,flutter,painting)冲突的命名都要避免,因此这里也要避免。主要采用增加前缀的方法。因此 View 改为 ChartView,Scene改为MarkScene。至于引擎里的Mark一词是否准确,现在先不想了,这里如果要变体系要变,后面3.0再说吧,这里就这样

Tuple value 应该还是不接受null:1.这是dart null-safety 倡导的原则,2.已经有了accessor这个处理环节

现在这种修改式的 Modifier 实现是不行的,非幂等,https://github.com/entronad/graphic/issues/206 就是非幂等引起的。整个dataflow op的原则必须是函数式的,幂等的。其它倒不是原则性问题,要求幂等正是为了避免其它问题。

类方法的参数,与类成员名字冲突时,将类方法的参数用缩写,特别是含义明确的 withXX,参考Color.withAlpha

至少目前,参数定义的原则涉及多个维度的还是以list定义为主,而不是分开 aaX, aaY这样,比如 CrosshairCuide, list 成员可以为null,以达到一个设置一个不设置的效果,不要搞单独元素指代两个相同这种,取数用 [0] [1]
2 changes: 1 addition & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final routes = {
'/examples/Animation': (context) => const AnimationPage(),
'/examples/Bigdata': (context) => BigdataPage(),
'/examples/Echarts': (context) => EchartsPage(),
'/examples/Debug': (context) => const DebugPage(),
'/examples/Debug': (context) => DebugPage(),
};

class MyApp extends StatelessWidget {
Expand Down
4 changes: 2 additions & 2 deletions example/lib/pages/animation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -373,13 +373,13 @@ class AnimationPageState extends State<AnimationPage> {
Defaults.colors10.first.withAlpha(10),
])),
transition: Transition(duration: Duration(seconds: 2)),
entrance: {MarkEntrance.x, MarkEntrance.y, MarkEntrance.alpha},
entrance: {MarkEntrance.x, MarkEntrance.y, MarkEntrance.opacity},
),
LineMark(
shape: ShapeEncode(value: BasicLineShape(smooth: true)),
size: SizeEncode(value: 0.5),
transition: Transition(duration: Duration(seconds: 2)),
entrance: {MarkEntrance.x, MarkEntrance.y, MarkEntrance.alpha},
entrance: {MarkEntrance.x, MarkEntrance.y, MarkEntrance.opacity},
),
],
axes: [
Expand Down
161 changes: 85 additions & 76 deletions example/lib/pages/debug.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,95 +3,104 @@ import 'package:graphic/graphic.dart';

import '../data.dart';

const adjustData = [
{"type": "Email", "index": 0, "value": 120},
{"type": "Email", "index": 1, "value": 132},
{"type": "Email", "index": 2, "value": 101},
{"type": "Email", "index": 3, "value": 134},
{"type": "Email", "index": 4, "value": 90},
{"type": "Email", "index": 5, "value": 230},
{"type": "Email", "index": 6, "value": 210},
{"type": "Affiliate", "index": 0, "value": 220},
{"type": "Affiliate", "index": 1, "value": 182},
{"type": "Affiliate", "index": 2, "value": 191},
{"type": "Affiliate", "index": 3, "value": 234},
{"type": "Affiliate", "index": 4, "value": 290},
{"type": "Affiliate", "index": 5, "value": 330},
{"type": "Affiliate", "index": 6, "value": 310},
{"type": "Video", "index": 0, "value": 150},
{"type": "Video", "index": 1, "value": 232},
{"type": "Video", "index": 2, "value": 201},
{"type": "Video", "index": 3, "value": 154},
{"type": "Video", "index": 4, "value": 190},
{"type": "Video", "index": 5, "value": 330},
{"type": "Video", "index": 6, "value": 410},
{"type": "Direct", "index": 0, "value": 320},
{"type": "Direct", "index": 1, "value": 332},
{"type": "Direct", "index": 2, "value": 301},
{"type": "Direct", "index": 3, "value": 334},
{"type": "Direct", "index": 4, "value": 390},
{"type": "Direct", "index": 5, "value": 330},
{"type": "Direct", "index": 6, "value": 320},
{"type": "Search", "index": 0, "value1": 320},
{"type": "Search", "index": 1, "value1": 432},
{"type": "Search", "index": 2, "value1": 401},
{"type": "Search", "index": 3, "value1": 434},
{"type": "Search", "index": 4, "value1": 390},
{"type": "Search", "index": 5, "value1": 430},
{"type": "Search", "index": 6, "value1": 420},
];

class DebugPage extends StatelessWidget {
const DebugPage({Key? key}) : super(key: key);
DebugPage({Key? key}) : super(key: key);

final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: const EdgeInsets.only(top: 10),
width: 350,
height: 300,
child: Chart(
rebuild: true,
data: basicData,
variables: {
'genre': Variable(
accessor: (Map map) => map['genre'] as String,
),
'sold': Variable(
accessor: (Map map) => map['sold'] as num,
),
},
marks: [
IntervalMark(
label: LabelEncode(
encoder: (tuple) => Label(tuple['sold'].toString())),
elevation: ElevationEncode(value: 0, updaters: {
'tap': {true: (_) => 5}
}),
color: ColorEncode(value: Defaults.primaryColor, updaters: {
'tap': {false: (color) => color.withAlpha(100)}
}),
selected: {
'tap': {0}
},
)
],
axes: [
Defaults.horizontalAxis,
Defaults.verticalAxis,
key: _scaffoldKey,
appBar: AppBar(
title: const Text('Rectangle Interval Mark'),
),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Center(
child: Column(
children: <Widget>[

buildChart('single point', [Data(0, 5, 1)]),
buildChart('2 points in the same sector at different radiuses',
[Data(0, 5, 1), Data(0, 6, 2)]),
buildChart('2 points with different sector and radius',
[Data(0, 5, 1), Data(4, 6, 2)]),
buildChart('3 points with different everything',
[Data(0, 5, 1), Data(1, 6, 2), Data(2, 7, 3)]),
buildChart('3 points with a duplicate',
[Data(0, 5, 1), Data(1, 6, 2), Data(1, 6, 2)]),


],
selections: {'tap': PointSelection(dim: Dim.x)},
tooltip: TooltipGuide(),
crosshair: CrosshairGuide(),
),
),
),
);
}
}
Widget buildChart(String name, List<Data> data) => Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(width: 300, child: Text(name)),
SizedBox(width: 100),
Container(
width: 150,
height: 150,
child: Chart(
data: data,
variables: {
'sector': Variable(
accessor: (Data d) => d.sector.toString(),
scale: OrdinalScale(
values: List<int>.generate(10, (i) => i++)
.map((s) => s.toString())
.toList(),
),
),
'radius': Variable(
accessor: (Data d) => d.radius,
scale: LinearScale(
min: 0,
max: 10,
),
),
'value': Variable(
accessor: (Data d) => d.value,
scale: LinearScale(
min: 0,
max: 10,
),
),
},
marks: [
PolygonMark(
shape: ShapeEncode(value: HeatmapShape(sector: true, tileCounts: [10, 10])),
color: ColorEncode(
variable: 'value',
values: [Colors.blue, Colors.red],
),
)
],
coord: PolarCoord(),
axes: [
Defaults.circularAxis,
Defaults.radialAxis,
],
),
),
],

);


class Data {
final int sector;
final double radius;
final double value;

Data(this.sector, this.radius, this.value);
}
// class DebugPage extends StatefulWidget {
// const DebugPage({Key? key}) : super(key: key);

Expand Down
3 changes: 3 additions & 0 deletions example/lib/pages/interval.dart
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@ class IntervalPage extends StatelessWidget {
modifiers: [StackModifier()],
)
],
coord: RectCoord(
horizontalRangeUpdater: Defaults.horizontalRangeEvent,
),
axes: [
Defaults.horizontalAxis,
Defaults.verticalAxis,
Expand Down
30 changes: 25 additions & 5 deletions example/lib/pages/polygon_custom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,9 @@ class PolygonCustomPage extends StatelessWidget {
modifiers: [DodgeModifier(ratio: 0.1)],
)
],
coord: RectCoord(
horizontalRangeUpdater: Defaults.horizontalRangeEvent,
),
axes: [
Defaults.horizontalAxis..tickLine = TickLine(),
Defaults.verticalAxis,
Expand Down Expand Up @@ -695,6 +698,9 @@ class PolygonCustomPage extends StatelessWidget {
modifiers: [DodgeSizeModifier()],
)
],
coord: RectCoord(
horizontalRangeUpdater: Defaults.horizontalRangeEvent,
),
axes: [
Defaults.horizontalAxis..tickLine = TickLine(),
Defaults.verticalAxis,
Expand Down Expand Up @@ -807,7 +813,7 @@ const _kMinBarSize = 4.0;
@immutable
class DodgeSizeModifier extends Modifier {
@override
void modify(
AttributesGroups modify(
AttributesGroups groups,
Map<String, ScaleConv<dynamic, num>> scales,
AlgForm form,
Expand Down Expand Up @@ -836,19 +842,33 @@ class DodgeSizeModifier extends Modifier {
// 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;
attributes.position = oldPosition

groupRst.add(Attributes(
index: attributes.index,
tag: attributes.tag,
position: oldPosition
.map(
(point) => Offset(point.dx + accumulated + bias, point.dy),
)
.toList();

attributes.size = size;
.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
Expand Down
35 changes: 27 additions & 8 deletions lib/src/dataflow/tuple.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:graphic/src/common/label.dart';
import 'package:graphic/src/coord/coord.dart';
import 'package:graphic/src/graffiti/element/label.dart';
import 'package:graphic/src/mark/mark.dart';
import 'package:graphic/src/mark/modifier/modifier.dart';
import 'package:graphic/src/scale/scale.dart';
import 'package:graphic/src/shape/shape.dart';
import 'package:graphic/src/util/assert.dart';
Expand Down Expand Up @@ -53,29 +54,47 @@ class Attributes {
/// The count of points is determined by the geometry mark type. The values
/// of each point dimension is scaled and normalized value of `[0, 1]`. the position
/// points can be converted to canvas points by [CoordConv].
List<Offset> position;
final List<Offset> position;

/// The shape of the tuple.
Shape shape;
final Shape shape;

/// The color of the tuple.
Color? color;
final Color? color;

/// The gradient of the tuple.
Gradient? gradient;
final Gradient? gradient;

/// The shadow elevation of the tuple.
double? elevation;
final double? elevation;

/// The label of the tuple.
Label? label;
final Label? label;

/// The size of the tuple.
double? size;
final double? size;

/// The represent point of [position] points.
Offset get representPoint => shape.representPoint(position);

/// Returns a new attributes that matches this attributes with the position replaced
/// with [p].
///
/// This method is mainly used for [Modifier]s.
Attributes withPosition(List<Offset> p) => Attributes(
index: index,
tag: tag,
position: p,
shape: shape,
color: color,
gradient: gradient,
elevation: elevation,
label: label,
size: size,
);

/// Returns the original state of an item attributes in animation according to
/// [entrance] type.
Attributes deflate(Set<MarkEntrance> entrance) {
var rst = this;

Expand Down Expand Up @@ -121,7 +140,7 @@ class Attributes {
);
}

if (entrance.contains(MarkEntrance.alpha)) {
if (entrance.contains(MarkEntrance.opacity)) {
final labelColor = rst.label?.style.textStyle?.color;
final labelRst = labelColor == null
? rst.label
Expand Down
Loading

0 comments on commit b2b3e76

Please sign in to comment.