123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- @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}%";
- }
- });
- }
- }
|