C# 如何使图像放大&;在Blazor里用鼠标滚轮出去?
我想在asp.net上放大和缩小blazor中的图像 当我使用谷歌地图时,我想通过使用鼠标滚轮缩放和拖动图像来移动图像位置。(我想使用图像文件,而不是谷歌地图。) 有没有办法放大、缩小和拖动blazor中的特定图像?注意:C# 如何使图像放大&;在Blazor里用鼠标滚轮出去?,c#,asp.net,blazor,C#,Asp.net,Blazor,我想在asp.net上放大和缩小blazor中的图像 当我使用谷歌地图时,我想通过使用鼠标滚轮缩放和拖动图像来移动图像位置。(我想使用图像文件,而不是谷歌地图。) 有没有办法放大、缩小和拖动blazor中的特定图像?注意: 我只会在上使用它,而不是因为如果网络速度慢,可能会有相当大的延迟 只使用JavaScript和/或可能更容易,但对于这个示例,我决定不使用JS互操作 使用此组件,您可以在按住鼠标滚轮的同时按住shift键进行缩放(缩小),或按住鼠标滚轮的同时按住1键进行移动。(与其说是
- 我只会在上使用它,而不是因为如果网络速度慢,可能会有相当大的延迟
- 只使用JavaScript和/或可能更容易,但对于这个示例,我决定不使用JS互操作
- 目前最大的问题是无法访问html元素as and中的鼠标
和OffsetX
,因此只能使用CSS来移动图像OffsetY
- 我之所以使用Shift进行滚动,是因为即使使用
,@onscroll:stopPropagation
,@onwheel:stopPropagation
和/或@onmouseheel:stopPropagation
,@oncroll:preventDefault
,滚动也不会被阻止或禁用,@onwheel:preventDefault
在父@onmouseheel:preventDefault
元素上设置。如果内容比可查看页面宽,屏幕仍将左右滚动mainImageContainer
transform:scale(n)@onmouseheel
事件中的code>属性
图像的移动有点复杂,因为没有鼠标指针相对于图像或元素边界的参考位置。(抵销额x和抵销额)
我们唯一能确定的是是否按下了鼠标按钮,然后计算鼠标在左
、右
、向上
或向下
移动的方向
然后,通过将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}%";
}
});
}
}
@使用System.Text;
@*此div仅用于缩放时四处移动*@
@如果(显示重置按钮)
{
重置
}
@代码{
///
///图像的路径或url
///
[参数]
公共字符串ImageUrlPath{get;set;}
///
///图像的宽度
///
[参数]
公共int ImageWidthInPx{get;set;}
///
///图像的高度
///
[参数]
public int-ImageHeightInPx{get;set;}
///
///设置为true以显示重置按钮
///
[参数]
公共bool showretebutton{get;set;}
///
///设置图像的缩放量,默认值为0.1f
///
[参数]
公共双DefaultScaleBy{get;set;}=0.1f;
///
///图像可以缩放到的最大值,默认值为5f
///
[参数]
公共双尺度最大值{get;set;}=5f;
///
///设置图像移动的速度(默认为2)。
///2或3似乎效果最好。
///
[参数]
公共双DefaultMoveBy{get;set;}=2;
//默认值
双电流标度=1.0f;
双位置左=0;
双位置顶部=0;
double _OldClientX=0;
double _OldClientY=0;
双精度_DefaultMinPosition=0;//在顶部和左侧
double _DefaultMaxPosition=0;//向右和向下
//用于在子div中显示图像的默认设置
私人字典(ImageContainerStyles);;
字典图像容器样式
{
得到
{
if(_ImageContainerStyles==null)
{
_ImageContainerStyles=新字典();
_添加(“宽度”,“100%”);
_ImageContainerStyles.添加(“高度”、“100%”);
_添加(“位置”、“相对”);
_添加(“背景大小”、“包含”);
_添加(“背景重复”,“无重复”);
_添加(“背景位置”,“50%50%”);
_Add(“background image”,$“URL({ImageUrlPath})”;
}
返回ImageContainerStyles;
}
}
私人词典(移动集装箱样式);;
字典移动容器样式
{
得到
{
if(_MovingContainerStyles==null)
{
调用同步(重置同步);
}
返回移动集装箱方式;
}
}
受保护的异步任务ResetImgage()
{
_位置左=0;
_PositionTop=0;
_DefaultMinPosition=0;
_DefaultMaxPosition=0;
_电流标度=1.0f;
_MovingContainerStyles=新字典();
_MovingContainerStyles。添加(“宽度”、“100%”);
_MovingContainerStyles.添加(“高度”、“100%”);
_移动集装箱方式。添加(“位置”、“相对”);
_MovingContainerStyles.Add(“left”、$“{u PositionLeft}%”;
_MovingContainerStyles.TryAdd(“top”,“$”{u PositionTop}%”);
等待调用同步(StateHasChanged);
}
字符串ZoomImageStyle{get=>DictionaryToCss(ImageContainerStyles);}
字符串MoveImageStyle{get=>DictionaryToCss(MovingContainerStyles);}
私有字符串字典(字典样式字典)
{
StringBuilder sb=新的StringBuilder();
对于
@page "/"
@using BlazorWasmApp.Components
Welcome to your new app.
<ZoomableImageComponent ImageUrlPath="images/Capricorn.png"
ImageWidthInPx=400
ImageHeightInPx=300
ShowResetButton=true
DefaultScaleBy=0.1f />