Skip to content

Commit

Permalink
added letter pop animatin
Browse files Browse the repository at this point in the history
  • Loading branch information
Amonc committed Aug 1, 2024
1 parent ef61fb1 commit d5f0495
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 44 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.2.0

* Letter Pop Animation added
* Some bug fixes and improvements

## 1.1.0

* Added initialLineList to add initial lines to the crossword
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# NEW: Reveal Letter animation, OnUpdate line function, Gradient Colors, TextStyles and Line Decoration updated to the Crossword Widget

# NEW: LetterPop Animation
# Crossword [![pub package](https://img.shields.io/pub/v/crossword.svg)](https://pub.dartlang.org/packages/crossword)

<br>
Expand Down Expand Up @@ -47,7 +46,7 @@ a [dependency in your pubspec.yaml file](https://flutter.io/using-packages/).

```yaml
dependencies:
crossword: ^1.1.0
crossword: ^1.2.0
```
Import the package in your Dart code and instantiate the `Crossword` widget.
Expand Down Expand Up @@ -151,6 +150,7 @@ final GlobalKey<CrosswordState> _crosswordState = GlobalKey();
- `revealLetterDecoration`: Accepts a `RevealLetterDecoration` to animate the decoration of the
letters

- 'letterPopDecoration': Accepts a `LetterPopDecoration` to animate the decoration of the specific letter onTouchEvent

## Contributions

Expand Down
5 changes: 5 additions & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ class _GamePageState extends State<GamePage> {
),
Expanded(
child: Crossword(
letterPopDecoration: const LetterPopDecoration(
onTouchPopScaleFactor: 1.5,
duration: Duration(milliseconds: 200),
onTouchLetterFontStyle: FontStyle.italic,
),
revealLetterDecoration:
const RevealLetterDecoration(shakeOffset: Offset(10, 20)),
key: crosswordState,
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ packages:
path: ".."
relative: true
source: path
version: "1.1.0"
version: "1.2.0"
cupertino_icons:
dependency: "direct main"
description:
Expand Down
77 changes: 54 additions & 23 deletions lib/components/crossword_panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Crossword extends StatefulWidget {
final bool? updateStateWithParent;
final List<LineOffset> initialLineList;
final int minimumWordLength;
final LetterPopDecoration letterPopDecoration;

final RevealLetterDecoration? revealLetterDecoration;

Expand All @@ -48,6 +49,7 @@ class Crossword extends StatefulWidget {
shakeOffset: Offset(20, 50), scaleFactor: 2),
this.updateStateWithParent = false,
this.minimumWordLength = 3,
this.letterPopDecoration = const LetterPopDecoration(),
}) : assert(
(drawCrossLine ?? true) ||
(drawHorizontalLine ?? true) ||
Expand All @@ -60,8 +62,7 @@ class Crossword extends StatefulWidget {
}

/// State class for the Crossword widget.
class CrosswordState extends State<Crossword>
with SingleTickerProviderStateMixin {
class CrosswordState extends State<Crossword> with TickerProviderStateMixin {
List<WordLine> lineList = [];
List<Offset> selectedOffsets = [];
List<Color> colors = [];
Expand All @@ -70,9 +71,13 @@ class CrosswordState extends State<Crossword>
LetterOffset? startPoint;
LetterOffset? endPoint;
List<List<String>> letters = [];
late AnimationController _controller;
late AnimationController _revealHintAnimationController;
late Animation<Offset> _shakeAnimation;
late Animation<double> _scaleAnimation;
Offset? currentOffset;

late AnimationController _popAnimationController;
late Animation<double> _popAnimation;

@override
void initState() {
Expand All @@ -83,7 +88,7 @@ class CrosswordState extends State<Crossword>
setupInitialLines();

///initialize the animation controller
_controller = AnimationController(
_revealHintAnimationController = AnimationController(
duration: widget.revealLetterDecoration!.animationDuration,
vsync: this,
);
Expand All @@ -92,15 +97,25 @@ class CrosswordState extends State<Crossword>
_shakeAnimation = Tween<Offset>(
begin: Offset.zero, end: widget.revealLetterDecoration!.shakeOffset)
.chain(CurveTween(curve: widget.revealLetterDecoration!.shakeCurve))
.animate(_controller);
.animate(_revealHintAnimationController);

///set the scale animation
_scaleAnimation = Tween<double>(
begin: 1,
end: widget.revealLetterDecoration!.scaleFactor,
)
.chain(CurveTween(curve: widget.revealLetterDecoration!.scaleCurve))
.animate(_controller);
.animate(_revealHintAnimationController);

_popAnimationController = AnimationController(
vsync: this,
duration: widget.letterPopDecoration.duration,
)..repeat(reverse: true);

_popAnimation = Tween<double>(
begin: 1, end: widget.letterPopDecoration.onTouchPopScaleFactor)
.chain(CurveTween(curve: widget.letterPopDecoration.curve))
.animate(_popAnimationController);
}

Offset revealLetterPositions = const Offset(0, 0);
Expand All @@ -109,12 +124,14 @@ class CrosswordState extends State<Crossword>
animate({required Offset offset}) {
revealLetterPositions = offset;
setState(() {});
_controller.forward().then((value) => _controller.reverse());
_revealHintAnimationController
.forward()
.then((value) => _revealHintAnimationController.reverse());
}

@override
void dispose() {
_controller.dispose();
_revealHintAnimationController.dispose();
super.dispose();
}

Expand Down Expand Up @@ -257,6 +274,13 @@ class CrosswordState extends State<Crossword>
startPoint!.offset.dy + restrictedDy),
spacing: widget.spacing);

if (currentOffset != c.getSmallerOffset) {
currentOffset = c.getSmallerOffset;
_popAnimationController
.forward()
.then((value) => _popAnimationController.reverse());
}

///line can only be drawn by touching inside the panel
if (isWithinLimit(c)) {
endPoint = c;
Expand Down Expand Up @@ -363,22 +387,29 @@ class CrosswordState extends State<Crossword>
});
},
child: AnimatedBuilder(
animation: _controller,
animation: _popAnimationController,
builder: (BuildContext context, Widget? child) {
return CustomPaint(
///paints lines on the screen
painter: LinePainter(
revealLetterPositions: revealLetterPositions,
scaleAnimationValue: _scaleAnimation.value,
shakeAnimationValue: _shakeAnimation.value,
lineDecoration: widget.lineDecoration,
letters: letters,
lineList: lineList,
textStyle: widget.textStyle,
spacing: widget.spacing,
hints: widget.hints),
size: Size(letters.length * widget.spacing.dx,
letters.first.length * widget.spacing.dy),
return AnimatedBuilder(
animation: _revealHintAnimationController,
builder: (BuildContext context, Widget? child) {
return CustomPaint(
///paints lines on the screen
painter: LinePainter(
currentOffset: currentOffset,
revealLetterPositions: revealLetterPositions,
popAnimationValue: _popAnimation.value,
scaleAnimationValue: _scaleAnimation.value,
shakeAnimationValue: _shakeAnimation.value,
lineDecoration: widget.lineDecoration,
letters: letters,
lineList: lineList,
textStyle: widget.textStyle,
spacing: widget.spacing,
hints: widget.hints),
size: Size(letters.length * widget.spacing.dx,
letters.first.length * widget.spacing.dy),
);
},
);
},
),
Expand Down
18 changes: 18 additions & 0 deletions lib/components/letter_pop_decoration.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'dart:ui';

import 'package:flutter/animation.dart';

class LetterPopDecoration {
final double onTouchPopScaleFactor;
final FontStyle onTouchLetterFontStyle;
final FontWeight onTouchLetterFontWeight;
final Duration duration;
final Curve curve;
const LetterPopDecoration({
this.onTouchPopScaleFactor = 1.5,
this.onTouchLetterFontStyle = FontStyle.italic,
this.onTouchLetterFontWeight = FontWeight.bold,
this.duration = const Duration(milliseconds: 200),
this.curve = Curves.decelerate,
});
}
56 changes: 40 additions & 16 deletions lib/components/line_painter.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:crossword/components/letter_pop_decoration.dart';
import 'package:crossword/components/line_decoration.dart';
import 'package:crossword/components/word_line.dart';
import 'package:flutter/material.dart';
Expand All @@ -12,22 +13,29 @@ class LinePainter extends CustomPainter {
final TextStyle? textStyle;
final Offset shakeAnimationValue;
final double scaleAnimationValue;
final double popAnimationValue;
final Offset? revealLetterPositions;
final LineDecoration? lineDecoration;

LinePainter({
this.initialLineList,
this.textStyle = const TextStyle(color: Colors.black, fontSize: 16),
this.lineDecoration,
required this.shakeAnimationValue,
required this.scaleAnimationValue,
required this.letters,
required this.lineList,
required this.spacing,
required this.hints,
this.revealLetterPositions,
this.correctColor = Colors.green,
});
final Offset? currentOffset;
final bool onTouchRotateLetter;
final LetterPopDecoration letterPopDecoration;

LinePainter(
{this.initialLineList,
this.textStyle = const TextStyle(color: Colors.black, fontSize: 16),
this.lineDecoration,
required this.shakeAnimationValue,
required this.scaleAnimationValue,
required this.popAnimationValue,
required this.letters,
required this.lineList,
required this.spacing,
required this.hints,
this.revealLetterPositions,
this.onTouchRotateLetter = true,
this.correctColor = Colors.green,
this.currentOffset,
this.letterPopDecoration = const LetterPopDecoration()});

@override
void paint(Canvas canvas, Size size) {
Expand Down Expand Up @@ -72,7 +80,12 @@ class LinePainter extends CustomPainter {
double y = j.toDouble() * spacing.dy + spacing.dy / 2;

Offset offset = Offset(i.toDouble(), j.toDouble());

double sizeFactor = 1;
if (offset == currentOffset) {
sizeFactor = popAnimationValue;
} else {
sizeFactor = 1;
}
bool within = withinOffset(offsets, offset);

/// Draw letters
Expand All @@ -87,7 +100,18 @@ class LinePainter extends CustomPainter {
fontSize:
((within ? lineDecoration?.lineTextStyle : textStyle)
?.fontSize)! *
(reveal ? scaleAnimationValue : 1)),
sizeFactor *
(reveal ? scaleAnimationValue : 1))
.copyWith(
fontStyle: offset == currentOffset && popAnimationValue != 1
? letterPopDecoration.onTouchLetterFontStyle
: FontStyle.normal,


fontWeight: offset == currentOffset && popAnimationValue != 1
? letterPopDecoration.onTouchLetterFontWeight
: textStyle?.fontWeight,
),
),
textDirection: TextDirection.ltr,
textAlign: TextAlign.center,
Expand Down
1 change: 1 addition & 0 deletions lib/crossword.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export 'components/line_offset.dart';
export 'components/line_painter.dart';
export 'components/reveal_letter_decoration.dart';
export 'components/word_line.dart';
export 'components/letter_pop_decoration.dart';
export 'helper/extensions.dart';
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: crossword
description: A Flutter package providing a user interface for solving crossword puzzles in your app.
version: 1.1.0
version: 1.2.0
homepage: https://github.com/Amonc/crossword

environment:
Expand Down

0 comments on commit d5f0495

Please sign in to comment.