Skip to content

Commit

Permalink
Implement drawTo method
Browse files Browse the repository at this point in the history
  • Loading branch information
n-bernat committed May 5, 2024
1 parent fcb1244 commit 5a47408
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 38 deletions.
4 changes: 4 additions & 0 deletions flutter_kanjivg/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.0.3

- Implemented `drawTo` method.

## 0.0.2

- Added a screenshot.
Expand Down
34 changes: 34 additions & 0 deletions flutter_kanjivg/lib/src/extensions/kvg_data_extension.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'dart:ui' as ui;

import 'package:kanjivg/kanjivg.dart';
import 'package:vector_graphics_compiler/vector_graphics_compiler.dart'
as compiler;

/// Extension methods for the [KvgData] class.
extension KvgDataExtension on KvgData {
/// Creates a [ui.Path] object from the paths of this [KvgData] instance.
ui.Path createPath() {
final path = ui.Path();
for (final data in paths) {
final pathData = compiler.parseSvgPathData(data);
for (final command in pathData.commands) {
if (command is compiler.LineToCommand) {
path.lineTo(command.x, command.y);
} else if (command is compiler.MoveToCommand) {
path.moveTo(command.x, command.y);
} else if (command is compiler.CubicToCommand) {
path.cubicTo(
command.x1,
command.y1,
command.x2,
command.y2,
command.x3,
command.y3,
);
}
}
}

return path;
}
}
32 changes: 32 additions & 0 deletions flutter_kanjivg/lib/src/extensions/path_extension.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'dart:ui';
import 'package:vector_graphics_compiler/vector_graphics_compiler.dart'
as compiler;

/// Extension methods for the [Path] class.
extension PathExtension on Path {
/// Draws a command on this path.
void drawCommand(compiler.PathCommand command) {
if (command is compiler.LineToCommand) {
lineTo(command.x, command.y);
} else if (command is compiler.MoveToCommand) {
moveTo(command.x, command.y);
} else if (command is compiler.CubicToCommand) {
cubicTo(
command.x1,
command.y1,
command.x2,
command.y2,
command.x3,
command.y3,
);
}
}

/// Draws a collection of commands on this path.
void drawCommands(Iterable<compiler.PathCommand> commands) =>
commands.forEach(drawCommand);

/// Total length of this path.
double computeLength() => computeMetrics()
.fold<double>(0, (previous, metric) => previous + metric.length);
}
40 changes: 2 additions & 38 deletions flutter_kanjivg/lib/src/kanji_canvas.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import 'dart:ui' as ui;

import 'package:flutter/widgets.dart';
import 'package:flutter_kanjivg/src/extensions/kvg_data_extension.dart';
import 'package:flutter_kanjivg/src/kanji_controller.dart';
import 'package:kanjivg/kanjivg.dart';
import 'package:vector_graphics_compiler/vector_graphics_compiler.dart'
as compiler;

/// A widget that provides a canvas on which to draw a kanji character.
///
Expand Down Expand Up @@ -72,36 +69,6 @@ class _KanjiPainter extends CustomPainter {
final Color color;
final Color? hintColor;

ui.Path? createPath() {
final paths = controller.data?.paths;
if (paths == null) {
return null;
}

final path = ui.Path();
for (final data in paths) {
final pathData = compiler.parseSvgPathData(data);
for (final command in pathData.commands) {
if (command is compiler.LineToCommand) {
path.lineTo(command.x, command.y);
} else if (command is compiler.MoveToCommand) {
path.moveTo(command.x, command.y);
} else if (command is compiler.CubicToCommand) {
path.cubicTo(
command.x1,
command.y1,
command.x2,
command.y2,
command.x3,
command.y3,
);
}
}
}

return path;
}

Path createAnimatedPath(Path path, double progress) {
final totalLength = path
.computeMetrics()
Expand Down Expand Up @@ -147,10 +114,7 @@ class _KanjiPainter extends CustomPainter {
}

// Create a path based on SVG paths.
final basePath = createPath();
if (basePath == null) {
return;
}
final basePath = data.createPath();

// Initialize Paint with custom settings.
final paint = Paint()
Expand Down
45 changes: 45 additions & 0 deletions flutter_kanjivg/lib/src/kanji_controller.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import 'dart:ui' as ui;

import 'package:flutter/animation.dart';
import 'package:flutter_kanjivg/src/extensions/kvg_data_extension.dart';
import 'package:flutter_kanjivg/src/extensions/path_extension.dart';
import 'package:kanjivg/kanjivg.dart';
import 'package:vector_graphics_compiler/vector_graphics_compiler.dart'
as compiler;

/// A controller for an animation of a kanji.
///
Expand Down Expand Up @@ -52,6 +58,45 @@ class KanjiController extends AnimationController {
return future;
}

/// Draw the character to a specific stroke.
TickerFuture drawTo(
int stroke, {
Duration? duration,
Curve curve = Curves.linear,
}) {
// Early return if there's no character to animate.
if (_data == null) {
TickerFuture.complete();
}

assert(
stroke <= _data!.paths.length,
"Stroke number can't be greater than the number of strokes.",
);

final ogPath = _data!.createPath();
final totalLength = ogPath.computeLength();

// Length of the new path.
final newLength = () {
final path = ui.Path();
for (var i = 0; i < stroke; i++) {
final commands = compiler.parseSvgPathData(_data!.paths[i]).commands;
path.drawCommands(commands);
}

// FIXME: This 0.1 is a random number to make it work, but it's not accurate
// nor the best solution.
return path.computeLength() - 0.1;
}();

return animateTo(
newLength / totalLength,
duration: duration,
curve: curve,
);
}

@override
TickerFuture reverse({double? from}) {
final future = super.reverse(from: from);
Expand Down

0 comments on commit 5a47408

Please sign in to comment.