效果圖
1597904550873.gif
主要實現功能
- 選取系統相冊圖片
- 切割圖片
- 打亂圖片
- 移動圖片
選取系統相冊
用的是flutter的image_picker的圖片選擇器.自己集成一下就可以。不再多說
image_picker: 0.6.7+4
切割圖片
新建一個類繼承CustomPainter, 去進行圖片操作,
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
/// 圖片裁剪
class ImageClipper extends CustomPainter {
final ui.Image image;
final double left;
final double top;
final double right;
final double bottom;
final int currentIndex;
ImageClipper(this.image, this.left, this.top, this.right, this.bottom,
this.currentIndex);
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
canvas.drawImageRect(
image,
Rect.fromLTRB(image.width * left, image.height * top,
image.width * right, image.height * bottom),
Rect.fromLTWH(0, 0, size.width, size.height),
paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
然后顯示出來
Container(
color: Colors.green,
child: GestureDetector(
child: CustomPaint(
painter: clipper,
size: Size(80, 80),
),
onTap: () {
tapList.add(clipper.currentIndex);
showAnimation(clipper.currentIndex);
},
),
);
上面代碼添加了,點擊方法。用來進行模塊移動, 其中clipper就是切割好的圖片,返回來的對象,
比較重要的一點是選擇的需要對選擇好了的本地圖片處理一下
Future<ui.Image> _loadImge() async {
ImageStream imageStream = FileImage(imgPath).resolve(ImageConfiguration());
Completer<ui.Image> completer = Completer<ui.Image>();
void imageListener(ImageInfo info, bool synchronousCall) {
ui.Image image = info.image;
completer.complete(image);
imageStream.removeListener(ImageStreamListener(imageListener));
}
imageStream.addListener(ImageStreamListener(imageListener));
return completer.future;
}
clip(left, top, right, bottom, currentIndex) async {
ui.Image uiImage;
_loadImge().then((image) {
uiImage = image;
}).whenComplete(() {
clipperList
.add(ImageClipper(uiImage, left, top, right, bottom, currentIndex));
setState(() {});
});
}
打亂圖片
這個可以用shuffle()函數去處理,但是打亂之后的數組,不一定能夠通過移動完成拼圖
所以采用了一個相當于比較穩的方法,這里提供一下思路。循環次數去進行點擊移動操作,記錄點擊的圖片模塊,進行移動,這樣自動還原的時候把記錄的數組進行倒敘之后,在進行移動就可以還原了。。完美
感興趣的同學可以用A*搜索算法。
移動圖片
更換數組位置即可。這個比較簡單了
int emptyIndex = 0;
int currentIndex = 0;
ImageClipper emptyClipper;
for (int i = 0; i < clipperList.length; i++) {
if (clipperList[i].currentIndex == 8) {
emptyIndex = i;
emptyClipper = clipperList[i];
}
if (clipperList[i].currentIndex == current) {
currentIndex = i;
}
}
// 判斷是否可以移動
if (isCanMove(emptyIndex, currentIndex)) {
// 不移動
clipperList[emptyIndex] = clipperList[currentIndex];
clipperList[currentIndex] = emptyClipper;
if (mounted) {
setState(() {});
// 判斷是否完成
isSuccess();
}
}
針對9宮格來說。沒有寫通用的。??
bool isCanMove(empty, current) {
bool isCanMove = false;
switch (empty) {
case 0:
{
if (current == 1 || current == 3) isCanMove = true;
break;
}
case 1:
{
if (current == 0 || current == 2 || current == 4) isCanMove = true;
break;
}
case 2:
{
if (current == 1 || current == 5) isCanMove = true;
break;
}
case 3:
{
if (current == 0 || current == 4 || current == 6) isCanMove = true;
break;
}
case 4:
{
if (current == 1 || current == 3 || current == 5 || current == 7)
isCanMove = true;
break;
}
case 5:
{
if (current == 2 || current == 4 || current == 8) isCanMove = true;
break;
}
case 6:
{
if (current == 3 || current == 7) isCanMove = true;
break;
}
case 7:
{
if (current == 4 || current == 6 || current == 8) isCanMove = true;
break;
}
case 8:
{
if (current == 5 || current == 7) isCanMove = true;
break;
}
default:
}
return isCanMove;
}