Silverlight 3 - ScaleTransform или другой метод увеличения холста?

Мне нужно иметь возможность масштабировать и удалять холст с помощью колесика мыши. Я успешно настроил обработчики колесиков мыши, и в настоящее время я использую ScaleTransform для применения масштабирования; однако масштабирование не выполняется "интуитивным" способом.

Я пытаюсь выполнить тот же стиль "масштабирования", который вы можете увидеть в MultiScaleImage, Google Maps/Earth или Adobe Acrobat Reader, но НЕ с изображением с элементом управления. Переход не обязательно должен быть "гладким" или анимированным (если это не простой подход), но функциональность должна быть одинаковой.

Любые мысли или идеи будут высоко оценены и благодарны заранее!

Изменить: мне удалось "сгладить" масштаб с помощью анимации:

<Canvas.Resources>
            <Storyboard x:Name="ZoomStoryboard">
                <DoubleAnimation x:Name="ZoomAnimationX"
                                 Storyboard.TargetName="Workspace"
                                 Storyboard.TargetProperty="Canvas.RenderTransform.ScaleTransform.ScaleX"
                                 Duration="0:0:0.2"/>
                <DoubleAnimation x:Name="ZoomAnimationY"
                                 Storyboard.TargetName="Workspace"
                                 Storyboard.TargetProperty="Canvas.RenderTransform.ScaleTransform.ScaleY"
                                 Duration="0:0:0.2"/>
            </Storyboard>
        </Canvas.Resources>

со следующим кодом:

_Zoom += (args.Delta / 7);
if (_Zoom < 0.15)
    _Zoom = 0.15;
ZoomAnimationX.To = _Zoom;
ZoomAnimationY.To = _Zoom;
ZoomStoryboard.Begin();
ZoomScale.Text = _Zoom.ToString("0.00") + "x";
_PreviousMousePosition = _CurrentMousePosition

Тем не менее, все еще возникает проблема, заключающаяся в том, что она направлена ​​вверх в верхнем левом углу, в отличие от таких сайтов, как Карты Google, где зум "вокруг" мыши.

Ответ 1

Вам нужно использовать средневзвешенное значение в качестве центра масштабирования на основе положения мыши. Другими словами, держите последний центр масштабирования (или если у вас его еще нет, просто установите его в текущую позицию мыши) и сохраните количество раз, когда рассчитывался центр масштабирования (после первого увеличения, что будет 1), Затем каждый раз, когда вы пересчитываете центр масштабирования, увеличивайте этот параметр var.

Пример кода: deltaZoom - это масштаб масштабирования, centerX и centerY - текущий центр масштабирования, ZoomStep - это количество раз, когда мы увеличили масштаб, а mouseX и mouseY - текущая позиция мыши:

_Zoom += deltaZoom;
        if (_Zoom <= 0)
            _Zoom = 0.1;

        if (deltaZoom >= 0)
        {
            if (_ZoomSteps == -1)
            {
                _CenterX = 0;
                _CenterY = 0;
                _ZoomSteps = 0;
            }
            else
            {
                _CenterX = (_CenterX * Math.Abs(_ZoomSteps) + mouseX) / (Math.Abs(_ZoomSteps + 1));
                _CenterY = (_CenterY * Math.Abs(_ZoomSteps) + mouseY) / (Math.Abs(_ZoomSteps + 1));
                _ZoomSteps++;
            }
        }
        else
        {
            if (_ZoomSteps == 1)
            {
                _CenterX = 0;
                _CenterY = 0;
                _ZoomSteps = 0;
            }
            else
            {
                _CenterX = (_CenterX * Math.Abs(_ZoomSteps) - mouseX) / (Math.Abs(_ZoomSteps - 1));
                _CenterY = (_CenterY * Math.Abs(_ZoomSteps) - mouseY) / (Math.Abs(_ZoomSteps - 1));
                _ZoomSteps--;
            }
        }

        ZoomAnimationX.To = _Zoom;
        ZoomAnimationY.To = _Zoom;
        CenterAnimationX.To = Math.Abs(_CenterX);
        CenterAnimationY.To = Math.Abs(_CenterY);
        ZoomStoryboard.Begin();

Отредактировано так, что вы можете опуститься ниже уровня масштабирования 1.0, но все еще есть некоторые проблемы (ZoomStep = -1, 0 или 1 иногда вызывает странные тряски).