Bootstrap Blazor自定义图片预览组件

        Bootstrap Blazor的官方虽然有提供图片预览组件ImagePreviewer,但是,它是置于窗口顶层的,而且是全屏显示,如果业务中有在预览组件中添加其它功能的需求,它是不支持扩展的。

        为此,我参考官方的源码,自己写了一个自定义图片预览组件,文件的源码在下面,可自行查阅和扩展。支持左右切换、缩放(含鼠标滚轮缩放)和旋转图片,实现的效果如下:

ImagePreviewCustom.razor文件内容如下:

<div class="fyy-previewer">
    <div class="fyy-viewer-canvas" id="fyy-viewer-canvas-id">
        <img src="@GetShowImageUrl()" draggable="false" class="fyy-viewer-img" id="fyy-viewer-img-id" style="transform: scale(@ScaleValue) rotate(@(RotateValue)deg); margin: 0; object-fit:contain;" @onmousewheel="(e) => OnMouseWheelToScaleImage(e.DeltaY)">
    </div>
    
    <div class="fyy-viewer-btn fyy-viewer-actions">
        <div class="fyy-viewer-actions-inner">
            @if (ShowButtons)
            {
                <i class="icon-circle fa-solid fa-angle-left" @onclick="() => OnClickToPrevImage()"></i>
                <i class="icon-circle fa-solid fa-angle-right" @onclick="() => OnClickToNextImage()"></i>
            }
            <i class="icon-circle minus-icon fa-solid fa-magnifying-glass-minus" @onclick="() => OnClickToMinusImage()"></i>
            <i class="icon-circle plus-icon fa-solid fa-magnifying-glass-plus" @onclick="() => OnClickToPlusImage()"></i>
            <i class="icon-circle rotate-left fa-solid fa-rotate-left" @onclick="() => OnClickToRotateLeft()"></i>
            <i class="icon-circle rotate-right fa-solid fa-rotate-right" @onclick="() => OnClickToRotateRight()"></i>
        </div>
    </div>
</div>

ImagePreviewCustom.razor.cs内容如下:

using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics.CodeAnalysis;

namespace Fyy.Components
{
    /// <summary>
    /// 自定义图片预览
    /// </summary>
    public partial class ImagePreviewCustom
    {
        
        [Inject]
        [NotNull]
        private MessageBox? _MsgBox { get; set; }

        /// <summary>
        /// 获得/设置 预览大图链接集合 默认 null
        /// </summary>
        [Parameter]
        [NotNull]
#if NET6_0_OR_GREATER
        [EditorRequired]
#endif
        public List<string>? PreviewList { get; set; }

        /// <summary>
        /// 获得/设置 预览大图当前链接集合点开的索引 默认为 0
        /// </summary>
        [Parameter]
        [NotNull]
        public int PreviewIndex { get; set; } = 0;

        /// <summary>
        /// 是否显示左右切换按钮
        /// </summary>
        private bool ShowButtons => PreviewList.Count > 1;

        /// <summary>
        /// 当前暂时的图片
        /// </summary>
        /// <returns></returns>
        private string? GetShowImageUrl() => PreviewList[PreviewIndex];

        /// <summary>
        /// 缩放倍数
        /// </summary>
        private double ScaleValue { get; set; } = 1;

        /// <summary>
        /// 旋转角度
        /// </summary>
        private long RotateValue { get; set; } = 0;

        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            try
            {
                if (firstRender)
                {
                    OnLoadData();
                }

                await base.OnAfterRenderAsync(firstRender);
            }
            catch (Exception ex)
            {
                _MsgBox.Show(ex.Message, AlertTypes.Error);
            }
        }

        private void OnLoadData()
        {
            if (PreviewIndex < 0 || PreviewIndex >= PreviewList.Count)
            {
                throw new ArgumentOutOfRangeException();
            }
        }

        /// <summary>
        /// 切换到前一张图片
        /// </summary>
        /// <returns></returns>
        private Task OnClickToPrevImage()
        {
            try
            {
                if (PreviewIndex == 0)
                {
                    PreviewIndex = PreviewList.Count - 1;
                }
                else
                {
                    PreviewIndex--;
                }

                StateHasChanged();
            }
            catch (Exception ex)
            {
                _MsgBox.Show(ex.Message, AlertTypes.Error);
            }

            return Task.CompletedTask;
        }

        /// <summary>
        /// 切换到后一张图片
        /// </summary>
        /// <returns></returns>
        private Task OnClickToNextImage()
        {
            try
            {
                if (PreviewIndex == PreviewList.Count - 1)
                {
                    PreviewIndex = 0;
                }
                else
                {
                    PreviewIndex++;
                }

                StateHasChanged();
            }
            catch (Exception ex)
            {
                _MsgBox.Show(ex.Message, AlertTypes.Error);
            }

            return Task.CompletedTask;
        }

        /// <summary>
        /// 缩小图片
        /// </summary>
        /// <returns></returns>
        private Task OnClickToMinusImage()
        {
            try
            {
                if (ScaleValue <= 0)
                {
                    ScaleValue = 1;
                }
                else
                {
                    ScaleValue -= 0.01;
                }

                StateHasChanged();
            }
            catch (Exception ex)
            {
                _MsgBox.Show(ex.Message, AlertTypes.Error);
            }

            return Task.CompletedTask;
        }

        /// <summary>
        /// 放大图片
        /// </summary>
        /// <returns></returns>
        private async Task OnClickToPlusImage()
        {
            try
            {
                if (ScaleValue <= 0)
                {
                    ScaleValue = 1;
                }
                else
                {
                    ScaleValue += 0.01;
                }

                StateHasChanged();
            }
            catch (Exception ex)
            {
                _MsgBox.Show(ex.Message, AlertTypes.Error);
            }
        }

        /// <summary>
        /// 逆时针旋转图片
        /// </summary>
        /// <returns></returns>
        private Task OnClickToRotateLeft()
        {
            try
            {
                RotateValue -= 90;

                StateHasChanged();
            }
            catch (Exception ex)
            {
                _MsgBox.Show(ex.Message, AlertTypes.Error);
            }

            return Task.CompletedTask;
        }

        /// <summary>
        /// 逆时针旋转图片
        /// </summary>
        /// <returns></returns>
        private Task OnClickToRotateRight()
        {
            try
            {
                RotateValue += 90;

                StateHasChanged();
            }
            catch (Exception ex)
            {
                _MsgBox.Show(ex.Message, AlertTypes.Error);
            }

            return Task.CompletedTask;
        }

        private async Task OnMouseWheelToScaleImage(double delta)
        {
            try
            {
                if (delta > 0)
                {
                    if (ScaleValue <= 0)
                    {
                        ScaleValue = 1;
                    }
                    else
                    {
                        ScaleValue += 0.01;
                    }
                }
                else
                {
                    if (ScaleValue <= 0)
                    {
                        ScaleValue = 1;
                    }
                    else
                    {
                        ScaleValue -= 0.01;
                    }
                }

                StateHasChanged();
            }
            catch (Exception ex)
            {
                _MsgBox.Show(ex.Message, AlertTypes.Error);
            }
        }
    }
}

ImagePreviewCustom.razor.css文件内容如下:

.fyy-previewer {
    height: 50vh;
}

.fyy-viewer-canvas {
    width: 100%;
    height: calc(100% - 38px);
    overflow: auto;
    border: 1px solid #ccc;
    position: relative;
    display: flex;
    align-items: center;
}

.fyy-viewer-img {
    display: block;
    transition: transform 0.3s ease;
}

.fyy-viewer-btn {
    position: absolute;
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
}

.fyy-viewer-actions {
    left: 50%;
    bottom: 2px;
    transform: translateX(-50%);
    width: 400px;
    height: 36px;
    cursor: default;
}

.fyy-viewer-actions-inner {
    font-size: 0rem;
}

.icon-circle {
    font-size: 1.5rem;
    width: 36px;
    height: 36px;
    margin-left: 5px;
    margin-right: 5px;
    border-radius: 50%;
    border: 1px solid darkgray;
    line-height: 36px;
    align-content: center;
    text-align: center;
    background-color: darkgray;
    opacity: .8;
}

    .icon-circle:hover {
        opacity: 1;
    }

弹出预览窗口的方式如下(这个是我在项目中用的,可作为参考):

[Inject]
[NotNull]
private DialogService _DialogService { get; set; }


private Task OnImageClick(List<string> previewList, int previewIndex)
{
    try
    {
        if (previewIndex >= previewList.Count)
        {
            previewIndex = 0;
        }

        _DialogService.Show(new DialogOption()
        {
            Title = "图片预览",
            ShowCloseButton = false,
            Size = BootstrapBlazor.Components.Size.ExtraExtraLarge,
            BodyTemplate = BootstrapDynamicComponent.CreateComponent<ImagePreviewCustom>(new Dictionary<string, object?>
            {
                [nameof(ImagePreviewCustom.PreviewList)] = previewList,
                [nameof(ImagePreviewCustom.PreviewIndex)] = previewIndex
            }).Render()
        });

    }
    catch (Exception ex)
    {
        
    }

    return Task.CompletedTask;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值