mirror of https://github.com/flutter/samples.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
6.1 KiB
261 lines
6.1 KiB
6 years ago
|
import 'dart:core';
|
||
|
import 'dart:math';
|
||
|
import 'package:flutter_web/material.dart';
|
||
|
import 'package:flutter_web/scheduler.dart';
|
||
|
|
||
|
import 'numberpicker.dart';
|
||
|
|
||
|
main() => runApp(MaterialApp(home: App(), debugShowCheckedModeBanner: false));
|
||
|
|
||
|
class App extends StatefulWidget {
|
||
|
@override
|
||
|
State<StatefulWidget> createState() => TM();
|
||
|
}
|
||
|
|
||
|
enum SI { pause, play, stop }
|
||
|
List<T> triangles;
|
||
|
var percent = 0.0, cTime = 0.0, dur = 120000.0, rng = Random(), rebuild = true;
|
||
|
|
||
|
class TM extends State<App> {
|
||
|
SI cState = SI.stop;
|
||
|
Ticker t;
|
||
|
var pTime = 0.0;
|
||
|
|
||
|
@override
|
||
|
initState() {
|
||
|
// Screen.keepOn(true);
|
||
|
t = Ticker(up);
|
||
|
super.initState();
|
||
|
}
|
||
|
|
||
|
up(Duration d) {
|
||
|
if (cState == SI.play) {
|
||
|
setState(() {
|
||
|
if (cTime >= dur)
|
||
|
stop();
|
||
|
else {
|
||
|
cTime = d.inMilliseconds.toDouble() + pTime;
|
||
|
percent = cTime / dur;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
press() {
|
||
|
if (cState == SI.play)
|
||
|
pause();
|
||
|
else if (cState == SI.pause)
|
||
|
play();
|
||
|
else {
|
||
|
cState = SI.play;
|
||
|
t.start();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pause() {
|
||
|
setState(() {
|
||
|
cState = SI.pause;
|
||
|
t.stop();
|
||
|
});
|
||
|
}
|
||
|
|
||
|
play() {
|
||
|
setState(() {
|
||
|
cState = SI.play;
|
||
|
t.start();
|
||
|
pTime = cTime;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
stop() {
|
||
|
setState(() {
|
||
|
cState = SI.stop;
|
||
|
t.stop();
|
||
|
pTime = 0.0;
|
||
|
cTime = 0.0;
|
||
|
percent = 0.0;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
openDialog() {
|
||
|
showDialog<num>(
|
||
|
context: context,
|
||
|
builder: (BuildContext context) {
|
||
|
return NumberPickerDialog.integer(
|
||
|
initialIntegerValue: (dur + 1.0) ~/ 60000,
|
||
|
maxValue: 20,
|
||
|
minValue: 1,
|
||
|
title: Text('Minutes'));
|
||
|
}).then((num v) {
|
||
|
if (v != null) dur = 60000.0 * v;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
List<Widget> w = List();
|
||
|
|
||
|
if (cState == SI.pause) {
|
||
|
w.add(fab(Colors.green, play, Icons.play_arrow));
|
||
|
w.add(SizedBox(height: 10));
|
||
|
w.add(fab(Colors.red, stop, Icons.close));
|
||
|
w.add(SizedBox(height: 20));
|
||
|
}
|
||
|
|
||
|
if (cState == SI.stop) {
|
||
|
w.add(fab(Colors.lightBlue, openDialog, Icons.timer));
|
||
|
w.add(SizedBox(height: 10));
|
||
|
w.add(fab(Colors.yellow[900], () {
|
||
|
rebuild = true;
|
||
|
}, Icons.loop));
|
||
|
w.add(SizedBox(height: 20));
|
||
|
}
|
||
|
|
||
|
Column r = Column(mainAxisAlignment: MainAxisAlignment.end, children: w);
|
||
|
|
||
|
return Scaffold(
|
||
|
backgroundColor: Colors.black,
|
||
|
body: SizedBox.expand(
|
||
|
child: Container(
|
||
|
child: CustomPaint(
|
||
|
painter: P(),
|
||
|
child: FlatButton(
|
||
|
onPressed: press,
|
||
|
child: Row(
|
||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||
|
children: [r]))))));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FloatingActionButton fab(Color c, VoidCallback f, IconData ic) =>
|
||
|
FloatingActionButton(backgroundColor: c, onPressed: f, child: Icon(ic));
|
||
|
|
||
|
class P extends CustomPainter {
|
||
|
@override
|
||
|
paint(Canvas canvas, Size size) {
|
||
|
var w = size.width, h = size.height, d = 2 / 3 * w;
|
||
|
if (w > 0.1 && h > 0.1) {
|
||
|
if (rebuild) {
|
||
|
rebuild = false;
|
||
|
setupT();
|
||
|
for (var t in triangles) t.setupdP(w / d, h / d);
|
||
|
}
|
||
|
|
||
|
for (var t in triangles) {
|
||
|
var cP = t.cP(), p = Path();
|
||
|
p.moveTo(cP[0].x * d + w / 2, cP[0].y * d + h / 2);
|
||
|
for (i = 1; i < 3; i++)
|
||
|
p.lineTo(cP[i].x * d + w / 2, cP[i].y * d + h / 2);
|
||
|
p.close();
|
||
|
canvas.drawPath(p, t.p);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
bool shouldRepaint(CustomPainter oldDelegate) => true;
|
||
|
}
|
||
|
|
||
|
int i;
|
||
|
|
||
|
class T {
|
||
|
List<Point> dP = List(3), sP = List(3);
|
||
|
Paint p;
|
||
|
|
||
|
T(Point p1, p2, p3, var c) {
|
||
|
p = Paint()..style = PaintingStyle.fill;
|
||
|
sP[0] = p1;
|
||
|
sP[1] = p2;
|
||
|
sP[2] = p3;
|
||
|
p.color = c[100 * (rng.nextInt(9) + 1)];
|
||
|
|
||
|
double x = 0, y = 0;
|
||
|
for (i = 0; i < 3; i++) {
|
||
|
x += sP[i].x;
|
||
|
y += sP[i].y;
|
||
|
}
|
||
|
|
||
|
x = 2 * x / 3;
|
||
|
y = 2 * y / 3;
|
||
|
if (x * x + y * y < 1) triangles.add(this);
|
||
|
}
|
||
|
|
||
|
setupdP(double wR, hR) {
|
||
|
var x = (rng.nextDouble() - 0.5) * (wR - 0.1),
|
||
|
y = (rng.nextDouble() - 0.5) * (hR - 0.1);
|
||
|
dP[0] = Point(x, y);
|
||
|
for (i = 1; i < 3; i++)
|
||
|
dP[i] = Point(sP[i].x + x - sP[0].x, sP[i].y + y - sP[0].y);
|
||
|
}
|
||
|
|
||
|
List<Point> cP() {
|
||
|
List<Point> res = List(3);
|
||
|
var p, k, o = 6000, r;
|
||
|
if (cTime < o)
|
||
|
p = 1 - cTime / o;
|
||
|
else
|
||
|
p = (cTime - o) / (dur - o);
|
||
|
k = 2 * ((cTime.toInt() % o) - o / 2).abs() / o;
|
||
|
r = min(min(1, (dur - cTime) / o), cTime / o);
|
||
|
this.p.color = this.p.color.withAlpha(255 - (200 * k * r).toInt());
|
||
|
|
||
|
for (i = 0; i < 3; i++)
|
||
|
res[i] = Point(
|
||
|
sP[i].x * p + dP[i].x * (1 - p), sP[i].y * p + dP[i].y * (1 - p));
|
||
|
|
||
|
if (cTime > o) {
|
||
|
var d = res[0].distanceTo(sP[0]);
|
||
|
var a = acos((sP[0].x - res[0].x) / d);
|
||
|
if (sP[0].y > res[0].y) a = 2 * pi - a;
|
||
|
var b = pi - a + p * pi * dur / 120000;
|
||
|
var dX = cos(b) * d, dY = sin(b) * d;
|
||
|
for (i = 0; i < 3; i++) res[i] = Point(sP[i].x + dX, sP[i].y + dY);
|
||
|
}
|
||
|
|
||
|
double mx = 0, my = 0;
|
||
|
for (i = 0; i < 3; i++) {
|
||
|
mx += res[i].x;
|
||
|
my += res[i].y;
|
||
|
}
|
||
|
mx /= 3;
|
||
|
my /= 3;
|
||
|
for (i = 0; i < 3; i++)
|
||
|
res[i] = Point(res[i].x + (res[i].x - mx) * (1 - k) * r / 2,
|
||
|
res[i].y + (res[i].y - my) * (1 - k) * r / 2);
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
setupT() {
|
||
|
int dim = 20, x, y;
|
||
|
List<Point> tri = List(dim * dim);
|
||
|
|
||
|
for (x = 0; x < dim; x++) {
|
||
|
for (y = 0; y < dim; y++) {
|
||
|
var dx = rng.nextDouble() - 0.5, dy = rng.nextDouble() - 0.5, off;
|
||
|
if (x % 2 == 0)
|
||
|
off = 0;
|
||
|
else
|
||
|
off = 0.5;
|
||
|
tri[x * dim + y] =
|
||
|
Point((x + dx) / (dim - 1) - 0.5, (y + off + dy) / (dim - 1) - 0.5);
|
||
|
}
|
||
|
}
|
||
|
triangles = List();
|
||
|
var r = rng.nextInt(5), c;
|
||
|
if (r == 0) c = Colors.lightBlue;
|
||
|
if (r == 1) c = Colors.yellow;
|
||
|
if (r == 2) c = Colors.lightGreen;
|
||
|
if (r == 3) c = Colors.red;
|
||
|
if (r == 4) c = Colors.pink;
|
||
|
|
||
|
for (x = 0; x < dim - 1; x++) {
|
||
|
for (y = 0; y < dim - 1; y++) {
|
||
|
int off = x * dim;
|
||
|
T(tri[y + off], tri[y + 1 + off], tri[y + off + dim], c);
|
||
|
T(tri[y + off + dim], tri[y + 1 + off], tri[y + 1 + off + dim], c);
|
||
|
}
|
||
|
}
|
||
|
}
|