在颤动中从 2 张图像设计背景 [英] Design a background from 2 images in flutter
问题描述
我想创建一个新的无状态小部件类,它由 2 个图像(顶部、底部)和一条线(由一个函数定义,例如 (x){x+500}
,一个宽度(可以是 0,如果它不应该被绘制)和一个颜色)分隔两个图像.
对于每个像素:
- 如果像素的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)+------+|||一个 ||__ ||/\__||||乙|+--------+(例如 1920,1080)
是否有形状由(数学)函数定义的线条小部件?
示例源代码:
import 'dart:math';导入包:颤振/material.dart";无效的主要(){运行应用程序(材料应用程序(家:脚手架(正文:ClippedPartsWidget(顶部:容器(颜色:颜色.红色,),底部:容器(颜色:颜色.蓝色,),splitFunction: (Size size, double x) {//标准化 x 使其恰好是一个波最终归一化X = x/size.width * 2 * pi;最终 waveHeight = size.height/15;最终 y = size.height/2 - sin(normalizedX) * waveHeight;返回 y;},),),),);}类 ClippedPartsWidget 扩展 StatelessWidget {最终小部件顶部;最终的小部件底部;final double Function(Size, double) splitFunction;ClippedPartsWidget({@required this.top,@required this.bottom,@required this.splitFunction,});@覆盖小部件构建(BuildContext 上下文){返回堆栈(孩子们:<小部件>[//我将未修改的顶部小部件放在后面.我不会剪的.//相反,我将用裁剪的底部小部件覆盖它.最佳,对齐(对齐:Alignment.bottomCenter,孩子:剪辑路径(剪裁器:FunctionClipper(splitFunction:splitFunction),孩子:底部,),),],);}}类 FunctionClipper 扩展 CustomClipper;{final double Function(Size, double) splitFunction;FunctionClipper({@required this.splitFunction}) : super();路径 getClip(Size size) {最终路径 = 路径();//移动到分割线起点path.moveTo(0, splitFunction(size, 0));//绘制分割线for (double x = 1; x <= size.width; x++) {path.lineTo(x, splitFunction(size, x));}//关闭屏幕底部path.lineTo(size.width, size.height);path.lineTo(0, size.height);返回路径;}@覆盖bool shouldReclip(CustomClipper<Path> oldClipper) {//为了简单起见,我在这里返回固定的真"值,这不是实际问题的一部分//基本上这意味着剪辑将在任何更改时重新绘制返回真;}}
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.
For each pixel:
- 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
Blow see an example of what mywidget({'top': A, 'bottom': B, 'f': (x){return sin(x)+500;}, 'width': 1, 'color': Color(0xFFFFFFFF)});
could look like:
(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.
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屋!