Question

So here is my questions that I hope I will be able to ask it in a proper way.

In brief: how to zoom smoothly in WPF?

In detail: I'm writing a CAD application in WPF that I'm redrawing parts of the screen when MouseWheel event is fired.

private void ModelWindowBorder_MouseWheel(object sender, MouseWheelEventArgs e)
{
       var zoom = e.Delta > 0 ? 0.2 : -0.2;
    // increase or decrease the scale by *zoom*
    // Redraw Screen
    // Apply TransformScale and etc.
}

Well actually the above code works but I'm not content with it for two reasons:

  1. When I have to redraw lots of visuals on the screen it kinda misses the multiple MouseWheel events that are fired. So if 8 MouseWheel events are to be fired in one big scroll only 4-5 of them are fired. And this makes the zooming a little slow.

  2. The second reason might not be WPF related at all. Is var zoom = e.Delta > 0 ? 0.2 : -0.2; the correct way we should increase/decrease the scale? To me it seems not appropriate. Since when we are zoomed out the difference seems considerable when we zoom in by one step, but once we are close to the drawing, increasing the zoom by one step doesn't seem much.

I'd like to know your answers and comments on both of these issues.

Was it helpful?

Solution

Problem 1.

You should take in account the value of e.Delta.

Not

var zoom = e.Delta > 0 ? 0.2 : -0.2;

but

var zoom = e.Delta * k;

k is a double factor, it's device specific

The effective upper and lower ranges of this value potentially come from device implementations or other callers that raised the event, and are therefore not defined

But its value get higher for as you say one big scroll.

One possible solution to find k would be to get first MouseWheel event and use received value as a starting point. If you receive double of that value, then two or more of mousewheel scrolls were combined into single event. Or do calibration all time, remembering smallest value and changing factor for it. Up to you.

Problem 2.

Use multiplication instead of adding flat value.

And combined solution will looks like this

st.ScaleX *= e.Delta * k;

OTHER TIPS

One simple thing to try and coelesce MouseWheel events is to use Rx. You can use the .FromEventPattern() method to consume Wheel events and only care about those that satisfy your delta tolerances. Rx is a little tricky but can help you have simpler code paths.

See this answer - Detect scroll is completed with PointerWheelChanged

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top