「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」
功能查看
老规矩先看看该功能是什么样的,当拖动中间的放大区域时, 会选取中心区域的色值进行显示, 所以该功能也是分为两个部分,一部分是放大功能的实现, 另一个就是中心点色值的获取,好的功能看完了,接下来我们就开始今天的源码查看
源码查看
今天的代码还是在flutter_ume_kit_ui包中,其中有个color_sucker文件夹,关于上方的toolbar和移动手势相关代码就不做过多的解释了, 跟对其标尺中的基本都是一致的,感兴趣的可以去看下对其标尺中是如何实现的
选中区域放大
在color_sucker.dart的第209行我们看到了一个新的组件BackdropFilter那么组件是做什么的,主要有两个功能,一个是做高斯模糊效果,另一个是做矩阵变换,该功能就是通过矩阵变换来实现的
BackdropFilter(
filter: ui.ImageFilter.matrix(_matrix.storage,
filterQuality: FilterQuality.none),
)
可是该功能也没有放大功能阿,那放大是怎么实现的,我们再看下ImageFilter.matrix方法
/// Creates an image filter that applies a matrix transformation.
///
/// For example, applying a positive scale matrix (see [Matrix4.diagonal3])
/// when used with [BackdropFilter] would magnify the background image.
factory ImageFilter.matrix(Float64List matrix4,
{ FilterQuality filterQuality = FilterQuality.low }) {
}
注释的最后一行我发现写了与BackdropFilter会有背景图放大的效果,这不就是我们要的效果么,再来看看_matrix是哪来的
在onPanUpdate手势中,有个Matrix4,通过x,y转换而来
final Matrix4 newMatrix = Matrix4.identity()
..translate(newX, newY)
..scale(_scale, _scale)
..translate(-newX, -newY);
_matrix = newMatrix;
好了放大功能已经实现了,我们再看看色值是如何得来的
色值获取
还是从手势的方法开始看,在上面矩阵转换的代码下有一行色值获取的方法_searchPixel,我们再往里看,
void _calculatePixel(Offset globalPosition) {
if (_snapshot == null) return;
double px = globalPosition.dx;
double py = globalPosition.dy;
int pixel32 = _snapshot!.getPixelSafe(px.toInt(), py.toInt());
int hex = _abgrToArgb(pixel32);
_currentColor = Color(hex);
}
获取到32位色值后转换成hex从而得到color,再看看是怎么通过坐标获取到色值的,继续看_snapshot!.getPixelSafe,方法注释写的很清楚,该方法传入x,y值以后就可以得到Uint32的色值
/// Get the pixel from the given [x], [y] coordinate. Color is encoded in a
/// Uint32 as #AABBGGRR. If the pixel coordinates are out of bounds, 0 is
/// returned.
int getPixelSafe(int x, int y) => boundsSafe(x, y) ? data[y * width + x] : 0;
所以问题到了_snapshot是如何得到的? 在手势开始的时候会判断是否有屏幕的截图,如果没有屏幕的截图,则会截取一张屏幕的截图
Future<void> _captureScreen() async {
try {
RenderRepaintBoundary boundary =
rootKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage();
ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
if (byteData == null) {
return;
}
Uint8List pngBytes = byteData.buffer.asUint8List();
_snapshot = img.decodeImage(pngBytes);
_excuting = false;
image.dispose();
} catch (e) {
debugPrint(e.toString());
}
}
这样就能通过截图得到色值了
好了今天的源码查看就到这了, 作为Flutter届的一个小学生,希望大家多多指教,有问题的地方一起讨论