Flutter自定义图像拼贴
Flutter custom image collage
我希望能够构建 拼贴画 为此,我尝试使用 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;
}
}
结果:
如您所见,这并不是真正想要的结果,因为图像没有填充形状。我没有找到任何东西。有可能吗?如果没有,用自定义形状构建拼贴画的最佳方法是什么?
如果您需要更多信息,请告诉我!
使用 ClipPath
小部件代替 CustomPaint
。
使用与您相同的路径 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;
}
在图像上缩放和平移的解决方案
使用GestureDetector
检测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;
}
我希望能够构建 拼贴画 为此,我尝试使用 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;
}
}
结果:
如您所见,这并不是真正想要的结果,因为图像没有填充形状。我没有找到任何东西。有可能吗?如果没有,用自定义形状构建拼贴画的最佳方法是什么?
如果您需要更多信息,请告诉我!
使用 ClipPath
小部件代替 CustomPaint
。
使用与您相同的路径 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;
}
在图像上缩放和平移的解决方案
使用GestureDetector
检测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;
}