From f39f4955034dd0ca37674214ac7d336035c5796d Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 7 Jun 2025 19:00:06 +0800 Subject: [PATCH 1/6] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BootstrapBlazor.ImageCropper/ImageCropperResult.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/BootstrapBlazor.ImageCropper/ImageCropperResult.cs b/src/components/BootstrapBlazor.ImageCropper/ImageCropperResult.cs index a1000a54..9317c551 100644 --- a/src/components/BootstrapBlazor.ImageCropper/ImageCropperResult.cs +++ b/src/components/BootstrapBlazor.ImageCropper/ImageCropperResult.cs @@ -9,9 +9,6 @@ namespace BootstrapBlazor.Components; /// /// 裁切结果实体类 /// -/// -/// 构造函数 -/// /// public class ImageCropperResult(string data) { From 39d9997930aa582da7c01b8e08b23d587f7e3e16 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 7 Jun 2025 19:00:36 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20Invoke=20?= =?UTF-8?q?=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor index 98303404..c6ddc059 100644 --- a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor +++ b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor @@ -1,6 +1,6 @@ @namespace BootstrapBlazor.Components @inherits BootstrapModuleComponentBase -@attribute [JSModuleAutoLoader("./_content/BootstrapBlazor.ImageCropper/ImageCropper.razor.js")] +@attribute [JSModuleAutoLoader("./_content/BootstrapBlazor.ImageCropper/ImageCropper.razor.js", JSObjectReference = true)]
From 1efe80ff2d46551c975c3911d80241d9142578d6 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 7 Jun 2025 19:01:14 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20OnCropEndAsync?= =?UTF-8?q?=20=E5=9B=9E=E8=B0=83=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ImageCropper.razor.cs | 26 +++- .../ImageCropper.razor.js | 116 +++++++++++------- 2 files changed, 95 insertions(+), 47 deletions(-) diff --git a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs index 338d0add..4ef0a7a4 100644 --- a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs +++ b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs @@ -3,6 +3,7 @@ // Website: https://www.blazor.zone or https://argozhang.github.io/ using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; namespace BootstrapBlazor.Components; @@ -29,6 +30,12 @@ public partial class ImageCropper [Parameter] public Func? OnCropAsync { get; set; } + /// + /// 获得/设置 剪裁调整结束回调方法 + /// + [Parameter] + public Func? OnCropEndAsync { get; set; } + /// /// 获取/设置 裁剪选项 /// @@ -81,7 +88,11 @@ protected override async Task OnAfterRenderAsync(bool firstRender) /// /// /// - protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Options ?? new()); + protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, new + { + Options = Options ?? new(), + TriggerOnCropEndAsync = OnCropEndAsync != null ? nameof(TriggerOnCropEndAsync) : null, + }); /// /// 剪裁方法 自动触发 回调方法 @@ -153,4 +164,17 @@ public Task Disable() /// 旋转角度 /// public async Task Rotate(int angle) => await InvokeVoidAsync("rotate", Id, angle); + + /// + /// + /// + /// + [JSInvokable] + public async Task TriggerOnCropEndAsync() + { + if(OnCropEndAsync != null) + { + await Task.CompletedTask; + } + } } diff --git a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.js b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.js index 204a9412..fee2efbf 100644 --- a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.js +++ b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.js @@ -2,7 +2,7 @@ import Data from '../BootstrapBlazor/modules/data.js' import { addLink } from '../BootstrapBlazor/modules/utility.js' -export async function init(id, options) { +export async function init(id, invoke, options) { await addLink("./_content/BootstrapBlazor.ImageCropper/cropper.bundle.css"); const el = document.getElementById(id); @@ -11,9 +11,9 @@ export async function init(id, options) { } const image = el.querySelector(".bb-cropper-image"); - const cropper = new Cropper(image, getOptions(options)); + const cropper = new Cropper(image, getOptions(options.options)); - Data.set(id, cropper); + Data.set(id, { el, invoke, options, cropper }); } const getOptions = op => { @@ -27,86 +27,110 @@ const getOptions = op => { } export function dispose(id) { - const cropper = Data.get(id); + const ic = Data.get(id); Data.remove(id); - if (cropper != null) { - cropper.destroy(); + if (ic != null) { + const { cropper } = ic; + if (cropper) { + cropper.destroy(); + } } } export function crop(id) { let ret = null; - const cropper = Data.get(id); - if (cropper != null) { - const { isRound } = cropper.options; - cropper.crop(); - let resultData = cropper.getCroppedCanvas(); - if (isRound) { - resultData = getRoundCanvas(resultData); + const ic = Data.get(id); + if (ic != null) { + const { cropper, options } = ic; + if (cropper !== null) { + cropper.crop(); + let resultData = cropper.getCroppedCanvas(); + + const { isRound } = options.options; + if (isRound) { + resultData = getRoundCanvas(resultData); + } + ret = resultData.toDataURL(); + resultData = null; } - ret = resultData.toDataURL(); - resultData = null; } return ret; } export function replace(id, url) { - const cropper = Data.get(id); - if (cropper != null) { - cropper.replace(url); + const ic = Data.get(id); + if (ic != null) { + const { cropper } = ic; + if (cropper) { + cropper.replace(url); + } } } export function reset(id) { - const cropper = Data.get(id); - if (cropper != null) { - cropper.reset(); + const ic = Data.get(id); + if (ic != null) { + const { cropper } = ic; + if (cropper) { + cropper.reset(); + } } } export function setDragMode(id, mode) { - const cropper = Data.get(id); - if (cropper != null) { - cropper.setDragMode(mode); + const ic = Data.get(id); + if (ic != null) { + const { cropper } = ic; + if (cropper) { + cropper.setDragMode(mode); + } } } export function rotate(id, angle) { - const cropper = Data.get(id); - if (cropper != null) { - cropper.rotate(angle); + const ic = Data.get(id); + if (ic != null) { + const { cropper } = ic; + if (cropper) { + cropper.rotate(angle); + } } } export function clear(id) { - const cropper = Data.get(id); - if (cropper != null) { - cropper.clear(); + const ic = Data.get(id); + if (ic != null) { + const { cropper } = ic; + if (cropper) { + cropper.clear(); + } } } export async function enable(id) { - const cropper = Data.get(id); - if (cropper != null) { - cropper.enable(); - } - - const el = document.getElementById(id); - if (el) { - el.classList.remove("disabled"); + const ic = Data.get(id); + if (ic != null) { + const { el, cropper } = ic; + if (cropper) { + cropper.enable(); + } + if (el) { + el.classList.remove("disabled"); + } } } export async function disable(id) { - const cropper = Data.get(id); - if (cropper != null) { - cropper.disable(); - } - - const el = document.getElementById(id); - if (el) { - el.classList.add("disabled"); + const ic = Data.get(id); + if (ic != null) { + const { el, cropper } = ic; + if (cropper) { + cropper.disable(); + } + if (el) { + el.classList.add("disabled"); + } } } From a4a8e710e6c5ef8d9153aa6a2eb911a970a695f1 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 7 Jun 2025 19:42:20 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20ImageCropperDa?= =?UTF-8?q?ta=20=E7=BB=93=E6=9E=84=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ImageCropper.razor.cs | 8 ++-- .../ImageCropper.razor.js | 13 +++++- .../ImageCropperData.cs | 46 +++++++++++++++++++ 3 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 src/components/BootstrapBlazor.ImageCropper/ImageCropperData.cs diff --git a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs index 4ef0a7a4..cd0517d4 100644 --- a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs +++ b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs @@ -34,7 +34,7 @@ public partial class ImageCropper /// 获得/设置 剪裁调整结束回调方法 /// [Parameter] - public Func? OnCropEndAsync { get; set; } + public Func? OnCropEndAsync { get; set; } /// /// 获取/设置 裁剪选项 @@ -170,11 +170,11 @@ public Task Disable() /// /// [JSInvokable] - public async Task TriggerOnCropEndAsync() + public async Task TriggerOnCropEndAsync(ImageCropperData data) { - if(OnCropEndAsync != null) + if (OnCropEndAsync != null) { - await Task.CompletedTask; + await OnCropEndAsync(data); } } } diff --git a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.js b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.js index fee2efbf..98e8c6c8 100644 --- a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.js +++ b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.js @@ -11,7 +11,18 @@ export async function init(id, invoke, options) { } const image = el.querySelector(".bb-cropper-image"); - const cropper = new Cropper(image, getOptions(options.options)); + const { options: op, triggerOnCropEndAsync } = options; + if (triggerOnCropEndAsync) { + let cropData = null; + op.cropend = () => { + invoke.invokeMethodAsync(triggerOnCropEndAsync, cropData); + cropData = null; + } + op.crop = e => { + cropData = e.detail; + } + } + const cropper = new Cropper(image, getOptions(op)); Data.set(id, { el, invoke, options, cropper }); } diff --git a/src/components/BootstrapBlazor.ImageCropper/ImageCropperData.cs b/src/components/BootstrapBlazor.ImageCropper/ImageCropperData.cs new file mode 100644 index 00000000..e1d53df4 --- /dev/null +++ b/src/components/BootstrapBlazor.ImageCropper/ImageCropperData.cs @@ -0,0 +1,46 @@ +// Copyright (c) Argo Zhang (argo@163.com). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +namespace BootstrapBlazor.Components; + +/// +/// 裁切数据实体类 +/// +public struct ImageCropperData +{ + /// + /// 获得/设置 裁剪框高度值 + /// + public float Height { get; set; } + + /// + /// 获得/设置 裁剪框宽度值 + /// + public float Width { get; set; } + + /// + /// 获得/设置 裁剪框 X 值 + /// + public float X { get; set; } + + /// + /// 获得/设置 裁剪框 Y 值 + /// + public float Y { get; set; } + + /// + /// 获得/设置 裁剪框旋转角度值 + /// + public float Rotate { get; set; } + + /// + /// 获得/设置 裁剪框 X 轴缩放值 + /// + public float ScaleX { get; set; } + + /// + /// 获得/设置 裁剪框 Y 轴缩放值 + /// + public float ScaleY { get; set; } +} From 410d27e0221ea591fe337973140d7ecb98ab0fb2 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 7 Jun 2025 19:52:39 +0800 Subject: [PATCH 5/6] chore: bump version 9.0.3 --- .../BootstrapBlazor.ImageCropper.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/BootstrapBlazor.ImageCropper/BootstrapBlazor.ImageCropper.csproj b/src/components/BootstrapBlazor.ImageCropper/BootstrapBlazor.ImageCropper.csproj index 73a8aa55..fe86e7b5 100644 --- a/src/components/BootstrapBlazor.ImageCropper/BootstrapBlazor.ImageCropper.csproj +++ b/src/components/BootstrapBlazor.ImageCropper/BootstrapBlazor.ImageCropper.csproj @@ -1,7 +1,7 @@ - 9.0.2 + 9.0.3 From f22f2195c78fb2c4527c11b34a0a78206006ade9 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sat, 7 Jun 2025 19:58:37 +0800 Subject: [PATCH 6/6] =?UTF-8?q?refactor:=20=E6=9B=B4=E6=96=B0=E5=9B=9E?= =?UTF-8?q?=E8=B0=83=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ImageCropper.razor.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs index cd0517d4..27954249 100644 --- a/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs +++ b/src/components/BootstrapBlazor.ImageCropper/ImageCropper.razor.cs @@ -31,10 +31,10 @@ public partial class ImageCropper public Func? OnCropAsync { get; set; } /// - /// 获得/设置 剪裁调整结束回调方法 + /// 获得/设置 剪裁框调整大小位置回调方法 /// [Parameter] - public Func? OnCropEndAsync { get; set; } + public Func? OnCropChangedAsync { get; set; } /// /// 获取/设置 裁剪选项 @@ -91,11 +91,11 @@ protected override async Task OnAfterRenderAsync(bool firstRender) protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, new { Options = Options ?? new(), - TriggerOnCropEndAsync = OnCropEndAsync != null ? nameof(TriggerOnCropEndAsync) : null, + TriggerOnCropEndAsync = OnCropChangedAsync != null ? nameof(TriggerOnCropChangedAsync) : null, }); /// - /// 剪裁方法 自动触发 回调方法 + /// 剪裁方法 触发 回调方法 /// public async Task Crop() { @@ -170,11 +170,11 @@ public Task Disable() /// /// [JSInvokable] - public async Task TriggerOnCropEndAsync(ImageCropperData data) + public async Task TriggerOnCropChangedAsync(ImageCropperData data) { - if (OnCropEndAsync != null) + if (OnCropChangedAsync != null) { - await OnCropEndAsync(data); + await OnCropChangedAsync(data); } } }