【问题标题】:Design a background from 2 images in flutter在颤动中从 2 张图像设计背景
【发布时间】:2019-08-05 15:47:29
【问题描述】:

我想创建一个新的无状态小部件类,它由 2 个图像(顶部,底部)和一条线(由一个函数定义,例如 (x){x+500},一个宽度(可以是 0,如果它应该) t 被绘制)和颜色)分隔两个图像。

对于每个像素:

  • 如果某个像素的 y 位置大于f(x) + width/2 的结果,则应绘制底部的像素
  • 如果它小于f(x) - width / 2,则应绘制顶部像素
  • 否则应绘制给定线条颜色的像素

请看一个mywidget({'top': A, 'bottom': B, 'f': (x){return sin(x)+500;}, 'width': 1, 'color': Color(0xFFFFFFFF)}); 的示例:

(0,0)
+------+
|      |
|  A   |
| __   |
|/  \__|
|      |
|  B   |
+------+(e.g. 1920,1080)

是否存在由(数学)函数定义形状的线条小部件?

this 是唯一的方法吗?或者是否有一个容器小部件已经允许这样做?我查看了Stack widget,但这并不能完全解决问题,因为我需要一个结构来决定如上所述渲染哪个像素。决定应该发生什么的功能应该由用户提供。

【问题讨论】:

    标签: flutter background flutter-layout


    【解决方案1】:

    ClipPathCustomClipper<Path> 可以帮助您。
    你能得到什么:

    示例源代码:

    import 'dart:math';
    
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(
        MaterialApp(
          home: Scaffold(
            body: ClippedPartsWidget(
              top: Container(
                color: Colors.red,
              ),
              bottom: Container(
                color: Colors.blue,
              ),
              splitFunction: (Size size, double x) {
                // normalizing x to make it exactly one wave
                final normalizedX = x / size.width * 2 * pi;
                final waveHeight = size.height / 15;
                final y = size.height / 2 - sin(normalizedX) * waveHeight;
    
                return y;
              },
            ),
          ),
        ),
      );
    }
    
    class ClippedPartsWidget extends StatelessWidget {
      final Widget top;
      final Widget bottom;
      final double Function(Size, double) splitFunction;
    
      ClippedPartsWidget({
        @required this.top,
        @required this.bottom,
        @required this.splitFunction,
      });
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: <Widget>[
            // I'm putting unmodified top widget to back. I wont cut it.
            // Instead I'll overlay it with clipped bottom widget.
            top,
            Align(
              alignment: Alignment.bottomCenter,
              child: ClipPath(
                clipper: FunctionClipper(splitFunction: splitFunction),
                child: bottom,
              ),
            ),
          ],
        );
      }
    }
    
    class FunctionClipper extends CustomClipper<Path> {
      final double Function(Size, double) splitFunction;
    
      FunctionClipper({@required this.splitFunction}) : super();
    
      Path getClip(Size size) {
        final path = Path();
    
        // move to split line starting point
        path.moveTo(0, splitFunction(size, 0));
    
        // draw split line
        for (double x = 1; x <= size.width; x++) {
          path.lineTo(x, splitFunction(size, x));
        }
    
        // close bottom part of screen
        path.lineTo(size.width, size.height);
        path.lineTo(0, size.height);
    
        return path;
      }
    
      @override
      bool shouldReclip(CustomClipper<Path> oldClipper) {
        // I'm returning fixed 'true' value here for simplicity, it's not the part of actual question
        // basically that means that clipping will be redrawn on any changes
        return true;
      }
    }
    

    【讨论】:

    • 哇,真不错!非常感谢。关于可选地以固定颜色绘制路径的另一件事(以前从示例构造函数调用中省略,抱歉),我可以使用Canvas.drawPath 绘制路径吗?如果是这样,您会在 getClip 函数中绘制路径,还是将路径保存为 FunctionClipper 的成员,以便您可以在 ClippedPartsWidget 的构建函数中绘制它?怎么去这里?如果给定宽度和width&gt;0,我只想绘制 splitFunction。
    • @jaaq 是的,您可以将结果路径与Canvas.drawPath 一起使用,但它需要使用另一组小部件(CustomPaintCustomPainter)。关于存储路径:如果其他小部件无法使用它,我会将其存储在 FunctionClipper(或 CustomPainter)中以进行封装
    • 非常感谢。一旦 stackoverflow 允许我,我会奖励你赚来的赏金:)
    • 你能再帮我一次吗?我尝试用CustomPaint 小部件包装ClippedPartsWidget,在那里我使用相同的函数再次绘制相同的路径(效率低下,但现在已经足够了)。但是,如果我用width=3 来绘制路径,它要么不显示油漆是否作为画家属性传递给它,要么它用我给它的颜色覆盖整个底部(剪辑的小部件)。您能否更详细地解释或告诉我如何完成此小部件,以便它可以选择呈现由 splitFunction 定义的行?
    • 哦,你要画一条线吗?那我误会你了。然后需要另一条路径,只包含分割线。还有一个设置Paint.style = PaintingStyle.stroke的选项,但在这种情况下,它将绘制整个路径的轮廓。
    猜你喜欢
    • 2020-08-17
    • 2019-12-27
    • 2019-09-07
    • 2021-06-18
    • 2018-07-20
    • 2022-01-14
    • 2020-10-01
    • 2021-06-22
    • 1970-01-01
    相关资源
    最近更新 更多