diff --git a/demo/Ursa.Demo/Assets/3x.png b/demo/Ursa.Demo/Assets/3x.png new file mode 100644 index 0000000..6dd5bf1 Binary files /dev/null and b/demo/Ursa.Demo/Assets/3x.png differ diff --git a/demo/Ursa.Demo/Pages/ImageViewerDemo.axaml b/demo/Ursa.Demo/Pages/ImageViewerDemo.axaml index 48e6266..85db8e6 100644 --- a/demo/Ursa.Demo/Pages/ImageViewerDemo.axaml +++ b/demo/Ursa.Demo/Pages/ImageViewerDemo.axaml @@ -20,8 +20,9 @@ + Height="300" + MinScale="0.5" + Source="../Assets/3x.png"> SetAndRaise(ScaleProperty, ref _scale, value); } + public static readonly DirectProperty MinScaleProperty = AvaloniaProperty.RegisterDirect( + nameof(MinScale), o => o.MinScale, (o, v) => o.MinScale = v, unsetValue: 0.1); + + public double MinScale + { + get => _minScale; + set => SetAndRaise(ScaleProperty, ref _minScale, value); + } + private double _minScale = 1; + private double _translateX; public static readonly DirectProperty TranslateXProperty = AvaloniaProperty.RegisterDirect( @@ -101,6 +111,8 @@ public class ImageViewer: TemplatedControl set => SetValue(StretchProperty, value); } + private double _sourceMinScale = 0.1; + static ImageViewer() { FocusableProperty.OverrideDefaultValue(true); @@ -109,6 +121,7 @@ public class ImageViewer: TemplatedControl TranslateXProperty.Changed.AddClassHandler((o,e)=>o.OnTranslateXChanged(e)); TranslateYProperty.Changed.AddClassHandler((o, e) => o.OnTranslateYChanged(e)); StretchProperty.Changed.AddClassHandler((o, e) => o.OnStretchChanged(e)); + MinScaleProperty.Changed.AddClassHandler((o, e) => o.OnMinScaleChanged(e)); } private void OnTranslateYChanged(AvaloniaPropertyChangedEventArgs args) @@ -161,14 +174,40 @@ public class ImageViewer: TemplatedControl _image.Height = size.Height; } Scale = GetScaleRatio(width/size.Width, height/size.Height, this.Stretch); + _sourceMinScale = Math.Min(width * MinScale / size.Width, height * MinScale / size.Height); } private void OnStretchChanged(AvaloniaPropertyChangedEventArgs args) { var stretch = args.GetNewValue(); Scale = GetScaleRatio(Width / _image!.Width, Height / _image!.Height, stretch); + if(_image is { }) + { + _sourceMinScale = Math.Min(Width * MinScale / _image.Width, Height * MinScale / _image.Height); + } + else + { + _sourceMinScale = MinScale; + } } - + + private void OnMinScaleChanged(AvaloniaPropertyChangedEventArgs args) + { + if (_image is { }) + { + _sourceMinScale = Math.Min(Width * MinScale / _image.Width, Height * MinScale / _image.Height); + } + else + { + _sourceMinScale = MinScale; + } + + if (_sourceMinScale > Scale) + { + Scale = _sourceMinScale; + } + } + private double GetScaleRatio(double widthRatio, double heightRatio, Stretch stretch) { return stretch switch @@ -203,6 +242,11 @@ public class ImageViewer: TemplatedControl _image.Width = size.Width; _image.Height = size.Height; Scale = GetScaleRatio(width/size.Width, height/size.Height, this.Stretch); + _sourceMinScale = Math.Min(width * MinScale / size.Width, height * MinScale / size.Height); + } + else + { + _sourceMinScale = MinScale; } } @@ -218,7 +262,7 @@ public class ImageViewer: TemplatedControl { var scale = Scale; scale /= 1.1; - if (scale < 0.1) scale = 0.1; + if (scale < _sourceMinScale) scale = _sourceMinScale; Scale = scale; } }