BlueJade

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Image 32 自带的Demo,添加一些注解。

 

unit uFrmAnimation;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
  System.Variants, System.Math, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
  Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, //
  Img32, Img32.Layers;

type
  TfrmAnimation = class(TForm)
    Panel1: TPanel;
    btnDec: TButton;
    btnAdd: TButton;
    lblSpeed: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure btnAddClick(Sender: TObject);
    procedure btnDecClick(Sender: TObject);
  private
    timer: TTimer;                 // 定时器,刷新动画
    reversing: Boolean;            // 颠倒
    imgIndex: integer;             // 动画图片索引
    layeredImage: TLayeredImage32; // 图片分层对象 Image32 (对象存储)
    drawRec: TRect;
    procedure Timer1Timer(Sender: TObject);
  protected
    procedure WMERASEBKGND(var message: TMessage); message WM_ERASEBKGND;
  public
  end;

var
  frmAnimation: TfrmAnimation;

implementation

{$R *.dfm}

uses
  Img32.Draw, Img32.Vector, Img32.Extra;

{ TfrmAnimation }

procedure TfrmAnimation.btnAddClick(Sender: TObject);
begin
  timer.Interval := Max(1, timer.Interval div 2);
end;

procedure TfrmAnimation.btnDecClick(Sender: TObject);
begin
  timer.Interval := Max(1, timer.Interval * 2);
end;

procedure TfrmAnimation.FormCreate(Sender: TObject);
var
  i, j, ballsize, SpaceAbove, maxSquishSize: integer;
  img: TImage32;
  path: TPathD;
  ballRec: TRect;
begin
  ballsize := DPIAware(100);  // 球大小, 根据屏幕分辨率缩放“值”(即屏幕像素/英寸或“点/英寸”)。(请参阅Windows操作系统设置|系统|显示|缩放和布局。)提供了一种实现图像和控件大小一致的�
  SpaceAbove := ballsize * 2; // 上方空间大小
  drawRec := Img32.Vector.Rect(0, 0, ballsize, ballsize + SpaceAbove); // 绘制区域  (0,0,100,300)

  layeredImage := TLayeredImage32.Create;
  layeredImage.SetSize(ballsize, ballsize + SpaceAbove); // 与绘制区域大小相同
  layeredImage.BackgroundColor := Color32(self.Color);   // clBtnFace);

  // path: for drawing a black line at the bottom of the image
  path := Img32.Vector.MakePath([0, ballsize * 3 - 8, ballsize, ballsize * 3 - 8]); // 下方的线条
  with layeredImage.AddLayer(TLayer32) do // 添加一个层图形对象
  begin
    SetInnerBounds(RectD(drawRec));                // 设置绑定区域
    DrawLine(Image, path, 5, clBlack32, esSquare); // Img32.Draw.DrawLine 画线    5为线宽
  end;

  ballRec := Img32.Vector.Rect(0, 0, ballsize, ballsize); // 球的区域

  Winapi.Windows.InflateRect(ballRec, -15, -15); // 扩展区域(负数为缩小)
  path := Ellipse(ballRec);                      // Img32.Vector.Ellipse   //㮋圆(长宽相等为圆)

  // 31 images (25 + 6) will be added to masterImageList. Each will be viewed   31个图像(25+6)将被添加到masterImageList。每个都将被查看
  // twice in each loop except for the top and bottom images. (60 frames/loop)  除了顶部和底部图像之外,每个循环中两次。(60帧/循环)

  img := TImage32.Create(ballsize, ballsize);
  try
    // draw the ball
    DrawPolygon(img, path, frNonZero, clLime32);  // 绘制多边形(填充)
    Draw3D(img, path, frNonZero, 8, 8);           // 使填充区域具有3D效果
    DrawLine(img, path, 3, clGreen32, esPolygon); // 绘制线(此外为圆的边框)
    // 以下是直接(球无变形,只是位置变化)
    for i := 1 to 25 do
    begin
      with layeredImage.AddLayer(TLayer32) do
      begin
        SetInnerBounds(RectD(drawRec));
        j := Round(power(SpaceAbove, i / 25));
        ballRec := Img32.Vector.Rect(0, j, ballsize, j + ballsize);
        Image.CopyBlend(img, img.Bounds, ballRec); // 源 完整拷贝到 目标位置
        Visible := false;                          // 默认此层都是隐藏的.
      end;
    end;

    // 以下是直接(球有变形,目标区域高度变小)
    maxSquishSize := Round(ballsize * 0.75);
    for i := 1 to 6 do
      with layeredImage.AddLayer(TLayer32) do
      begin
        SetInnerBounds(RectD(drawRec));
        ballRec := Img32.Vector.Rect(0, SpaceAbove + maxSquishSize - Round(power(maxSquishSize, (6 - i) / 6)), ballsize, SpaceAbove + ballsize);
        Image.CopyBlend(img, img.Bounds, ballRec);
        Visible := false; // 默认此层都是隐藏的.
      end;
  finally
    img.Free;
  end;

  // 创建,启动定时器
  timer := TTimer.Create(self);
  timer.OnTimer := Timer1Timer;
  timer.Interval := 15;
  timer.Enabled := true;
end;

procedure TfrmAnimation.FormDestroy(Sender: TObject);
begin
  layeredImage.Free;
  timer.Free;
end;

procedure TfrmAnimation.FormPaint(Sender: TObject);
begin
  with layeredImage.GetMergedImage do   //获取合并的图像(只有图层显示状态的才参与合并)
    CopyToDc(Bounds, Canvas.Handle, drawRec.Left, drawRec.Top, false);
end;

procedure TfrmAnimation.FormResize(Sender: TObject);
begin  //当窗口大小发生变化时,要重新计算绘制区域位置
  if csDestroying in ComponentState then
    Exit;
  // repaint the whole background only when resizing.   只有在调整大小时才能重新绘制整个背景。
  Canvas.FillRect(ClientRect);
  // center the animation in the form clientrect    将动画置于窗口显示区域的中心
  Img32.Vector.TranslateRect(drawRec, //  修改 drawRec
    -drawRec.Left + (ClientWidth - layeredImage.Width) div 2,  //
    -drawRec.Top + (ClientHeight - layeredImage.Height) div 2); //
end;

procedure TfrmAnimation.Timer1Timer(Sender: TObject);
begin
  if imgIndex > 0 then   //当前绘制的图层索引
    layeredImage[imgIndex].Visible := false;  //此层不显示
  // 计算当前应该显示哪张图片
  if reversing then    //是否颠倒
  begin
    dec(imgIndex);
    if (imgIndex = 1) then
      reversing := false;
  end
  else
  begin
    inc(imgIndex);
    if (imgIndex = layeredImage.Count - 1) then
      reversing := true;
  end;
  layeredImage[imgIndex].Visible := true;  //当前层显示
  Invalidate;  //使窗口无效(即要求重新绘制窗口)
end;

procedure TfrmAnimation.WMERASEBKGND(var message: TMessage);
begin
  message.Result := 1;
  // this stops windows unhelpfully erasing the form's canvas.    这将阻止windows毫无帮助地擦除窗体的画布。
  // We want full control of painting (see FormPaint below).      我们希望完全控制绘画(请参阅下面的FormPaint)
end;

end.

效果:

posted on 2024-06-11 16:33  bluejade2024  阅读(10)  评论(0编辑  收藏  举报