Flutter 将图像切成等份,或者只调用图像的一部分?飞镖
我需要将图片的一部分分配到一个竞争者示例中—一个益智游戏示例。使用颤振,这是一些代码,你可以这样做:Flutter 将图像切成等份,或者只调用图像的一部分?飞镖,flutter,dart,Flutter,Dart,我需要将图片的一部分分配到一个竞争者示例中—一个益智游戏示例。使用颤振,这是一些代码,你可以这样做: import 'dart:math'; import 'package:flutter/material.dart'; class PuzzlePiece extends StatefulWidget { final Image image; final Size imageSize; final int row; final int col; final int max
import 'dart:math';
import 'package:flutter/material.dart';
class PuzzlePiece extends StatefulWidget {
final Image image;
final Size imageSize;
final int row;
final int col;
final int maxRow;
final int maxCol;
PuzzlePiece(
{Key key,
@required this.image,
@required this.imageSize,
@required this.row,
@required this.col,
@required this.maxRow,
@required this.maxCol})
: super(key: key);
@override
PuzzlePieceState createState() {
return new PuzzlePieceState();
}
}
class PuzzlePieceState extends State<PuzzlePiece> {
double top;
double left;
@override
Widget build(BuildContext context) {
final imageWidth = MediaQuery.of(context).size.width;
final imageHeight = MediaQuery.of(context).size.height * MediaQuery.of(context).size.width / widget.imageSize.width;
final pieceWidth = imageWidth / widget.maxCol;
final pieceHeight = imageHeight / widget.maxRow;
if (top == null) {
top = Random().nextInt((imageHeight - pieceHeight).ceil()).toDouble();
top -= widget.row * pieceHeight;
}
if (left == null) {
left = Random().nextInt((imageWidth - pieceWidth).ceil()).toDouble();
left -= widget.col * pieceWidth;
}
return Positioned(
top: top,
left: left,
width: imageWidth,
child: ClipPath(
child: CustomPaint(
foregroundPainter: PuzzlePiecePainter(widget.row, widget.col, widget.maxRow, widget.maxCol),
child: widget.image
),
clipper: PuzzlePieceClipper(widget.row, widget.col, widget.maxRow, widget.maxCol),
),
);
}
}
// this class is used to clip the image to the puzzle piece path
class PuzzlePieceClipper extends CustomClipper<Path> {
final int row;
final int col;
final int maxRow;
final int maxCol;
PuzzlePieceClipper(this.row, this.col, this.maxRow, this.maxCol);
@override
Path getClip(Size size) {
return getPiecePath(size, row, col, maxRow, maxCol);
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
// this class is used to draw a border around the clipped image
class PuzzlePiecePainter extends CustomPainter {
final int row;
final int col;
final int maxRow;
final int maxCol;
PuzzlePiecePainter(this.row, this.col, this.maxRow, this.maxCol);
@override
void paint(Canvas canvas, Size size) {
final Paint paint = Paint()
..color = Color(0x80FFFFFF)
..style = PaintingStyle.stroke
..strokeWidth = 1.0;
canvas.drawPath(getPiecePath(size, row, col, maxRow, maxCol), paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
// this is the path used to clip the image and, then, to draw a border around it; here we actually draw the puzzle piece
Path getPiecePath(Size size, int row, int col, int maxRow, int maxCol) {
final width = size.width / maxCol;
final height = size.height / maxRow;
final offsetX = col * width;
final offsetY = row * height;
final bumpSize = height / 4;
var path = Path();
path.moveTo(offsetX, offsetY);
if (row == 0) {
// top side piece
path.lineTo(offsetX + width, offsetY);
} else {
// top bump
path.lineTo(offsetX + width / 3, offsetY);
path.cubicTo(offsetX + width / 6, offsetY - bumpSize, offsetX + width / 6 * 5, offsetY - bumpSize, offsetX + width / 3 * 2, offsetY);
path.lineTo(offsetX + width, offsetY);
}
if (col == maxCol - 1) {
// right side piece
path.lineTo(offsetX + width, offsetY + height);
} else {
// right bump
path.lineTo(offsetX + width, offsetY + height / 3);
path.cubicTo(offsetX + width - bumpSize, offsetY + height / 6, offsetX + width - bumpSize, offsetY + height / 6 * 5, offsetX + width, offsetY + height / 3 * 2);
path.lineTo(offsetX + width, offsetY + height);
}
if (row == maxRow - 1) {
// bottom side piece
path.lineTo(offsetX, offsetY + height);
} else {
// bottom bump
path.lineTo(offsetX + width / 3 * 2, offsetY + height);
path.cubicTo(offsetX + width / 6 * 5, offsetY + height - bumpSize, offsetX + width / 6, offsetY + height - bumpSize, offsetX + width / 3, offsetY + height);
path.lineTo(offsetX, offsetY + height);
}
if (col == 0) {
// left side piece
path.close();
} else {
// left bump
path.lineTo(offsetX, offsetY + height / 3 * 2);
path.cubicTo(offsetX - bumpSize, offsetY + height / 6 * 5, offsetX - bumpSize, offsetY + height / 6, offsetX, offsetY + height / 3);
path.close();
}
return path;
}
import'dart:math';
进口“包装:颤振/材料.省道”;
类PuzzlePiece扩展了StatefulWidget{
最终图像;
最终尺寸图像尺寸;
最后一行;
最终整数列;
最终int maxRow;
最终int maxCol;
拼图(
{键,
@需要这个图像,
@需要此图像大小,
@需要此行,
@需要这个,
@需要此.maxRow,
@需要此参数(maxCol})
:super(key:key);
@凌驾
PuzzlePieceState createState(){
返回新的状态();
}
}
类状态扩展状态{
双层顶;
左双;
@凌驾
小部件构建(构建上下文){
最终imageWidth=MediaQuery.of(context).size.width;
final imageHeight=MediaQuery.of(context).size.height*MediaQuery.of(context).size.width/widget.imageSize.width;
最终工件宽度=imageWidth/widget.maxCol;
最终工件高度=imageHeight/widget.maxRow;
if(top==null){
top=Random().nextInt((imageHeight-pieceHeight).ceil()).toDouble();
top-=widget.row*工件高度;
}
if(left==null){
left=Random().nextInt((imageWidth-pieceWidth.ceil()).toDouble();
left-=widget.col*工件宽度;
}
返回定位(
顶:顶,,
左:左,,
宽度:图像宽度,
孩子:克利帕斯(
孩子:定制油漆(
foregroundPainter:PuzzlePiecePainter(widget.row,widget.col,widget.maxRow,widget.maxCol),
子:widget.image
),
clipper:PuzzlePieceClipper(widget.row,widget.col,widget.maxRow,widget.maxCol),
),
);
}
}
//此类用于将图像剪裁到拼图块路径
类Clipper扩展了CustomClipper{
最后一行;
最终整数列;
最终int maxRow;
最终int maxCol;
拼图剪辑器(this.row,this.col,this.maxRow,this.maxCol);
@凌驾
路径getClip(大小){
返回getPiecePath(大小、行、列、maxRow、maxCol);
}
@凌驾
bool shouldReclip(CustomClipper oldClipper)=>false;
}
//此类用于围绕剪裁图像绘制边框
类painter扩展了CustomPainter{
最后一行;
最终整数列;
最终int maxRow;
最终int maxCol;
拼图绘制(this.row,this.col,this.maxRow,this.maxCol);
@凌驾
空心油漆(帆布,尺寸){
最终油漆=油漆()
…颜色=颜色(0x80FFFFFF)
…风格=绘画风格笔划
..冲程宽度=1.0;
drawPath(getPiecePath(大小、行、列、maxRow、maxCol)、绘制);
}
@凌驾
bool应重新绘制(自定义代理){
返回false;
}
}
//这是用于剪裁图像并在其周围绘制边框的路径;在这里,我们实际绘制了拼图
路径getPiecePath(大小、整数行、整数列、整数maxRow、整数maxCol){
最终宽度=size.width/maxCol;
最终高度=size.height/maxRow;
最终偏移量x=柱*宽度;
最终偏移量=行*高度;
最终尺寸=高度/4;
var path=path();
path.moveTo(offsetX,offsetY);
如果(行==0){
//顶部侧件
path.lineTo(偏移量+宽度,偏移量);
}否则{
//顶部凸起
路径.lineTo(偏移量+宽度/3,偏移量);
path.cubicTo(offsetX+width/6,offsetY-bumpSize,offsetX+width/6*5,offsetY-bumpSize,offsetX+width/3*2,offsetY);
path.lineTo(偏移量+宽度,偏移量);
}
if(col==maxCol-1){
//右侧件
path.lineTo(偏移量+宽度,偏移量+高度);
}否则{
//右凸点
path.lineTo(偏移量+宽度,偏移量+高度/3);
path.cubicTo(offsetX+width-bumpSize,offsetY+height/6,offsetX+width-bumpSize,offsetY+height/6*5,offsetX+width,offsetY+height/3*2);
path.lineTo(偏移量+宽度,偏移量+高度);
}
如果(行==maxRow-1){
//底部侧块
path.lineTo(偏移量x,偏移量+高度);
}否则{
//底部隆起
path.lineTo(偏移量+宽度/3*2,偏移量+高度);
path.cubicTo(offsetX+width/6*5,offsetY+height-bumpSize,offsetX+width/6,offsetY+height-bumpSize,offsetX+width/3,offsetY+height);
path.lineTo(偏移量x,偏移量+高度);
}
如果(列==0){
//左侧件
path.close();
}否则{
//左凸点
路径.lineTo(偏移量x,偏移量+高度/3*2);
path.cubicTo(offsetX-bumpSize,offsetY+height/6*5,offsetX-bumpSize,offsetY+height/6,offsetX,offsetY+height/3);
path.close();
}
返回路径;
}
我找到了这段代码,但我选择的部分是你发送的,图像和制作的部分,现在重要的是要知道它是如何使用的,使它成为一个新的有状态类,接收图像和一些你需要查看的其他参数,以便可以自定义你需要什么,如行数和列数,最小y最大值和图像本身,its使用一个新类扩展CustomClipper并点击它的方式实际上是创建片段的方法,通过计算行数和列数以及接收图像的宽度和高度
现在他使用的是这样的path.cubicTo(offsetX+width-bumpSize,offsetY+height/6,offsetX+width-bumpSize,offsetY+height/6*5,offsetX+width,offsetY+height/3*2)
但是创建拼图凹凸形状是很困难的,所以如果您不需要它,可以忽略它
您可以对这些代码稍加修改,看看它将如何满足您的需要。看,这是一些代码,您可以如何做到这一点:
import 'dart:math';
import 'package:flutter/material.dart';
class PuzzlePiece extends StatefulWidget {
final Image image;
final Size imageSize;
final int row;
final int col;
final int maxRow;
final int maxCol;
PuzzlePiece(
{Key key,
@required this.image,
@required this.imageSize,
@required this.row,
@required this.col,
@required this.maxRow,
@required this.maxCol})
: super(key: key);
@override
PuzzlePieceState createState() {
return new PuzzlePieceState();
}
}
class PuzzlePieceState extends State<PuzzlePiece> {
double top;
double left;
@override
Widget build(BuildContext context) {
final imageWidth = MediaQuery.of(context).size.width;
final imageHeight = MediaQuery.of(context).size.height * MediaQuery.of(context).size.width / widget.imageSize.width;
final pieceWidth = imageWidth / widget.maxCol;
final pieceHeight = imageHeight / widget.maxRow;
if (top == null) {
top = Random().nextInt((imageHeight - pieceHeight).ceil()).toDouble();
top -= widget.row * pieceHeight;
}
if (left == null) {
left = Random().nextInt((imageWidth - pieceWidth).ceil()).toDouble();
left -= widget.col * pieceWidth;
}
return Positioned(
top: top,
left: left,
width: imageWidth,
child: ClipPath(
child: CustomPaint(
foregroundPainter: PuzzlePiecePainter(widget.row, widget.col, widget.maxRow, widget.maxCol),
child: widget.image
),
clipper: PuzzlePieceClipper(widget.row, widget.col, widget.maxRow, widget.maxCol),
),
);
}
}
// this class is used to clip the image to the puzzle piece path
class PuzzlePieceClipper extends CustomClipper<Path> {
final int row;
final int col;
final int maxRow;
final int maxCol;
PuzzlePieceClipper(this.row, this.col, this.maxRow, this.maxCol);
@override
Path getClip(Size size) {
return getPiecePath(size, row, col, maxRow, maxCol);
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
// this class is used to draw a border around the clipped image
class PuzzlePiecePainter extends CustomPainter {
final int row;
final int col;
final int maxRow;
final int maxCol;
PuzzlePiecePainter(this.row, this.col, this.maxRow, this.maxCol);
@override
void paint(Canvas canvas, Size size) {
final Paint paint = Paint()
..color = Color(0x80FFFFFF)
..style = PaintingStyle.stroke
..strokeWidth = 1.0;
canvas.drawPath(getPiecePath(size, row, col, maxRow, maxCol), paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
// this is the path used to clip the image and, then, to draw a border around it; here we actually draw the puzzle piece
Path getPiecePath(Size size, int row, int col, int maxRow, int maxCol) {
final width = size.width / maxCol;
final height = size.height / maxRow;
final offsetX = col * width;
final offsetY = row * height;
final bumpSize = height / 4;
var path = Path();
path.moveTo(offsetX, offsetY);
if (row == 0) {
// top side piece
path.lineTo(offsetX + width, offsetY);
} else {
// top bump
path.lineTo(offsetX + width / 3, offsetY);
path.cubicTo(offsetX + width / 6, offsetY - bumpSize, offsetX + width / 6 * 5, offsetY - bumpSize, offsetX + width / 3 * 2, offsetY);
path.lineTo(offsetX + width, offsetY);
}
if (col == maxCol - 1) {
// right side piece
path.lineTo(offsetX + width, offsetY + height);
} else {
// right bump
path.lineTo(offsetX + width, offsetY + height / 3);
path.cubicTo(offsetX + width - bumpSize, offsetY + height / 6, offsetX + width - bumpSize, offsetY + height / 6 * 5, offsetX + width, offsetY + height / 3 * 2);
path.lineTo(offsetX + width, offsetY + height);
}
if (row == maxRow - 1) {
// bottom side piece
path.lineTo(offsetX, offsetY + height);
} else {
// bottom bump
path.lineTo(offsetX + width / 3 * 2, offsetY + height);
path.cubicTo(offsetX + width / 6 * 5, offsetY + height - bumpSize, offsetX + width / 6, offsetY + height - bumpSize, offsetX + width / 3, offsetY + height);
path.lineTo(offsetX, offsetY + height);
}
if (col == 0) {
// left side piece
path.close();
} else {
// left bump
path.lineTo(offsetX, offsetY + height / 3 * 2);
path.cubicTo(offsetX - bumpSize, offsetY + height / 6 * 5, offsetX - bumpSize, offsetY + height / 6, offsetX, offsetY + height / 3);
path.close();
}
return path;
}
import'dart:math';
进口“包装:颤振/材料.省道”;
类PuzzlePiece扩展了StatefulWidget{
最终图像;
最终尺寸图像尺寸;
最后一行;