image - Flutter 自定义图片拼贴
问题描述
我希望能够构建拼贴画,为此我尝试使用它CustomPaint
来绘制形状,然后用image
. 这是我尝试过的:
Container(
height: 300,
width: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
border: Border.all(color: Colors.white, width: 5),
),
child: CustomPaint(
painter: DrawTriangleShape(color: Colors.blue),
child: Image.asset('assets/images/exampleImage.jpg'),
),
),
我的DrawTriangleShape
:
class DrawTriangleShape extends CustomPainter {
Paint painter;
DrawTriangleShape({color: Colors}) {
painter = Paint()
..color = color
..style = PaintingStyle.fill;
}
@override
void paint(Canvas canvas, Size size) {
var path = Path();
path.moveTo(size.width / 1, 0);
path.lineTo(0, size.height);
path.lineTo(size.height, size.width);
path.close();
canvas.drawPath(path, painter);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
结果:
如您所见,这并不是真正想要的结果,因为图像没有填充形状。我没有找到任何东西。甚至可能吗?如果没有,用自定义形状构建拼贴画的最佳方法是什么?
如果您需要更多信息,请告诉我!
解决方案
代替 a CustomPaint
,使用ClipPath
小部件。
使用与您相同的路径CustomPaint
:
完整的源代码
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ClipPath(
clipper: CustomClipperImage(),
child: Image.asset('images/abstract.jpg'),
),
),
);
}
}
class CustomClipperImage extends CustomClipper<Path> {
@override
getClip(Size size) {
return Path()
..moveTo(size.width / 1, 0)
..lineTo(0, size.height)
..lineTo(size.height, size.width)
..close();
}
@override
bool shouldReclip(CustomClipper oldClipper) {
return false;
}
}
带有白色边框和缩放图像的附加示例。
完整的源代码
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width * .8;
final height = width * .7;
return Scaffold(
body: Container(
color: Colors.black54,
child: Center(
child: Stack(
children: [
CustomPaint(
painter: MyPainter(),
child: Container(width: width, height: height),
),
ClipPath(
clipper: CustomClipperImage(),
child: Transform.scale(
scale: 3,
child: Image.asset('images/abstract.jpg',
width: width, height: height),
),
),
],
),
),
),
);
}
}
class CustomClipperImage extends CustomClipper<Path> {
@override
getClip(Size size) {
return Path()
..moveTo(size.width, 0)
..lineTo(0, size.height)
..lineTo(size.height, size.height)
..close();
}
@override
bool shouldReclip(CustomClipper oldClipper) {
return false;
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final path = Path()
..moveTo(size.width, 0)
..lineTo(0, size.height)
..lineTo(size.height, size.height)
..close();
final paint = Paint()
..color = Colors.white
..strokeWidth = 8.0
..style = PaintingStyle.stroke;
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
对图像进行缩放和平移的解决方案
使用 aGestureDetector
来检测 和 的scale
变化localFocalPoint
。然后使用我们Matrix4
的:Transform
Image.asset
完整源代码:
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends HookWidget {
@override
Widget build(BuildContext context) {
final _width = MediaQuery.of(context).size.width * .8;
final _height = _width * .6;
final _zoom = useState<double>(1.0);
final _previousZoom = useState<double>(1.0);
final _offset = useState<Offset>(Offset.zero);
final _previousOffset = useState<Offset>(Offset.zero);
final _startingFocalPoint = useState<Offset>(Offset.zero);
return Scaffold(
body: Container(
color: Colors.black54,
child: Center(
child: GestureDetector(
onScaleStart: (details) {
_startingFocalPoint.value = details.localFocalPoint;
_previousOffset.value = _offset.value;
_previousZoom.value = _zoom.value;
},
onScaleUpdate: (details) {
_zoom.value = _previousZoom.value * details.scale;
final Offset normalizedOffset =
(_startingFocalPoint.value - _previousOffset.value) /
_previousZoom.value;
_offset.value =
details.localFocalPoint - normalizedOffset * _zoom.value;
},
child: Stack(
children: [
CustomPaint(
painter: MyPainter(),
child: Container(width: _width, height: _height),
),
ClipPath(
clipper: CustomClipperImage(),
child: Transform(
transform: Matrix4.identity()
..translate(_offset.value.dx, _offset.value.dy)
..scale(_zoom.value),
// ..rotateZ(_rotation.value),
child: Image.asset('images/milkyway.jpg',
width: _width, height: _height),
),
),
],
),
),
),
),
);
}
}
class CustomClipperImage extends CustomClipper<Path> {
@override
getClip(Size size) {
return Path()
..moveTo(size.width, 0)
..lineTo(0, size.height)
..lineTo(size.height, size.height)
..close();
}
@override
bool shouldReclip(CustomClipper oldClipper) {
return false;
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final path = Path()
..moveTo(size.width, 0)
..lineTo(0, size.height)
..lineTo(size.height, size.height)
..close();
final paint = Paint()
..color = Colors.white
..strokeWidth = 8.0
..style = PaintingStyle.stroke;
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
推荐阅读
- c++ - 2 天的差异:为什么选择 convert(datetime, 43279) = '2018-06-30' 和 DateTime.FromOADate(43279) = '2018-06-28'?
- java - 在类中使用全局变量
- php - 检查是否设置了数组值
- azure-iot-hub - Azure IoT Hub Java SDK,通过单个 AMQP 连接连接多路复用的 X.509 设备
- java - 方法本地内部类程序
- loops - 使用 Corona SDK 在循环中一次仅选择一个矩形
- android - 选择特定的字符串数组
- python - 在 python 中处理 Slack 按钮操作 POST 请求数据
- xcode - 无法运行从 github 下载的应用程序
- typo3 - TYPO3 sys_language_mode = strict 仍然让我获得“默认”语言的记录