从抖动中的2张图像设计背景 [英] Design a background from 2 images in flutter

查看:56
本文介绍了从抖动中的2张图像设计背景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个新的无状态小部件类,该类由2个图像(顶部,底部)和一条线(由一个函数定义,例如(x){x+500})定义,宽度(可以为0,如果不可以的话)绘制),并用颜色将两个图像分开.

I'd like to create a a new stateless widget class that is defined by 2 images(top, bottom) and a line(defined by a function, e.g. (x){x+500}, a width(can be 0, if it shouldn't be drawn), and a color) separating the two images.

对于每个像素:

  • 如果像素的y位置大于f(x) + width/2的结果,则应绘制底部的像素
  • 如果小于f(x) - width / 2,则应在顶部绘制一个像素
  • 否则,将绘制给定线条颜色的像素
  • If the y position of a pixel is greater than the result of f(x) + width/2 a pixel of bottom shall be drawn
  • If it's smaller than f(x) - width / 2 a pixel of top shall be drawn
  • Else a pixel of the given line color shall be drawn

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

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

是否有一个线形控件,其中的形状是由(数学)函数定义的?

Is there a line widget where the shape is defined by a (mathematic) function?

是唯一的方法吗?还是有一个已经允许这样做的容器小部件?我看过堆栈小工具,但这并不能完全解决问题,因为我需要一种结构来决定如上所述渲染哪个像素.决定应该发生什么的功能应该由用户提供.

Is this the only way to do it? Or is there a container widget that already allows this? I have looked at the Stack widget but that's not quite solving the problem, as I'd need a structure to decide which pixel is rendered as described above. The function to decide which should happen should be supplyable by the user.

推荐答案

ClipPathCustomClipper<Path>可以为您提供帮助.
您会得到什么:

示例源代码:

ClipPath with CustomClipper<Path> can help you with it.
What you can get:

Example source code:

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;
  }
}

这篇关于从抖动中的2张图像设计背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆