Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.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
Flutter 如何使透明图像的特定部分可单击?_Flutter_Image Processing_Flutter Layout - Fatal编程技术网

Flutter 如何使透明图像的特定部分可单击?

Flutter 如何使透明图像的特定部分可单击?,flutter,image-processing,flutter-layout,Flutter,Image Processing,Flutter Layout,我在颤振应用程序中有一个堆栈,它将多个图像堆叠在彼此的顶部。它们都具有相同的宽度和高度,并且具有透明的背景 就个人而言,它们是这样的: 当它们重叠时,它们看起来如下所示: 我需要使每个图片的可见部分可点击。我不希望与任何图像的透明部分进行任何交互。我尝试过使用GestureDetector,但由于所有图像的大小都相同,所以效果不太好。我如何做到这一点? 在我使用的任何矢量图形编辑器中圈出图片的边框,这是免费的 将其另存为svg文件,打开它并从svg复制路径 将svg路径转换为颤振路径,我已经

我在颤振应用程序中有一个堆栈,它将多个图像堆叠在彼此的顶部。它们都具有相同的宽度和高度,并且具有透明的背景

就个人而言,它们是这样的:

当它们重叠时,它们看起来如下所示:

我需要使每个图片的可见部分可点击。我不希望与任何图像的透明部分进行任何交互。我尝试过使用GestureDetector,但由于所有图像的大小都相同,所以效果不太好。我如何做到这一点?

  • 在我使用的任何矢量图形编辑器中圈出图片的边框,这是免费的
  • 将其另存为svg文件,打开它并从svg复制路径
  • 将svg路径转换为颤振路径,我已经使用了这个包
  • 使用自定义剪裁器按路径剪裁图像
  • 不幸的是,path_绘图包忽略了路径的开头。因此,您需要通过添加偏移量来添加它
  • 添加手势检测器
  • 导入“包装:颤振/材料.省道”;
    导入“package:path_drawing/path_drawing.dart”;
    void main()=>runApp(MyApp());
    类MyApp扩展了无状态小部件{
    @凌驾
    小部件构建(构建上下文){
    返回材料PP(
    标题:“颤振演示”,
    主题:主题数据(
    主样本:颜色。蓝色,
    ),
    家:脚手架(
    正文:安全区(
    子:MyHomePage(),
    ),
    ),
    );
    }
    }
    类MyHomePage扩展StatefulWidget{
    @凌驾
    _MyHomePageState createState()=>\u MyHomePageState();
    }
    类_MyHomePageState扩展状态{
    单击的字符串=“”;
    @凌驾
    小部件构建(构建上下文){
    返回堆栈(
    儿童:[
    _getClippedImage(
    克利伯:克利伯(
    svgPath:svgCarPath,
    偏移量:偏移量(66157),
    ),
    图像:“assets/image.png”,
    onClick:_handleClick(“汽车”),
    ),
    _getClippedImage(
    克利伯:克利伯(
    svgPath:svgManPath,
    偏移量:偏移量(115,53),
    ),
    图像:“assets/image.png”,
    onClick:_handleClick(“人”),
    ),
    定位(
    子:文本(
    点击,
    样式:TextStyle(字体大小:30),
    ),
    底部:0,
    ),
    ],
    );
    }
    void Function()_handleClick(字符串单击图像){
    return()=>setState(){
    单击=单击图像;
    });
    }
    Widget\u getClippedImage({
    _克利伯克利伯,
    字符串图像,
    void Function()onClick,
    }) {
    返回ClipPath(
    克利伯:克利伯,
    儿童:手势检测器(
    onTap:onClick,
    子级:Image.asset('assets/Image.png'),
    ),
    );
    }
    }
    类_Clipper扩展了CustomClipper{
    _Clipper({this.svgPath,this.offset=offset.zero});
    字符串svgPath;
    偏移量;
    @凌驾
    路径getClip(大小){
    var path=parseSvgPathData(svgPath);
    返回路径移位(偏移);
    }
    @凌驾
    bool shouldReclip(CustomClipper oldClipper){
    返回false;
    }
    }
    常量svgCarPath=
    'M35 13.7742L46.9628 1.52606L58.8398 5.97996V17.1147L111.544 13.7742L117.111 50.8899L109.688 55.715C108.575 61.2823 103.75 72.417 93.3574 72.417C82.965 72.417 80.4751 64.3753 80.4751 59.4266C68.1032 55.5913.5355.5355 53.8592 39.5397 57.5708C35.0128 76.8214.4376.0512.417C82.965.375.417 80.4751.4751 64.3751.3753.47517.47518.732.737'737';
    常量svgManPath=
    'M50.2647 19.9617C50.6461 5.85163 47.5952 0.703364 38.2521 0.703369C32.0776 2.87051 31.0217 6.36354 30.625 14.0016C30.625 14.0016 27.9555 28.1424 30.625 32.8584C33.2945 37.5744 42.1784 35.788 39.3961 40.7456C36.6138 45.7032 27.9555 63.6268 27.9555.6268H22.6564.7870 C130.623.793.733.733.739-793.7390.879345 106.911L8.12508 109.199L19.1844 96.8046L12.1293 120.258L15.9428 123.499L22.6165 121.402L32.7224 97.9487L39.3961 104.622C36.5995 110.597 32.2267 122.088 37.108 120.258C43.2097 117.97 54.2865 120.258 66.0909 113.394C75.3267 28.4915 49.8834.0719 50.2647 19.9617Z';
    
    我对flatter不太熟悉,但在一般编程中:您不能找出单击像素的颜色或alpha吗?如果是这样,您可以很容易地判断他们是单击了图像部分还是透明部分。我怀疑你是否能在“第二张”图片中捕捉到点击。或者,如果“第一个”(堆栈顶部的一个)是唯一获得单击事件的,那么您将永远不知道该像素在“第二个”图像中是否有颜色。@FedericoAlvarez我将把这些图像叠加在提取它们的原始图像上,因此获取单击像素的颜色可能会遇到问题。是的,当这些图像堆叠在一起时,即使是获取点击像素的颜色也似乎是一项困难的任务。这不是一项容易的任务,因为图像只是整个区域上的一个矩形。我会使用剪贴画:用路径定义图像周围的区域,正确定位,并添加一个手势检测器。我做了一些类似的东西(带有一个按钮),我将其配置为适合我的目的。谢谢
        import 'package:flutter/material.dart';
        import 'package:path_drawing/path_drawing.dart';
    
        void main() => runApp(MyApp());
    
        class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return MaterialApp(
              title: 'Flutter Demo',
              theme: ThemeData(
                primarySwatch: Colors.blue,
              ),
              home: Scaffold(
                body: SafeArea(
                  child: MyHomePage(),
                ),
              ),
            );
          }
        }
    
        class MyHomePage extends StatefulWidget {
          @override
          _MyHomePageState createState() => _MyHomePageState();
        }
    
        class _MyHomePageState extends State<MyHomePage> {
          String clicked = '';
    
          @override
          Widget build(BuildContext context) {
            return Stack(
              children: <Widget>[
                _getClippedImage(
                  clipper: _Clipper(
                    svgPath: svgCarPath,
                    offset: Offset(66, 157),
                  ),
                  image: 'assets/image.png',
                  onClick: _handleClick('car'),
                ),
                _getClippedImage(
                  clipper: _Clipper(
                    svgPath: svgManPath,
                    offset: Offset(115, 53),
                  ),
                  image: 'assets/image.png',
                  onClick: _handleClick('man'),
                ),
                Positioned(
                  child: Text(
                    clicked,
                    style: TextStyle(fontSize: 30),
                  ),
                  bottom: 0,
                ),
              ],
            );
          }
    
          void Function() _handleClick(String clickedImage) {
            return () => setState(() {
                  clicked = clickedImage;
                });
          }
    
          Widget _getClippedImage({
            _Clipper clipper,
            String image,
            void Function() onClick,
          }) {
            return ClipPath(
              clipper: clipper,
              child: GestureDetector(
                onTap: onClick,
                child: Image.asset('assets/image.png'),
              ),
            );
          }
        }
    
        class _Clipper extends CustomClipper<Path> {
          _Clipper({this.svgPath, this.offset = Offset.zero});
    
          String svgPath;
          Offset offset;
          @override
          Path getClip(Size size) {
            var path = parseSvgPathData(svgPath);
    
            return path.shift(offset);
          }
    
          @override
          bool shouldReclip(CustomClipper oldClipper) {
            return false;
          }
        }
    
        const svgCarPath =
            'M35 13.7742L46.9628 1.52606L58.8398 5.97996V17.1147L111.544 13.7742L117.111 50.8899L109.688 55.715C108.575 61.2823 103.75 72.417 93.3574 72.417C82.965 72.417 80.4751 64.3753 80.4751 59.4266C68.1032 55.5913 53.5355 53.8592 39.5397 57.5708C35.0128 76.8252 14.4397 76.0591 12.0741 55.715H0.939362V26.7647L12.0741 17.1147L35.8281 13.7742Z';
        const svgManPath =
            'M50.2647 19.9617C50.6461 5.85163 47.5952 0.703364 38.2521 0.703369C32.0776 2.87051 31.0217 6.36354 30.625 14.0016C30.625 14.0016 27.9555 28.1424 30.625 32.8584C33.2945 37.5744 42.1784 35.788 39.3961 40.7456C36.6138 45.7032 27.9555 63.6268 27.9555 63.6268H22.6165C14.7864 70.572 19.1843 79.9011 12.1293 88.7962C3.01255 100.291 -0.77319 103.733 0.879345 106.911L8.12508 109.199L19.1844 96.8046L12.1293 120.258L15.9428 123.499L22.6165 121.402L32.7224 97.9487L39.3961 104.622C36.5995 110.597 32.2267 122.088 37.108 120.258C43.2097 117.97 54.2865 120.258 66.0909 113.394C75.3267 28.4915 49.8834 34.0719 50.2647 19.9617Z';