flutter之摩天輪轉盤選擇控件實現

import 'dart:math';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:spritewidget/spritewidget.dart';

class Subject {
}

class MoreScreen extends StatefulWidget {

  @override
  State<StatefulWidget> createState() {
    return MoreState();
  }
}

class MoreNode extends NodeWithSize {
  int _startTimeMillis;
  double rot;
  double drot;
  int lastEventTm;
  Offset lastEventPos;
  List<Node> gameicons = List();
  static const gamepos = [
    ["tri.png",500.0,500.0],
    ["hrd.png",500.0,500.0],
    ["sprite.png",500.0,500.0],
    ["cube.png",500.0,500.0],
    ["painter.png",500.0,500.0]
  ];

  double reduce;

  var jumpFn;

  MoreNode(SpriteSheet moresprites, this.jumpFn)
      : super(const Size(1024.0, 1024.0)) {
    for(var game in gamepos) {
      Node node = Sprite(moresprites[game[0]]);
      node.position=Offset(game[1], game[2]);
      addChild(node);
      gameicons.add(node);//, const Offset(512.0, 512.0) moresprites[])):
    }

    _startTimeMillis = 0;
    rot = 0.0;
    drot = 5.0;
    reduce = 0.5;

    userInteractionEnabled = true;
  }

  @override
  void update(double dt) {
    int millis = new DateTime.now().millisecondsSinceEpoch - _startTimeMillis;
    if(millis>100 && (drot>0.01 || drot<-0.01)) {
      rot+=drot;
      drot*=reduce;
      rot%=360;
      _startTimeMillis = DateTime.now().millisecondsSinceEpoch;
      for (var ind=0; ind<gameicons.length; ind++) {
        var grot = ((rot+ind*(360.0/gameicons.length))%360)*pi/180.0;
        var game = gameicons[ind];
        var s = sqrt((grot-pi)*(grot-pi))/7+0.7;
        var pos = Offset(sin(grot)*300+gamepos[ind][1], 400*cos(grot)*s+gamepos[ind][2]);
        game.scale = s;
        game.zPosition = s;
        game.position = pos;
      }
    }
  }

  @override handleEvent(SpriteBoxEvent event) {
      switch(event.type) {
        case PointerDownEvent:
          reduce = 1.0;
          drot = 0;
          lastEventPos = event.boxPosition;
          lastEventTm = DateTime.now().millisecondsSinceEpoch;
          break;

        case PointerMoveEvent:
          var dt = (DateTime.now().millisecondsSinceEpoch-lastEventTm);
          if(dt>10) {
            drot = (event.boxPosition.dx-lastEventPos.dx)*100.0/dt;
            if(event.boxPosition.dy<350){
              drot=-drot;
            }
            lastEventPos = event.boxPosition;
            lastEventTm = DateTime.now().millisecondsSinceEpoch;
          }
          break;

        case PointerUpEvent:
          reduce = 0.8;
          if(drot*drot<1) {
            var angle = atan2(event.boxPosition.dx-190, event.boxPosition.dy-290);
            var pice = (360.0 / gameicons.length);
            var thresthold = (pice/3)*pi/180.0;
            for (var ind=0; ind<gameicons.length; ind++) {
              var grot = (rot + ind * pice) * pi/180.0;
              var delta = grot-angle;
              if(delta>pi) {
                delta -= 2 * pi;
              }
              if(delta<-pi) {
                delta += 2 * pi;
              }
              if(delta<thresthold && delta>-thresthold) {
                jumpFn("/"+(gamepos[ind][0] as String).split('.')[0]);
              }
            }
          }
          break;
      }
      return true;
  }
}

class MoreState extends State<MoreScreen> {
  List<Subject> subjects;

  ImageMap moreimages;
  SpriteSheet moresprites;
  SpriteWidget gamesWidget;

  void loadData() async {
    moreimages = new ImageMap(rootBundle);
    await moreimages.load(<String>[
      'assets/more.png',
    ]);
    String json = await DefaultAssetBundle.of(context).loadString('assets/more.json');
    moresprites = new SpriteSheet(moreimages['assets/more.png'], json);

    setState(() {
      gamesWidget = new SpriteWidget(MoreNode(moresprites, jumpFn), SpriteBoxTransformMode.scaleToFit);
    });
  }
  void jumpFn(String route) {
        Navigator.of(context).pushNamedAndRemoveUntil(route, (route) => route == null );
  }

  @override
  void initState() {
    super.initState();
    loadData();
  }


  @override
  Widget build(BuildContext context) {
    return
      new Scaffold(
          appBar: new AppBar(title: new Text('益智小遊戲')),
          body: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children:[
                new Padding(
                  padding: new EdgeInsets.all(20.0),
                  child: Text("版本:0.0.0\n作者:羅治凡\n聯繫:[email protected]"),
                ),
                Expanded(
                  child:    Container(
                    decoration: BoxDecoration(
                        color: Colors.white
                    ),
                    child: gamesWidget,
                  ),
                )
              ]
          )
      );
  }

  guideWidget() {
    return gamesWidget;
  }

}
效果截圖
標題

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章