c#winforms如何旋转图像(但不是围绕其中心)

时间:2012-06-08 18:28:32

标签: c# winforms image animation

我正在尝试开发一个我几乎完成的节拍器应用程序。

我剩下的唯一部分是辅助视觉效果,要求我及时向后和向前旋转手臂的图像(在时钟上思考分针)。

如何旋转图像并不绕其中心点旋转图像。在我写作的场景中,我需要能够围绕底部边框中间的一个点旋转图像。

此外,我希望能够在n毫秒内将图像从X旋转到Y,并让它在动画中轻松进出。对于C#来说,这是一座过于遥远的桥梁,是否有任何图书馆可以帮助我实现这种先进的物理动画类型。

非常感谢

3 个答案:

答案 0 :(得分:2)

不是你要求的,但是:

不要每秒多次执行处理器密集型操作,而应考虑翻转一组静态图像。

答案 1 :(得分:2)

扩展回复

没有任何闪烁。 ctor中的SetStyle会处理这个问题。你所看到的“闪烁”是由三个因素引起的神器:

  1. 更新率仅为10 /秒。尝试将其增加到20或30。
  2. 方向值是路线。它应该基于时间/加速。这是留给你的练习。
  3. 蹩脚的“手”图像有坚硬的别名边缘。无论你更新的速度有多快,或者你的动画效果如何,它都会让人感到紧张。再次,做反锯齿,混合图形处理仍然是一个练习。
  4. 仔细查看代码。这不是“在表单上绘制”,它是一个自定义控件。了解MetronomeControl来自Control的方式?通过添加MetronomeControl来了解我们如何创建表单?

    图片框用于显示静态图片,而不是用于自定义控件!

    它更新的方式是创建一个计时器。当计时器的Tick事件触发时,我们更新角度和方向,更一般地说,我们更新控件的状态。对Invalidate的调用告诉操作系统,“嘿,我需要重新绘制,在方便时向我发送WM_PAINT消息!”。我们的OnPaint覆盖只是绘制控件的当前状态。

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Windows.Forms;
    
    class MetronomeControl : Control
    {
        private Bitmap hand;
        private float angle = 0;
        private float direction = 2;
        private Timer timer = new Timer { Enabled = true, Interval = 30 };
    
        public MetronomeControl()
        {
            SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint, true);
            hand = CreateCrappyHandBitmap();
            timer.Tick += new EventHandler(timer_Tick);
        }
    
        void timer_Tick(object sender, EventArgs e)
        {
            if (angle < -45 || angle > 45)
                direction = -direction;
            angle += direction;
            Invalidate();
        }
    
        private static Bitmap CreateCrappyHandBitmap()
        {
            Bitmap bitmap = new Bitmap(100, 300, PixelFormat.Format32bppArgb);
            using (Graphics graphics = Graphics.FromImage(bitmap))
            {
                graphics.Clear(Color.Transparent);
                graphics.FillRectangle(Brushes.LightGray, 50 - 5, 0, 10, 300);
                graphics.FillPolygon(Brushes.LightSlateGray, new Point[] { new Point(50 - 30, 40), new Point(50 + 30, 40), new Point(50 + 20, 80), new Point(50 - 20, 80) });
                graphics.FillEllipse(Brushes.LightSlateGray, 0, 200, 100, 100);
            }
            return bitmap;
        }
    
        protected override void OnPaint(PaintEventArgs e)
        {
            // Erase background since we specified AllPaintingInWmPaint
            e.Graphics.Clear(Color.AliceBlue);
    
            e.Graphics.DrawString(Text, Font, Brushes.Black, new RectangleF(0, 0, ClientSize.Width, ClientSize.Height), new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
    
            // Move the 0,0 point to the just below the bottom-center of our client area
            e.Graphics.TranslateTransform(ClientSize.Width / 2, ClientSize.Height + 40);
            // Rotate around this new 0,0
            e.Graphics.RotateTransform(angle);
            // Turn on AA to make it a bit less jagged looking
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            // Draw the image so that the center of the ellipse is at 0,0
            e.Graphics.DrawImage(hand, 0 - hand.Width / 2, 0 - hand.Height + 50);
    
            // Reset the transform for other drawing
            e.Graphics.ResetTransform();
    
            base.OnPaint(e);
        }
    }
    
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form
            {
                Text = "Metronome Control Demo",
                ClientSize = new Size(640, 480),
                Controls =
                {
                    new MetronomeControl
                    {
                        Location = new Point(10, 10),
                        Size = new Size (340, 300),
                        Font = new Font(FontFamily.GenericSansSerif, 24),
                        Text = "Metronome Control Demo",
                    }
                }
            });
        }
    }
    

答案 2 :(得分:0)

可能是这个示例代码很有用:

Graphics x=Graphics.FromImage(m);
x.TranslateTransform(m.Width / 2, m.Height / 2);
x.RotateTransform(30);
SizeF textSize = x.MeasureString("hi", font);
x.DrawString("hi", font, Brushes.Red, -(textSize.Width / 2), -(textSize.Height / 2);