Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dart 颤振-像巫师学校应用程序一样的掩蔽效果_Dart_Flutter - Fatal编程技术网

Dart 颤振-像巫师学校应用程序一样的掩蔽效果

Dart 颤振-像巫师学校应用程序一样的掩蔽效果,dart,flutter,Dart,Flutter,在这里,我想做一个掩蔽效果,像巫师学校的应用程序。 在这里,我使用的是renderProxy Box,但我一次只能做一个遮罩,我想提供多时间效果。使用blendMode.clear删除封面图像,并显示图像。那个么,有并没有其他方法来实现预期章节中给出的多重掩蔽效果呢 import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'dart: math' as math; class

在这里,我想做一个掩蔽效果,像巫师学校的应用程序。 在这里,我使用的是
renderProxy Box
,但我一次只能做一个遮罩,我想提供多时间效果。使用
blendMode.clear
删除封面图像,并显示图像。那个么,有并没有其他方法来实现预期章节中给出的多重掩蔽效果呢

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart: math' as math;
class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Scratch Card',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Scratch Card'),
        ),
        body: Material(
          child: Center(
            child: SizedBox(
              width: 500.0,
              height: 500.0,
              child: Stack(
                children: <Widget>[
                  ScratchCard(
                    cover: Stack(
                      fit: StackFit.expand,
                      children: <Widget>[
                        FittedBox(
                          child: Image.asset(
                            'assets/bird.jpg',
                            repeat: ImageRepeat.repeat,
                          ),
                        ),
                      ],
                    ),
                    reveal: DecoratedBox(
                      decoration: const BoxDecoration(color: Colors.black),
                      child: Center(
                        child:
                            FittedBox(child: Image.asset('assets/flower.jpg')),
                      ),
                    ),
                    strokeWidth: 15.0,
                    finishPercent: 50,
                    onComplete: () => print('The card is now clear!'),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class ScratchCard extends StatefulWidget {
  const ScratchCard({
    Key key,
    this.cover,
    this.reveal,
    this.strokeWidth = 25.0,
    this.finishPercent,
    this.onComplete,
  }) : super(key: key);

  final Widget cover;
  final Widget reveal;
  final double strokeWidth;
  final int finishPercent;
  final VoidCallback onComplete;

  @override
  _ScratchCardState createState() => _ScratchCardState();
}

class _ScratchCardState extends State<ScratchCard> {
  _ScratchData _data = _ScratchData();

  Offset _lastPoint = null;

  Offset _globalToLocal(Offset global) {
    return (context.findRenderObject() as RenderBox).globalToLocal(global);
  }

  double _distanceBetween(Offset point1, Offset point2) {
    return math.sqrt(math.pow(point2.dx - point1.dx, 2) +
        math.pow(point2.dy - point1.dy, 2));
  }

  double _angleBetween(Offset point1, Offset point2) {
    return math.atan2(point2.dx - point1.dx, point2.dy - point1.dy);
  }

  void _onPanDown(DragDownDetails details) {
    _lastPoint = _globalToLocal(details.globalPosition);
  }

  void _onPanUpdate(DragUpdateDetails details) {
    final currentPoint = _globalToLocal(details.globalPosition);
    final distance = _distanceBetween(_lastPoint, currentPoint);
    final angle = _angleBetween(_lastPoint, currentPoint);
    for (double i = 0.0; i < distance; i++) {
      _data.addPoint(Offset(
        _lastPoint.dx + (math.sin(angle) * i),
        _lastPoint.dy + (math.cos(angle) * i),
      ));
    }
    _lastPoint = currentPoint;
  }

  void _onPanEnd(TapUpDetails details) {
    final areaRect = context.size.width * context.size.height;
    double touchArea = math.pi * widget.strokeWidth * widget.strokeWidth;
    double areaRevealed =
        _data._points.fold(0.0, (double prev, Offset point) => touchArea);
    print('areaRect $areaRect $areaRevealed');
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onPanDown: _onPanDown,
      onPanUpdate: _onPanUpdate,
      onTapUp: _onPanEnd,
      child: Stack(
        fit: StackFit.expand,
        children: <Widget>[
          widget.reveal,
          _ScratchCardLayout(
            strokeWidth: widget.strokeWidth,
            data: _data,
            child: widget.cover,
          ),
        ],
      ),
    );
  }
}

class _ScratchCardLayout extends SingleChildRenderObjectWidget {
  _ScratchCardLayout({
    Key key,
    this.strokeWidth = 25.0,
    @required this.data,
    @required this.child,
  }) : super(
          key: key,
          child: child,
        );

  final Widget child;
  final double strokeWidth;
  final _ScratchData data;

  @override
  RenderObject createRenderObject(BuildContext context) {
    return _ScratchCardRender(
      strokeWidth: strokeWidth,
      data: data,
    );
  }

  @override
  void updateRenderObject(
      BuildContext context, _ScratchCardRender renderObject) {
    renderObject
      ..strokeWidth = strokeWidth
      ..data = data;
  }
}

class _ScratchCardRender extends RenderProxyBox {
  _ScratchCardRender({
    RenderBox child,
    double strokeWidth,
    _ScratchData data,
  })  : assert(data != null),
        _strokeWidth = strokeWidth,
        _data = data,
        super(child);

  double _strokeWidth;
  _ScratchData _data;

  set strokeWidth(double strokeWidth) {
    assert(strokeWidth != null);
    if (_strokeWidth == strokeWidth) {
      return;
    }
    _strokeWidth = strokeWidth;
    markNeedsPaint();
  }

  set data(_ScratchData data) {
    assert(data != null);
    if (_data == data) {
      return;
    }
    if (attached) {
      _data.removeListener(markNeedsPaint);
      data.addListener(markNeedsPaint);
    }
    _data = data;
    markNeedsPaint();
  }

  @override
  void attach(PipelineOwner owner) {
    super.attach(owner);
    _data.addListener(markNeedsPaint);
  }

  @override
  void detach() {
    _data.removeListener(markNeedsPaint);
    super.detach();
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    if (child != null) {
      context.canvas.saveLayer(offset & size, Paint());
      context.paintChild(child, offset);
      Paint clear = Paint()..blendMode = BlendMode.clear;
      _data._points.forEach((point) =>
          context.canvas.drawCircle(offset + point, _strokeWidth, clear));
      context.canvas.restore();
    }
  }

  @override
  bool get alwaysNeedsCompositing => child != null;
}

class _ScratchData extends ChangeNotifier {
  List<Offset> _points = [];

  void addPoint(Offset offset) {
    _points.add(offset);
    notifyListeners();
  }
}
导入“包装:颤振/材料.省道”;
导入“package:flatter/rendering.dart”;
导入'dart:math'作为数学;
类DemoApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“刮刮卡”,
家:脚手架(
appBar:appBar(
标题:文本(“草稿卡”),
),
主体:材料(
儿童:中心(
孩子:大小盒子(
宽度:500.0,
高度:500.0,
子:堆栈(
儿童:[
草稿卡(
封面:堆叠(
fit:StackFit.expand,
儿童:[
装配箱(
子:Image.asset(
“assets/bird.jpg”,
重复:ImageRepeat.repeat,
),
),
],
),
展示:装饰盒(
装饰:const BOX装饰(颜色:Colors.black),
儿童:中心(
儿童:
FittedBox(子项:Image.asset('assets/flower.jpg'),
),
),
冲程宽度:15.0,
完成百分比:50,
onComplete:()=>打印('卡现在已清除!'),
),
],
),
),
),
),
),
);
}
}
类ScratchCard扩展了StatefulWidget{
常数刮刮卡({
关键点,
这个封面,
这个,透露,,
该值为0.strokeWidth=25.0,
这是百分之十,
这个。完成了,
}):super(key:key);
最终小部件封面;
最终小部件显示;
最终双冲程宽度;
最终完成百分比;
最终完成;
@凌驾
_ScratchCardState createState()=>\u ScratchCardState();
}
类_ScratchCardState扩展状态{
_ScratchData _data=_ScratchData();
偏移量_lastPoint=null;
偏移量_全局全局(偏移量全局){
return(context.findenderObject()作为RenderBox.globalToLocal(全局);
}
双距离(偏移点1、偏移点2){
返回math.sqrt(math.pow(point2.dx-point1.dx,2)+
pow(point2.dy-point1.dy,2));
}
双角度(偏移点1、偏移点2){
返回math.atan2(point2.dx-point1.dx,point2.dy-point1.dy);
}
作废_onPanDown(dragdown详细信息){
_lastPoint=_globalTopolocal(详细信息:globalPosition);
}
void _onPanUpdate(DragUpdate详细信息){
最终电流点=_全局全局坐标(详细信息:全局位置);
最终距离=_距离(_lastPoint,currentPoint);
最终角度=_角度之间(_lastPoint,currentPoint);
对于(双i=0.0;i触摸区域);
打印('areaRect$areaRect$areaRect');
}
@凌驾
小部件构建(构建上下文){
返回手势检测器(
行为:HitTestBehavior.不透明,
onPanDown:_onPanDown,
onPanUpdate:_onPanUpdate,
onTapUp:_onPanEnd,
子:堆栈(
fit:StackFit.expand,
儿童:[
widget.discover,
_草稿卡布局(
strokeWidth:widget.strokeWidth,
数据:_数据,
孩子:widget.cover,
),
],
),
);
}
}
类_ScratchCardLayout扩展了SingleChildRenderObjectWidget{
_草稿卡布局({
关键点,
该值为0.strokeWidth=25.0,
@需要这个数据,
@需要这个孩子,
}):超级(
钥匙:钥匙,
孩子:孩子,
);
最后一个孩子;
最终双冲程宽度;
最终数据;
@凌驾
RenderObject createRenderObject(构建上下文上下文){
返回\u ScratchCardRender(
strokeWidth:strokeWidth,
数据:数据,
);
}
@凌驾
void updatenderObject(
BuildContext上下文,_scratchCardRenderRenderObject){
渲染对象
..冲程宽度=冲程宽度
..数据=数据;
}
}
类_ScratchCardRender扩展了RenderProxyBox{
_ScratchCardRender({
RenderBox儿童,
双冲程宽度,
_数据数据,
}):assert(数据!=null),
_冲程宽度=冲程宽度,
_数据=数据,
超级(儿童);
双冲程宽度;
_ScratchData_数据;
设置strokeWidth(双strokeWidth){
断言(strokeWidth!=null);
如果(_strokeWidth==strokeWidth){
返回;
}
_冲程宽度=冲程宽度;
markNeedsPaint();
}
设置数据(_scratchdatadata){
断言(数据!=null);
如果(_data==数据){
返回;
}
如有(附件){
_数据。removeListener(MarkNeedsPoint);
data.addListener(markNeedsPaint);
}
_数据=数据;
markNeedsPaint();
}
@凌驾
无效附加(管道所有者){
超级附件(所有者);
_data.addListener(markNeedsPaint);
}
@凌驾
void detach(){
_数据。removeListener(MarkNeedsPoint);
super.detach();
}
@凌驾
无效绘制(绘制上下文上下文,偏移){
如果(ch
ui.Image uiImage;
  static Future<void> cacheImage(String asset) async {
        if (maskImageMap[asset] == null) {
          try {
            ByteData data = await rootBundle.load(asset);
            ui.Codec codec = await ui.instantiateImageCodec(
              data.buffer.asUint8List(),
            );
            ui.FrameInfo fi = await codec.getNextFrame();
           uiImage = fi.image;
          } catch (e) {
            print(e);
          }
        }
      }
final Float64List deviceTransform = new Float64List(16)
      ..[0] = devicePixelRatio
      ..[5] = devicePixelRatio
      ..[10] = 1.0
      ..[15] = 3.5;
 canvas.saveLayer();
        Paint().shader = ImageShader(uiImage,
                  TileMode.repeated, TileMode.repeated, deviceTransform);