flutter 移动、旋转、放大、缩小、画笔

首先是移动、旋转、放大缩小


平移旋转伸缩.gif
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class ScalePageView extends StatefulWidget {
  const ScalePageView({Key? key}) : super(key: key);

  @override
  State<ScalePageView> createState() => _ScalePageViewState();
}

class _ScalePageViewState extends State<ScalePageView> {

  double _top = 100.0;
  double _left = 100.0;

  double _width = 200;
  double _baseWidth = 200;

  double _rotation = 0.0;
  double _baseRotation = 0.0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Positioned(
              top: _top,
              left: _left,
              child: GestureDetector(

                onScaleStart: (_){
                  _baseWidth = _width;
                  _baseRotation = _rotation;
                },
                onScaleUpdate: (ScaleUpdateDetails e){
                    setState((){
                      _left += e.focalPointDelta.dx;//水平方向偏移量
                      _top +=  e.focalPointDelta.dy; //竖直方向偏移量

                      _rotation = _baseRotation + e.rotation;//选转量

                      _width = _baseWidth * e.scale.clamp(0.8, 5); //缩小放大

                    });
                },
                //不可以同时使用onPanUpdate和onScaleUpdate,因为onScaleUpdate是onPanUpdate的父类
                //同时使用的话会报错scale is a superset of pan
                // onPanUpdate: (e){
                //
                // },
                child: Transform.rotate(
                  angle: _rotation,
                  child: Container(
                    width: _width ,
                    height: _width ,
                    color: Colors.red,
                  ),
                ),
              )
          )
        ],
      ),
    );
  }

//系统提供的InteractiveViewer,不适合项目仅供参考

  // @override
  // Widget build(BuildContext context) {
  //   return Scaffold(
  //     body: Container(
  //       height: double.infinity,
  //       width: double.infinity,
  //       alignment: Alignment.center,
  //       color: Colors.red.withAlpha(33),
  //       child: InteractiveViewer(
  //         ///只能沿着坐标轴滑动,就是横着或者竖着滑动
  //         alignPanAxis: false,
  //
  //         ///是否能够用手指滑动
  //         panEnabled: true,
  //
  //         ///子控件可以移动的范围
  //         boundaryMargin: EdgeInsets.all(double.infinity),
  //
  //         ///是否开启缩放
  //         scaleEnabled: true,
  //
  //         ///放大系数
  //         maxScale: 2.5,
  //
  //         ///缩小系数
  //         minScale: 0.3,
  //
  //         ///是否约束
  //         constrained: false,
  //         onInteractionStart: (details){
  //           print("onInteractionStart----"+details.toString());
  //         },
  //         onInteractionEnd: (details){
  //           print("onInteractionEnd----"+details.toString());
  //         },
  //         onInteractionUpdate: (details){
  //           print("onInteractionUpdate----"+details.toString());
  //
  //         },
  //         child: Row(
  //           children: [
  //             Container(width: 100, height: 100, color: Colors.red,),
  //           ],
  //         ),
  //       ),
  //     ),
  //   );
  // }
}

2.画笔工具


画笔.gif
import 'package:flutter/material.dart';

class DrawingBoard extends StatefulWidget {
  const DrawingBoard({Key? key}) : super(key: key);

  @override
  State<DrawingBoard> createState() => _DrawingBoardState();
}

class _DrawingBoardState extends State<DrawingBoard> {
  final List<List<Offset>> _path = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Paint"),
        actions: [
          TextButton(onPressed: (){
            setState((){
              _path.removeLast();
            });
          }, child: const Text("撤销", style: TextStyle(color: Colors.black, fontSize: 16),)),
        ],
      ),
      body: Listener(
        onPointerDown: (PointerDownEvent pointerDownEvent){
          setState((){
            _path.add([pointerDownEvent.localPosition]);
          });
        },

        onPointerMove: (PointerMoveEvent pointerMoveEvent){
          setState((){
            _path[_path.length-1].add(pointerMoveEvent.localPosition);
          });
        },
        onPointerUp: (PointerUpEvent pointerUpEvent){
          setState((){
            _path[_path.length-1].add(pointerUpEvent.localPosition);
          });
        },

        onPointerCancel: (PointerCancelEvent pointerCancelEvent){
          setState((){
            _path[_path.length-1].add(pointerCancelEvent.localPosition);
          });
        },
        child: SizedBox(
          width: double.infinity,
          height: double.infinity,
          child: CustomPaint(
            painter: DrawingBoardPainter(_path),
          ),
        ),
      ),
    );
  }
}

class DrawingBoardPainter extends CustomPainter {
  final List<List<Offset>> path;

  DrawingBoardPainter(this.path);
  final Paint _paint = Paint()
  ..color = Colors.red
  ..style = PaintingStyle.stroke
  ..strokeWidth = 10;
  // ..strokeJoin = StrokeJoin.round;
  @override
  void paint(Canvas canvas, Size size) {
    // TODO: implement paint
    path.forEach((list) {
      Path path = Path();
      for(int i = 0; i < list.length; i++){
        if(i == 0){
          path.moveTo(list[i].dx, list[i].dy);
        }else{
          path.lineTo(list[i].dx, list[i].dy);
        }
      }
      canvas.drawPath(path, _paint);
    });
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return true;
  }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容