应用场景:视频播放窗口缩放,最小保持100%
帧图像:视频中的一帧图像
视口:用于显示视频的区域
可视区域:帧图像中某一块区域,拉伸后贴图到视口
说明:当鼠标在视口中任意位置滚动滚轮,向上放大时可视区域变小,向下缩小时可视区域变大,将可视区域内的图像拉伸贴图到视口,即实现缩放效果。
要达到以鼠标为中心缩放的目的,必须对可视区域进行相应计算,以下是伪代码说明:
Bmp := TBitmap.Create;//帧图像初始化
Bmp.LoadFormFile('1.bmp');
ViewRect := Rect(0, 0, Bmp.Width, Bmp.Height);//可视区域初始化
//在鼠标滚轮事件中实现以下代码
if WheelDelta > 0 then
begin
//比例因子以100%递增
if Scale > 32 then exit;
Inc(Scale);
end
else
begin
//缩小时以100%递减
if Scale <= 1 then exit
Dec(Scale);
end;
//1.计算出放大N倍时可视区域的宽和高
W := Bmp.Width div Scale;
H := Bmp.Height div Scale;
if Scale = 1 then//不允许缩小
begin
L := 0;
T := 0;
end
else
begin
//2.计算出可视区域
pt := ScreenToClient(MousePos);
sx := pt.x / Bmp.Width;//鼠标位置在视口位置的百分比
sy := pt.y / Bmp.Height;
SW := ViewRect.Right - ViewRect.Left;
SH := ViewRect.Bottom - ViewRect.Top;
L := ViewRect.Left + Round((SW - W) * sx);//缩放前后区域宽和高乘以鼠标位置占比,得出可视区域坐标移动范围
T := ViewRect.Top + Round((SH - H) * sy);
if L < 0 then L := 0;//防止左边越界
if L + W > Bmp.Width then L := Bmp.Width - W;//防止右边越界
if T < 0 then T := 0;//防止上边越界
if T + H > Bmp.Height then T := Bmp.Height - H;//防止下边越界
end;
ViewRect := Rect(L, T, L + W, T + H);//计算出可视区域
DestImage.Canvas.CopyRect(DestImage.BoundsRect, Bmp.Canvas, ViewRect);//将可视区域中的图块拉伸并贴图到视口
//放大后的图像拖动漫游,
//在OnMouseDown事件中记录鼠标按下状态和鼠标位置,在OnMouseUp中释放鼠标按下状态
//在MouseMove事件中处理
if IsMouseDown or (Scale < 2) then exit;
sx := Round((X - ImageDownX) / Scale);//拖动距离按比例缩放,比如在4倍放大时拖动4个像素,可视区域实际只移动一个像素
sy := Round((Y - ImageDownY) / Scale);
if sx > 0 then//向右拖
begin
if sx > ViewRect.Left then//防止越界
sx := ViewRect.Left;
end
else if sx < 0 then//向左拖
begin
if Abs(sx) > Bmp.Width - ViewRect.Right then//防止越界
sx := Bmp.Width - ViewRect.Right;
end;
if sy > 0 then//向下拖
begin
if sy > ViewRect.Top then//防止越界
sy := ViewRect.Top;
end
else if sy < 0 then//向上拖
begin
if Abs(sy) > Bmp.Height - ViewRect.Bottom then//防止越界
sy := Bmp.Height - ViewRect.Bottom;
end;
ImageDownX := X;
ImageDownY := Y;
if (sx = 0) and (sy = 0) then Exit;
OffsetRect(ViewRect, -sx, -sy);
DestImage.Canvas.CopyRect(DestImage.BoundsRect, Bmp.Canvas, ViewRect);