Search code examples
c#winformsanimationresizezooming

Zoom animation (resize image with mouse events)


I am trying to implement a simple animation when I pick an image in c#, using winforms. The objective is that when the user touches one of the images that are reduced, on mouse-down, it resizes (grows up) and passes a bit of their original size(the original size is bigger than the start size), and the next instant it comes back to the original size.

The code I'm trying to implement is the following:

// - Grows up the control to a bigger size than the original one
while ((sender as Peça).Width < (sender as Peça).imagem.Width) { (sender as Peça).Width = (int)((sender as Peça).Width * 1.8);
  (sender as Peça).Height = (int)((sender as Peça).Height * 1.8);
  (sender as Peça).setSize(new Size((sender as Peça).Width, (sender as Peça).Height));
  Application.DoEvents();
}

// - Return the size of the control to the original one
if ((sender as Peça).Width > (sender as Peça).imagem.Width) { (sender as Peça).Width = (sender as Peça).imagem.Width;
  (sender as Peça).Height = (sender as Peça).imagem.Height;
  (sender as Peça).setSize(new Size((sender as Peça).Width, (sender as Peça).Height));
}

I am not getting the results I wanted. The animation is not smooth, and for that reason I think I am not doing it correctly.

I know that winforms is not the best for this, but I have to use it. Is there any animation library for winforms?


Solution

  • Yes, for simple animation you use a Timer. Any other way would not work smoothly, if at all.

    Here is an example that makes a picturebox a little bigger (by 10 pixels) and reverts to the original size on mousedown and mouseUp.

    I have set the Timer to an Interval of 10ms, which is a little less than its actual resolution of ca. 15ms, so it'll be as smooth as it gets.

    Note: I increase by 2 pixels, so I can adjust the position by 1 and the Picturebox doesn't move. Its SizeMode is Zoom.

    You can extend it if you want it to shrink beyond original then finally reset, but this should get you going..:

    Size originalSize;   //**
    Point originalLoc;   //**
    int resize = 0;
    
    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {
        originalSize = pictureBox1.Size;   //**
        originalLoc= pictureBox1.Location;
        resize = 1;
        timer1.Interval = 10;
        timer1.Start();
    }
    
    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
    {
        resize = -1;
        timer1.Start();
    }
    
    private void pictureBox1_MouseLeave(object sender, EventArgs e)
    {
        timer1.Stop();
        pictureBox1.Size = originalSize;
        pictureBox1.Location = originalLoc;
    }
    
    private void timer1_Tick(object sender, EventArgs e)
    {
        if (resize > 0 && pictureBox1.Width < originalSize.Width+ 10)     //**
        {
            pictureBox1.Size = new Size(pictureBox1.Width + 2, pictureBox1.Height + 2);
            pictureBox1.Location = new Point(pictureBox1.Left - 1, pictureBox1.Top - 1);
        }
        else if (resize < 0 && pictureBox1.Width > originalSize.Width)    //**
        {
            pictureBox1.Size = new Size(pictureBox1.Width - 2, pictureBox1.Height - 2);
            pictureBox1.Location = new Point(pictureBox1.Left + 1, pictureBox1.Top + 1);
        }
        else timer1.Stop();
    }
    

    Note2: I have made a few changes (**) to reliably reset even when leaving while mousedown.