gpt4 book ai didi

c# - 如何在 Blazor 中使用鼠标滚轮放大和缩小图像?

转载 作者:行者123 更新时间:2023-12-04 12:14:03 27 4
gpt4 key购买 nike

我想在 asp.net 上的 blazor 中放大和缩小图像。
当我用于谷歌地图时,我想通过用鼠标滚轮缩放和拖动图像来移动图像位置。(我想使用图像文件,而不是谷歌地图。)
Example of use
有没有办法在 blazor 中放大、缩小和拖动特定图像?

最佳答案

注:

  • 我只会在 BlazorWasm 上使用它而不是 BlazorServer因为如果网络很慢,可能会有相当多的延迟。
  • 仅使用 JavaScript 和/或 JavaScript interoperability (JS interop) 可能更容易但对于这个例子,我决定 不使用 JS互操作。

  • 此组件使您可以通过按 shift 进行缩放。而 mouse wheel向上(缩小)或 mouse wheel向下(放大)并按 mouse button 1 移动图像移动时向下。 ( 比拖动更平移 )
    Blazor 中的限制: (在撰写本文时)
  • 目前最大的问题是无法访问鼠标 OffsetXOffsetY在 html 元素中作为 described herealso here ,因此必须仅使用 CSS 来移动图像。
  • 我使用的原因 换类 滚动是因为滚动没有被阻止或禁用为 described here即使与 @onscroll:stopPropagation , @onwheel:stopPropagation , @onmousewheel:stopPropagation和/或 @onscroll:preventDefault , @onwheel:preventDefault , @onmousewheel:preventDefault设置在父级 mainImageContainer元素。如果内容比可见页面宽,屏幕仍会左右滚动。

  • 解决方案:
    缩放部分非常简单,您需要做的就是设置 transform:scale(n);属性(property)在 @onmousewheel事件。
    图像的移动有点复杂,因为没有引用鼠标指针相对于图像或元素边界的位置。 (OffsetX 和 OffsetY)
    我们唯一可以确定的是是否按下了鼠标按钮,然后计算鼠标在 left 中移动的方向。 , right , updown .
    然后的想法是通过设置 top 来移动元素与图像的位置。和 left CSS 值作为百分比。
    此组件代码:
    @using System.Text;

    <div id="mainImageContainer" style="display: block;width:@($"{ImageWidthInPx}px");height:@($"{ImageHeightInPx}px");overflow: hidden;">
    <div id="imageMover"
    @onmousewheel="MouseWheelZooming"
    style="@MoveImageStyle">
    <div id="imageContainer"
    @onmousemove="MouseMoving"
    style="@ZoomImageStyle">
    @*this div is used just for moving around when zoomed*@
    </div>
    </div>
    </div>
    @if (ShowResetButton)
    {
    <div style="display:block">
    <button @onclick="ResetImgage">Reset</button>
    </div>
    }

    @code{

    /// <summary>
    /// The path or url of the image
    /// </summary>
    [Parameter]
    public string ImageUrlPath { get; set; }

    /// <summary>
    /// The width of the image
    /// </summary>
    [Parameter]
    public int ImageWidthInPx { get; set; }

    /// <summary>
    /// The height of the image
    /// </summary>
    [Parameter]
    public int ImageHeightInPx { get; set; }

    /// <summary>
    /// Set to true to show the reset button
    /// </summary>
    [Parameter]
    public bool ShowResetButton { get; set; }

    /// <summary>
    /// Set the amount the image is scaled by, default is 0.1f
    /// </summary>
    [Parameter]
    public double DefaultScaleBy { get; set; } = 0.1f;

    /// <summary>
    /// The Maximum the image can scale to, default = 5f
    /// </summary>
    [Parameter]
    public double ScaleToMaximum { get; set; } = 5f;

    /// <summary>
    /// Set the speed at which the image is moved by, default 2.
    /// 2 or 3 seems to work best.
    /// </summary>
    [Parameter]
    public double DefaultMoveBy { get; set; } = 2;

    //defaults
    double _CurrentScale = 1.0f;
    double _PositionLeft = 0;
    double _PositionTop = 0;
    double _OldClientX = 0;
    double _OldClientY = 0;
    double _DefaultMinPosition = 0;//to the top and left
    double _DefaultMaxPosition = 0;//to the right and down

    //the default settings used to display the image in the child div
    private Dictionary<string, string> _ImageContainerStyles;
    Dictionary<string, string> ImageContainerStyles
    {
    get
    {
    if (_ImageContainerStyles == null)
    {
    _ImageContainerStyles = new Dictionary<string, string>();
    _ImageContainerStyles.Add("width", "100%");
    _ImageContainerStyles.Add("height", "100%");
    _ImageContainerStyles.Add("position", "relative");
    _ImageContainerStyles.Add("background-size", "contain");
    _ImageContainerStyles.Add("background-repeat", "no-repeat");
    _ImageContainerStyles.Add("background-position", "50% 50%");
    _ImageContainerStyles.Add("background-image", $"URL({ImageUrlPath})");
    }
    return _ImageContainerStyles;
    }
    }

    private Dictionary<string, string> _MovingContainerStyles;
    Dictionary<string, string> MovingContainerStyles
    {
    get
    {
    if (_MovingContainerStyles == null)
    {
    InvokeAsync(ResetImgage);
    }
    return _MovingContainerStyles;
    }
    }

    protected async Task ResetImgage()
    {
    _PositionLeft = 0;
    _PositionTop = 0;
    _DefaultMinPosition = 0;
    _DefaultMaxPosition = 0;
    _CurrentScale = 1.0f;

    _MovingContainerStyles = new Dictionary<string, string>();
    _MovingContainerStyles.Add("width", "100%");
    _MovingContainerStyles.Add("height", "100%");
    _MovingContainerStyles.Add("position", "relative");
    _MovingContainerStyles.Add("left", $"{_PositionLeft}%");
    _MovingContainerStyles.TryAdd("top", $"{_PositionTop}%");

    await InvokeAsync(StateHasChanged);
    }

    string ZoomImageStyle { get => DictionaryToCss(ImageContainerStyles); }
    string MoveImageStyle { get => DictionaryToCss(MovingContainerStyles); }


    private string DictionaryToCss(Dictionary<string, string> styleDictionary)
    {
    StringBuilder sb = new StringBuilder();
    foreach (var kvp in styleDictionary.AsEnumerable())
    {
    sb.AppendFormat("{0}:{1};", kvp.Key, kvp.Value);
    }
    return sb.ToString();
    }


    protected async void MouseMoving(MouseEventArgs e)
    {
    //if the mouse button 1 is not down exit the function
    if (e.Buttons != 1)
    {
    _OldClientX = e.ClientX;
    _OldClientY = e.ClientY;
    return;
    }

    //get the % of the current scale to move by at least the default move speed plus any scaled changes
    //basically the bigger the image the faster it moves..
    double scaleFrac = (_CurrentScale / ScaleToMaximum);
    double scaleMove = (DefaultMoveBy * (DefaultMoveBy * scaleFrac));

    //moving mouse right
    if (_OldClientX < e.ClientX)
    {
    if ((_PositionLeft - DefaultMoveBy) <= _DefaultMaxPosition)
    {
    _PositionLeft += scaleMove;
    }
    }

    //moving mouse left
    if (_OldClientX > e.ClientX)
    {
    //if (_DefaultMinPosition < (_PositionLeft - DefaultMoveBy))
    if ((_PositionLeft + DefaultMoveBy) >= _DefaultMinPosition)
    {
    _PositionLeft -= scaleMove;
    }
    }

    //moving mouse down
    if (_OldClientY < e.ClientY)
    {
    //if ((_PositionTop + DefaultMoveBy) <= _DefaultMaxPosition)
    if ((_PositionTop - DefaultMoveBy) <= _DefaultMaxPosition)
    {
    _PositionTop += scaleMove;
    }
    }

    //moving mouse up
    if (_OldClientY > e.ClientY)
    {
    //if ((_PositionTop - DefaultMoveBy) > _DefaultMinPosition)
    if ((_PositionTop + DefaultMoveBy) >= _DefaultMinPosition)
    {
    _PositionTop -= scaleMove;
    }
    }

    _OldClientX = e.ClientX;
    _OldClientY = e.ClientY;

    await UpdateScaleAndPosition();
    }

    async Task<double> IncreaseScale()
    {
    return await Task.Run(() =>
    {
    //increase the scale first then calculate the max and min positions
    _CurrentScale += DefaultScaleBy;
    double scaleFrac = (_CurrentScale / ScaleToMaximum);
    double scaleDiff = (DefaultMoveBy + (DefaultMoveBy * scaleFrac));
    double scaleChange = DefaultMoveBy + scaleDiff;
    _DefaultMaxPosition += scaleChange;
    _DefaultMinPosition -= scaleChange;

    return _CurrentScale;
    });
    }

    async Task<double> DecreaseScale()
    {
    return await Task.Run(() =>
    {
    _CurrentScale -= DefaultScaleBy;

    double scaleFrac = (_CurrentScale / ScaleToMaximum);
    double scaleDiff = (DefaultMoveBy + (DefaultMoveBy * scaleFrac));
    double scaleChange = DefaultMoveBy + scaleDiff;
    _DefaultMaxPosition -= scaleChange;
    _DefaultMinPosition += scaleChange;//DefaultMoveBy;

    //fix descaling, move the image back into view when descaling (zoomin out)
    if (_CurrentScale <= 1)
    {
    _PositionLeft = 0;
    _PositionTop = 0;
    }
    else
    {
    //left can not be more than max position
    _PositionLeft = (_DefaultMaxPosition < _PositionLeft) ? _DefaultMaxPosition : _PositionLeft;

    //top can not be more than max position
    _PositionTop = (_DefaultMaxPosition < _PositionTop) ? _DefaultMaxPosition : _PositionTop;

    //left can not be less than min position
    _PositionLeft = (_DefaultMinPosition > _PositionLeft) ? _DefaultMinPosition : _PositionLeft;

    //top can not be less than min position
    _PositionTop = (_DefaultMinPosition > _PositionTop) ? _DefaultMinPosition : _PositionTop;
    }
    return _CurrentScale;
    });
    }

    protected async void MouseWheelZooming(WheelEventArgs e)
    {
    //holding shift stops the page from scrolling
    if (e.ShiftKey == true)
    {
    if (e.DeltaY > 0)
    {
    _CurrentScale = ((_CurrentScale + DefaultScaleBy) >= 5) ? _CurrentScale = 5f : await IncreaseScale();
    }
    if (e.DeltaY < 0)
    {
    _CurrentScale = ((_CurrentScale - DefaultScaleBy) <= 0) ? _CurrentScale = DefaultScaleBy : await DecreaseScale();
    }

    await UpdateScaleAndPosition();
    }
    }

    /// <summary>
    /// Refresh the values in the moving style dictionary that is used to position the image.
    /// </summary>
    async Task UpdateScaleAndPosition()
    {
    await Task.Run(() =>
    {
    if (!MovingContainerStyles.TryAdd("transform", $"scale({_CurrentScale})"))
    {
    MovingContainerStyles["transform"] = $"scale({_CurrentScale})";
    }

    if (!MovingContainerStyles.TryAdd("left", $"{_PositionLeft}%"))
    {
    MovingContainerStyles["left"] = $"{_PositionLeft}%";
    }

    if (!MovingContainerStyles.TryAdd("top", $"{_PositionTop}%"))
    {
    MovingContainerStyles["top"] = $"{_PositionTop}%";
    }
    });
    }

    }
    这是用法:
    @page "/"
    @using BlazorWasmApp.Components
    Welcome to your new app.

    <ZoomableImageComponent ImageUrlPath="images/Capricorn.png"
    ImageWidthInPx=400
    ImageHeightInPx=300
    ShowResetButton=true
    DefaultScaleBy=0.1f />
    这是结果:
    enter image description here
    我只在没有触摸输入的台式电脑上用 chrome 测试过这个。

    关于c# - 如何在 Blazor 中使用鼠标滚轮放大和缩小图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63626228/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com