Here's an example of a rotating image using the Matrix.RotateAt() method.
This is a pretty simple process:
- Create a Bitmap object from an Image file (or a Project resource); note that the Bitmap is [Cloned][2]: this way, we are detaching it from the FileStream (GDI+ won't lock the file while in use). Remember to Dispose() of it when you're done with it (or the application closes)
- define a rotation angle that fits the image shape
- set a Timer interval that generates the rotation speed (combined with the rotation angle). We are using a System.Windows.Form.Timer of course: we want it to tick in the UI thread (note that this object needs to be Disposed, too)
- when the Timer ticks, Invalidate() the canvas (a PictureBox control, here)
- use
Matrix.RotateAt(gearCurrentRotationAngle, [ImageCentre])
and apply the Matrix to the Graphics geometric world transformation using its Transform property
- add the chosen rotation angle to the current rotation angle at each rotation. When it reaches 360 degrees, re-set to min value (the
gearRotationAngle
field value, here)
Some other examples here:
Transparent Overlapping Circular Progress Bars
GraphicsPath and Matrix classes
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
Bitmap gear = null;
RectangleF gearRect = Rectangle.Empty;
int gearRotateSpeed = 100;
int gearRotationAngle = 24;
int gearCurrentRotationAngle = 0;
System.Windows.Forms.Timer gearTimer = new System.Windows.Forms.Timer();
public Form1() {
InitializeComponent();
gear = Image.FromStream(new MemoryStream(File.ReadAllBytes(@"File Path")));
// Assuming the Gear Image is square shaped and the PictureBox size remains constant
// otherwise, recalculate in the Control.Resize event
var gearScale = Math.Min(pictureBox1.Width, pictureBox1.Height) / (float)Gear.Width;
var gearSize = new SizeF(gear.Width * gearScale, gear.Height * gearScale);
gearRect = new RectangleF(new PointF((pictureBox1.Width - gearSize.Width) / 2.0f, (pictureBox1.Height - gearSize.Height) / 2.0f), gearSize);
gearTimer.Tick += (s, e) => {
gearCurrentRotationAngle += gearRotationAngle;
if (gearCurrentRotationAngle > 360) gearCurrentRotationAngle = gearRotationAngle;
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseEnter(object sender, EventArgs e) {
gearTimer.Interval = gearRotateSpeed;
gearTimer.Start();
}
private void pictureBox1_MouseLeave(object sender, EventArgs e) => gearTimer.Stop();
private void pictureBox1_Paint(object sender, PaintEventArgs e) {
var canvas = sender as PictureBox;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
PointF centerImage = new PointF(canvas.Width / 2, canvas.Height / 2);
using (var mx = new Matrix()) {
mx.RotateAt(gearCurrentRotationAngle, centerImage);
e.Graphics.Transform = mx;
e.Graphics.DrawImage(gear, gearRect);
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…