extended_image 相關文章
圖片編輯這個功能很早之前就想把它給做了,畢竟是做的全家桶,少一個功能都覺得不舒服。最近自己一個人在家,週末瘋狂寫了2天程式碼,睡覺都在思考,
恰巧今天Google大會,據說現在掘金Flutter相關 約2萬粉絲,2600多篇相關文章。我晚上回家擼到半夜總算是完成,嗯,文章+1了實現
這部分我覺得不太好講,全是數學幾何相關的計算。當初開始寫的extended_image的時候,就留意了一下可能會擴充套件的功能實現的可能性,程式碼之間也做好了鋪墊。大家都問,功能能抽離出來嗎? 我說不能,從開始基礎就決定它將會擁有這些功能。簡單提一下,圖片的顯示區域不等於圖片的layout區域,它受BoxFix等引數的影響。而Flutter裡面的 Transform是對整個layout區域起作用的,明顯不符合我們的需求。所以從一開始我就放棄直接使用Transform對圖片進行處理,直接通過演算法在繪製圖片的時候進行縮放,平移,旋轉,翻轉等操作。
Rome is not built in one day,extended_image從今年2月份開始編寫的,到9月份最終成為各種常用實用功能的圖片全家桶。 如果對實現感興趣的小夥伴,可以先看看原始碼,如果有不清楚的,可以加群(QQ群:181398081)詢問。
使用
ExtendedImage.network(
imageTestUrl,
fit: BoxFit.contain,
mode: ExtendedImageMode.editor,
extendedImageEditorKey: editorKey,
initEditorConfigHandler: (state) {
return EditorConfig(
maxScale: 8.0,
cropRectPadding: EdgeInsets.all(20.0),
hitTestSize: 20.0,
cropAspectRatio: _aspectRatio.aspectRatio);
},
);
複製程式碼
ExtendedImage 相關引數設定
引數 | 描述 | 預設 |
---|---|---|
mode | 圖片模式,預設/手勢/編輯 (none,gestrue,editor) | none |
initGestureConfigHandler | 編輯器配置的回撥(圖片載入完成時).你可以根據圖片的資訊比如寬高,來初始化 | - |
extendedImageEditorKey | key of ExtendedImageEditorState 用於裁剪旋轉翻轉 | - |
EditorConfig 引數
引數 | 描述 | 預設 |
---|---|---|
maxScale | 最大的縮放倍數 | 5.0 |
cropRectPadding | 裁剪框跟圖片layout區域之間的距離。最好是保持一定距離,不然裁剪框邊界很難進行拖拽 | EdgeInsets.all(20.0) |
cornerSize | 裁剪框四角圖形的大小 | Size(30.0, 5.0) |
cornerColor | 裁剪框四角圖形的顏色 | primaryColor |
lineColor | 裁剪框線的顏色 | scaffoldBackgroundColor.withOpacity(0.7) |
lineHeight | 裁剪框線的高度 | 0.6 |
eidtorMaskColorHandler | 蒙層的顏色回撥,你可以根據是否手指按下來設定不同的蒙層顏色 | scaffoldBackgroundColor.withOpacity(pointerdown ? 0.4 : 0.8) |
hitTestSize | 裁剪框四角以及邊線能夠拖拽的區域的大小 | 20.0 |
animationDuration | 當裁剪框拖拽變化結束之後,自動適應到中間的動畫的時長 | Duration(milliseconds: 200) |
tickerDuration | 當裁剪框拖拽變化結束之後,多少時間才觸發自動適應到中間的動畫 | Duration(milliseconds: 400) |
cropAspectRatio | 裁剪框的寬高比 | null(無寬高比)) |
initCropRectType | 剪下框的初始化型別(根據圖片初始化區域或者圖片的layout區域) | imageRect |
裁剪框的寬高比
這是一個double型別,你可以自定義裁剪框的寬高比。 如果為null,那就沒有寬高比限制。 如果小於等於0,寬高比等於圖片的寬高比。 下面是一些定義好了的寬高比
class CropAspectRatios {
/// no aspect ratio for crop
static const double custom = null;
/// the same as aspect ratio of image
/// [cropAspectRatio] is not more than 0.0, it's original
static const double original = 0.0;
/// ratio of width and height is 1 : 1
static const double ratio1_1 = 1.0;
/// ratio of width and height is 3 : 4
static const double ratio3_4 = 3.0 / 4.0;
/// ratio of width and height is 4 : 3
static const double ratio4_3 = 4.0 / 3.0;
/// ratio of width and height is 9 : 16
static const double ratio9_16 = 9.0 / 16.0;
/// ratio of width and height is 16 : 9
static const double ratio16_9 = 16.0 / 9.0;
}
複製程式碼
旋轉,翻轉,重置
- 定義key,以方便操作ExtendedImageEditorState
final GlobalKey<ExtendedImageEditorState> editorKey =GlobalKey<ExtendedImageEditorState>();
- 順時針旋轉90°
editorKey.currentState.rotate(right: true);
- 逆時針旋轉90°
editorKey.currentState.rotate(right: false);
- 翻轉(映象)
editorKey.currentState.flip();
- 重置
editorKey.currentState.reset();
使用dart庫(穩定)
- 新增 Image 庫到 pubspec.yaml, 它是用來裁剪/旋轉/翻轉圖片資料的
dependencies:
image: any
複製程式碼
- 從ExtendedImageEditorState中獲取裁剪區域以及圖片資料
///crop rect base on raw image
final Rect cropRect = state.getCropRect();
var data = state.rawImageData;
複製程式碼
- 將flutter的圖片資料轉換為image庫的資料
/// it costs much time and blocks ui.
//Image src = decodeImage(data);
/// it will not block ui with using isolate.
//Image src = await compute(decodeImage, data);
//Image src = await isolateDecodeImage(data);
final lb = await loadBalancer;
Image src = await lb.run<Image, List<int>>(decodeImage, data);
複製程式碼
- 翻轉,旋轉,裁剪資料
//相機拍照的圖片帶有旋轉,處理之前需要去掉
src = bakeOrientation(src);
if (editAction.needCrop)
src = copyCrop(src, cropRect.left.toInt(), cropRect.top.toInt(),
cropRect.width.toInt(), cropRect.height.toInt());
if (editAction.needFlip) {
Flip mode;
if (editAction.flipY && editAction.flipX) {
mode = Flip.both;
} else if (editAction.flipY) {
mode = Flip.horizontal;
} else if (editAction.flipX) {
mode = Flip.vertical;
}
src = flip(src, mode);
}
if (editAction.hasRotateAngle) src = copyRotate(src, editAction.rotateAngle);
複製程式碼
- 將資料轉為為圖片的後設資料
獲取到的將是圖片的後設資料,你可以使用它來儲存或者其他的一些用途
/// you can encode your image
///
/// it costs much time and blocks ui.
//var fileData = encodeJpg(src);
/// it will not block ui with using isolate.
//var fileData = await compute(encodeJpg, src);
//var fileData = await isolateEncodeImage(src);
var fileData = await lb.run<List<int>, Image>(encodeJpg, src);
複製程式碼
使用原生庫(快速)
- 新增 ImageEditor 庫到 pubspec.yaml, 它是用來裁剪/旋轉/翻轉圖片資料的。
dependencies:
image_editor: any
複製程式碼
- 從ExtendedImageEditorState中獲取裁剪區域以及圖片資料
///crop rect base on raw image
final Rect cropRect = state.getCropRect();
final img = state.rawImageData;
複製程式碼
- 準備裁剪選項
final rotateAngle = action.rotateAngle.toInt();
final flipHorizontal = action.flipY;
final flipVertical = action.flipX;
ImageEditorOption option = ImageEditorOption();
if (action.needCrop) option.addOption(ClipOption.fromRect(cropRect));
if (action.needFlip)
option.addOption(
FlipOption(horizontal: flipHorizontal, vertical: flipVertical));
if (action.hasRotateAngle) option.addOption(RotateOption(rotateAngle));
複製程式碼
- 使用editImage方法進行裁剪
獲取到的將是圖片的後設資料,你可以使用它來儲存或者其他的一些用途
final result = await ImageEditor.editImage(
image: img,
imageEditorOption: option,
);
複製程式碼
結語
時間過得真快,搞弄flutter也快要1年了,認識不少朋友,大家在一起互相學習,促進的感覺真好。歡迎加入Flutter Candies,一起生產可愛的Flutter小糖果(QQ群:181398081)
最最後放上Flutter Candies全家桶,真香。