Flutter - how do I rotate an object on a CustomPainter canvas? - flutter

How do you rotate an object drawn on a canvas in Flutter (not the whole canvas, just the object)?
The following does not work. Error is: This expression has a type of 'void' so its value can't be used.
Transform.rotate(
angle: pi,
child: canvas.drawPath(
getTrianglePath(Offset(secondhandX, secondhandY)),
secondhandBrush));
Here is the full code:
// imports omitted
class TimerDialPainter extends CustomPainter {
Path getTrianglePath(Offset position) {
return Path()
..moveTo(position.dx - 20, position.dy - 20)
..lineTo(position.dx + 40, position.dy + 40)
..lineTo(position.dx - 20, position.dy + 40)
..lineTo(position.dx - 20, position.dy - 20);
}
#override
void paint(Canvas canvas, Size size) {
int centerX = size.width / 2;
int centerY = size.height / 2;
int secondsArc = 60;
Paint countBrush = Paint()
..color = (Colors.red)
..style = PaintingStyle.fill
..strokeWidth = 3;
var secondhandX = centerX + 80 * cos(secondsArc * pi / 180);
var secondhandY = centerY + 80 * sin(secondsArc * pi / 180);
Transform.rotate(
angle: pi/3,
child: canvas.drawPath(
getTrianglePath(Offset(secondhandX, secondhandY)),
countBrush));
} //I feel this is not a right place to solve this??
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}

Try rotating the canvas and paint it. Then rotate it back to previous value
#override
void paint(Canvas canvas, Size size) {
double centerX = size.width / 2;
double centerY = size.height / 2;
int secondsArc = 60;
Paint countBrush = Paint()
..color = (Colors.red)
..style = PaintingStyle.fill
..strokeWidth = 3;
num secondhandX = centerX + 80 * cos(secondsArc * pi / 180);
num secondhandY = centerY + 80 * sin(secondsArc * pi / 180);
canvas.rotate(40);
canvas.drawPath(
getTrianglePath(Offset(secondhandX.toDouble(), secondhandY.toDouble())),
countBrush);
canvas.rotate(0);
}

Related

How I will create game level map with level pointers with flutter?

I am trying to make a game level map UI with flutter. I am trying to do this with Custompainter. I can draw path line but don't know how to get this level pointers and add buttons/image widget to those points. I didn't find good solution in web.
My code below:
class LinePainter extends CustomPainter {
int totalLevel ;
LinePainter(this.totalLevel);
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..color = AppColors.primaryColor
..style = PaintingStyle.stroke
..strokeWidth = 10;
var path = Path();
path.moveTo(0, size.height * 0.125);
path.lineTo(size.width- 50, size.height * 0.125);
path.lineTo(size.width- 50, size.height * 0.375);
path.lineTo(50, size.height * 0.375);
path.lineTo(50, size.height * 0.625);
path.lineTo(size.width- 50, size.height * 0.625);
path.lineTo(size.width- 50, size.height * 0.875);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}}
Please help to find best solution.

Why is my setState not working in Flutter?

My first day learning flutter, can someone help me understand why my setState is not working?
Making a basic clock app.
The main part is the initState where I am trying to make it so that the Paint function which creates the clock UI is updated once every second so my second hand is updated in real-time.
import 'dart:math';
import 'package:flutter/material.dart';
class ClockView extends StatefulWidget{
#override
_ClockViewState createState() => _ClockViewState();
}
class _ClockViewState extends State<ClockView>{
#override void initState() {
Timer.periodic(Duration(seconds: 1), (timer) {setState(() {
});});
super.initState();
}
#override
Widget build(BuildContext context){
return Container(
width: 300,
height: 300,
child: Transform.rotate(
angle: -pi/2,
child: CustomPaint(
painter: ClockPainter(),
),
),
);
}
}
class ClockPainter extends CustomPainter{
#override
void paint(Canvas canvas, Size size) {
var CenterX = size.width/2;
var CenterY = size.height/2;
var CenterTrue = Offset(CenterX, CenterY);
var CRadius = min(CenterY, CenterY);
var SecHandBrush = Paint()..strokeCap = StrokeCap.round ..color = Colors.orange ..style = PaintingStyle.stroke ..strokeWidth = 4;
var MinHandBrush = Paint()..strokeCap = StrokeCap.round ..shader = RadialGradient(colors: [Colors.lightBlue, Colors.pink]).createShader(Rect.fromCircle(center: CenterTrue, radius: CRadius)) ..style = PaintingStyle.stroke ..strokeWidth = 8;
var HrHandBrush = Paint()..strokeCap = StrokeCap.round ..shader = RadialGradient(colors: [Colors.deepPurpleAccent, Colors.redAccent]).createShader(Rect.fromCircle(center: CenterTrue, radius: CRadius/2)) ..style = PaintingStyle.stroke ..strokeWidth = 10;
var FillBrush = Paint()..color = Color(0xFF444974);
var OutlineBrush = Paint()..color = Color(0xFFEAECFF) ..style = PaintingStyle.stroke ..strokeWidth = 5;
var CenterBrush = Paint()..color = Color(0xFFEAECFF);
canvas.drawCircle(CenterTrue, CRadius - 50, FillBrush);
canvas.drawCircle(CenterTrue, CRadius - 50.1, OutlineBrush);
var SecHandX = CenterX + 80 * cos(DateTime.now().second * 6 * pi/180);
var SecHandY = CenterX + 80 * sin(DateTime.now().second * 6 * pi/180);
canvas.drawLine(CenterTrue, Offset(SecHandX, SecHandY), SecHandBrush);
var MinHandX = CenterX + 75 * cos(DateTime.now().minute * 6 * pi/180);
var MinHandY = CenterX + 75 * sin(DateTime.now().minute * 6 * pi/180);
canvas.drawLine(CenterTrue, Offset(MinHandX,MinHandY), MinHandBrush);
var HrHandX = CenterX + 60 * cos((DateTime.now().hour * 30 + DateTime.now().minute * 0.5) * pi/180);
var HrHandY = CenterX + 60 * sin((DateTime.now().hour * 30 + DateTime.now().minute * 0.5) * pi/180);
canvas.drawLine(CenterTrue, Offset(HrHandX,HrHandY), HrHandBrush);
canvas.drawCircle(CenterTrue, 5, CenterBrush);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}```
Add a widgets binding observer to trigger timer after the initial state build is complete, I would rewrite it as:
import 'dart:math';
import 'package:flutter/material.dart';
class ClockView extends StatefulWidget{
#override
_ClockViewState createState() => _ClockViewState();
}
class _ClockViewState extends State<ClockView>{
void _startTimer(){
WidgetsBinding.instance.endOfFrame.then(
(_) {
if (mounted) {
// do some suff
Timer.periodic(Duration(seconds: 1), (timer) {setState(() {
});});
};
},
);
}
#override void initState() {
_startTimer();
super.initState();
}
#override
Widget build(BuildContext context){
return Container(
width: 300,
height: 300,
child: Transform.rotate(
angle: -pi/2,
child: CustomPaint(
painter: ClockPainter(),
),
),
);
}
}
class ClockPainter extends CustomPainter{
#override
void paint(Canvas canvas, Size size) {
var CenterX = size.width/2;
var CenterY = size.height/2;
var CenterTrue = Offset(CenterX, CenterY);
var CRadius = min(CenterY, CenterY);
var SecHandBrush = Paint()..strokeCap = StrokeCap.round ..color = Colors.orange ..style = PaintingStyle.stroke ..strokeWidth = 4;
var MinHandBrush = Paint()..strokeCap = StrokeCap.round ..shader = RadialGradient(colors: [Colors.lightBlue, Colors.pink]).createShader(Rect.fromCircle(center: CenterTrue, radius: CRadius)) ..style = PaintingStyle.stroke ..strokeWidth = 8;
var HrHandBrush = Paint()..strokeCap = StrokeCap.round ..shader = RadialGradient(colors: [Colors.deepPurpleAccent, Colors.redAccent]).createShader(Rect.fromCircle(center: CenterTrue, radius: CRadius/2)) ..style = PaintingStyle.stroke ..strokeWidth = 10;
var FillBrush = Paint()..color = Color(0xFF444974);
var OutlineBrush = Paint()..color = Color(0xFFEAECFF) ..style = PaintingStyle.stroke ..strokeWidth = 5;
var CenterBrush = Paint()..color = Color(0xFFEAECFF);
canvas.drawCircle(CenterTrue, CRadius - 50, FillBrush);
canvas.drawCircle(CenterTrue, CRadius - 50.1, OutlineBrush);
var SecHandX = CenterX + 80 * cos(DateTime.now().second * 6 * pi/180);
var SecHandY = CenterX + 80 * sin(DateTime.now().second * 6 * pi/180);
canvas.drawLine(CenterTrue, Offset(SecHandX, SecHandY), SecHandBrush);
var MinHandX = CenterX + 75 * cos(DateTime.now().minute * 6 * pi/180);
var MinHandY = CenterX + 75 * sin(DateTime.now().minute * 6 * pi/180);
canvas.drawLine(CenterTrue, Offset(MinHandX,MinHandY), MinHandBrush);
var HrHandX = CenterX + 60 * cos((DateTime.now().hour * 30 + DateTime.now().minute * 0.5) * pi/180);
var HrHandY = CenterX + 60 * sin((DateTime.now().hour * 30 + DateTime.now().minute * 0.5) * pi/180);
canvas.drawLine(CenterTrue, Offset(HrHandX,HrHandY), HrHandBrush);
canvas.drawCircle(CenterTrue, 5, CenterBrush);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}```
Note: This problem has been solved. It required a complete re-installation of the flutter package but the code as mentioned in the code works fine on its own without any modifications.

Flutter 270 degree radial chart

I am looking for the following chart in flutter:
Can anyone provide me any solution?
//First get X,Y Center and radius
double centerX = width / 2;
double centerY = height / 2;
double radius = width / 2;
const numberOfIntervals=5;
//create axis lines
var axisLinePaint = Paint()
..color = viewPortBorderColor
..style = PaintingStyle.stroke
..strokeWidth=1;
//Gridline Paint
var gridlinePaint = Paint()
..color = gridColor
..strokeWidth = 0.6
..style = PaintingStyle.fill;
canvas.drawArc(Rect.fromLTRB(0, 0, width, height),
getRadiansByAngle(-90), getRadiansByAngle(270), true, axisLinePaint);
// Get gap between intervals
int gap=270~/numberOfIntervals;
now creating gridlines:
for (var i = gap; i <= 270; i += gap) {
var thetaAngle = 0;
label=label+(maxVal~/numberOfIntervals);
if (i <= 90) {
thetaAngle = 270 + i;
} else {
thetaAngle = i - 90;
}
var theta = thetaAngle * (pi / 180);
var offSet=Offset(centerX + radius * cos(theta), centerY + radius * sin(theta));
canvas.drawLine(
offSet,
Offset(centerX, centerY),
gridlinePaint);
}
for radian angle:
double getRadiansByAngle(double angle) {
return (angle * pi / 180);
}
Here is full solution:
https://github.com/MoinHashmi/radial_chart_gridlines
If anyone have another suggestion or solution please post.
Great Effort thanks am waiting for this from a long time

How to Insert/draw Image/text inside canvas circle in flutter

I want to draw/insert image and text inside canvas circle but I am unable to do that. I am posting screenshot for better understanding of my requirements
Image
Code
void paint(Canvas canvas, Size size) {
Size size = MediaQuery.of(buildContext).size;
double strokeWidth = 10;
Rect myRect = Offset(-size.width * 0.21, -40) &
Size(size.width * 0.195, size.width * 0.195);
var paint1 = Paint()
..color = Color(0xFF23BBFF)
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke;
var paint2 = Paint()
..color = Color(0xFFFF8623)
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke;
double firstLineRadianStart = 0;
double _unAnswered = 0.30;
double firstLineRadianEnd = (360 * _unAnswered) * pi / 180;
canvas.drawArc(
myRect, firstLineRadianStart, firstLineRadianEnd, false, paint1);
double _learned = 1 - _unAnswered;
double secondLineRadianEnd = getRadians(_learned);
canvas.drawArc(
myRect, firstLineRadianEnd, secondLineRadianEnd, false, paint2);
}
double getRadians(double value) {
return (360 * value) * pi / 180;
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;

Can't recreate this floating widget

I'm currently blocked trying to create a widget (like a tooltip box) that is represented by the image below. I should probably be able to create it by relying on a Painter class, but i'm not familiar doing so...
https://pasteboard.co/IgccNxD.png
(it's small, yes, max height = ~35px)
The code ended being something like:
void paint(Canvas canvas, Size size) {
Paint p = Paint()
..color = Colors.red
..isAntiAlias = true
..style = PaintingStyle.fill;
Offset nw = Offset(0, 0);
Offset se = Offset(size.width, size.height * 0.8);
final Rect rect = Rect.fromPoints(nw, se);
final RRect r = RRect.fromRectAndRadius(rect, Radius.circular(10));
canvas.drawRRect(r, p);
Offset bottomPoint = Offset((size.width / 2), size.height);
Offset rightPoint = Offset((size.width / 2) * 0.80, size.height * 0.80);
Offset leftPoint = Offset((size.width / 2) * 1.20, size.height * 0.80);
var path1 = Path()
..moveTo(rightPoint.dx, rightPoint.dy)
..lineTo(bottomPoint.dx, bottomPoint.dy)
..lineTo(leftPoint.dx, leftPoint.dy)
..lineTo(rightPoint.dx, rightPoint.dy);
canvas.drawPath(path1, p);
}
For the text inside, I've stacked it above this painting.