Search code examples
imagedelphianimationflip

Playing card flip animation


Do you know of any free components/libraries, which allow to achieve a 3D flip effect?

Demo here: snorkl.tv


Solution

  • Something like this might do the similar effect (just another attempt to show how this could be done, also not so precise, but it's just for fun since you've asked for a library or component). The principle is based on a rectnagle that is being resized and centered in the paint box where the card is being rendered with the StretchDraw function:

    Unit1.pas

    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls, PNGImage;
    
    type
      TCardSide = (csBack, csFront);
      TForm1 = class(TForm)
        Timer1: TTimer;
        Timer2: TTimer;
        PaintBox1: TPaintBox;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
        procedure Timer2Timer(Sender: TObject);
        procedure PaintBox1Click(Sender: TObject);
        procedure PaintBox1Paint(Sender: TObject);
      private
        FCardRect: TRect;
        FCardSide: TCardSide;
        FCardBack: TPNGImage;
        FCardFront: TPNGImage;
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      FCardSide := csBack;
      FCardRect := PaintBox1.ClientRect;
      FCardBack := TPNGImage.Create;
      FCardBack.LoadFromFile('tps2N.png');
      FCardFront := TPNGImage.Create;
      FCardFront.LoadFromFile('Ey3cv.png');
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      FCardBack.Free;
      FCardFront.Free;
    end;
    
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      if FCardRect.Right - FCardRect.Left > 0 then
      begin
        FCardRect.Left := FCardRect.Left + 3;
        FCardRect.Right := FCardRect.Right - 3;
        PaintBox1.Invalidate;
      end
      else
      begin
        Timer1.Enabled := False;
        case FCardSide of
          csBack: FCardSide := csFront;
          csFront: FCardSide := csBack;
        end;
        Timer2.Enabled := True;
      end;
    end;
    
    procedure TForm1.Timer2Timer(Sender: TObject);
    begin
      if FCardRect.Right - FCardRect.Left < PaintBox1.ClientWidth then
      begin
        FCardRect.Left := FCardRect.Left - 3;
        FCardRect.Right := FCardRect.Right + 3;
        PaintBox1.Invalidate;
      end
      else
        Timer2.Enabled := False;
    end;
    
    procedure TForm1.PaintBox1Click(Sender: TObject);
    begin
      Timer1.Enabled := False;
      Timer2.Enabled := False;
      FCardRect := PaintBox1.ClientRect;
      Timer1.Enabled := True;
      PaintBox1.Invalidate;
    end;
    
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    begin
      case FCardSide of
        csBack: PaintBox1.Canvas.StretchDraw(FCardRect, FCardBack);
        csFront: PaintBox1.Canvas.StretchDraw(FCardRect, FCardFront);
      end;
    end;
    
    end.
    

    Unit1.dfm

    object Form1: TForm1
      Left = 0
      Top = 0
      Caption = 'Form1'
      ClientHeight = 203
      ClientWidth = 173
      Color = clBtnFace
      DoubleBuffered = True
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      Position = poScreenCenter
      OnCreate = FormCreate
      OnDestroy = FormDestroy
      PixelsPerInch = 96
      TextHeight = 13
      object PaintBox1: TPaintBox
        Left = 48
        Top = 40
        Width = 77
        Height = 121
        OnClick = PaintBox1Click
        OnPaint = PaintBox1Paint
      end
      object Timer1: TTimer
        Enabled = False
        Interval = 10
        OnTimer = Timer1Timer
        Left = 32
        Top = 88
      end
      object Timer2: TTimer
        Enabled = False
        Interval = 10
        OnTimer = Timer2Timer
        Left = 88
        Top = 88
      end
    end
    

    Cards

    enter image description here enter image description here