此功能模仿微信朋友圈查看图片交互设计,预览图片的放大缩小左移右移。
还有很多缺陷,比如图片切换没有动画效果,2个月前写的,好多不记得了。
而且delphi自带手势滑动的快慢是有区别的,StandardGestures和interactiveGestures有描述。
手势都是窗体的。
unit UPreviewImage;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.TabControl,
DRFormClass,System.Generics.Collections,DataRec,FMX.Objects,MSFileCLass,
FMX.Gestures,System.Math;
type
TFrmPreviewImage = class(TForm)
TabEnlargeImage: TTabControl;
GestureManager1: TGestureManager;
procedure TabEnlargeImageMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Single);
procedure TabEnlargeImageGesture(Sender: TObject;
const EventInfo: TGestureEventInfo; var Handled: Boolean);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Single);
procedure FormGesture(Sender: TObject; const EventInfo: TGestureEventInfo;
var Handled: Boolean);
private
FSendData : TDictionary<integer, TSelectPictureInfo> ;
FNumber : integer;
FMSCarrierObject_ID : string;
FType_ID : string;
FIsDown : boolean ;
FTmpDownPos : TPointF ;
FLastPosition : TPointF;
FLastDIstance : integer ;
FOriginalWidth : Single ;
FOriginalHeight : Single ;
FOriginalX : single ;
FOriginalY : Single ;
FZoomWidth : Single ;
FZoomHeight : Single ;
LImage: TImage;
Ratio:single;
NowWidth:Single ;
NowHeight:Single ;
ZoomState:Boolean;
PanState:Boolean;
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Single);
procedure FormClose(Sender:Tobject);
{ Private declarations }
public
class procedure ShowFrm(ASendData:TDictionary<integer, TSelectPictureInfo>;ANumber:
integer;AMSCarrierObject_ID:string='';AType_ID:string=''); //缩略图字典;第几张图;原图载体id;原图类型id
procedure PreviewImage;
{ Public declarations }
end;
var
FrmPreviewImage: TFrmPreviewImage;
implementation
{$R *.fmx}
{ TForm1 }
procedure TFrmPreviewImage.FormClose(Sender: Tobject);
begin
TDRForm.Create(self).Release;
end;
procedure TFrmPreviewImage.FormGesture(Sender: TObject;
const EventInfo: TGestureEventInfo; var Handled: Boolean);
var
LObj: IControl;
LImageCenter: TPointF;
Tan :single;
A,B :single;
begin
INHERITED;
if EventInfo.GestureID = igiZoom then//放大缩小手势
begin
ZoomState:=true;
LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
if LObj is TImage then
begin
if (not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags)) and
(not(TInteractiveGestureFlag.gfEnd in EventInfo.Flags)) then
begin
{ zoom the image }
LImage := TImage(LObj.GetObject);
LImageCenter := LImage.Position.Point + PointF(LImage.Width / 2,
LImage.Height / 2);
A:=LImage.Width;
if LImage.Width<FOriginalWidth then
begin
LImage.Width := LImage.Width + (power(2,(EventInfo.Distance - FLastDistance)/10)-1)*10; // 控制u图片缩小速度和大小,滑的越大变化越小,后面变化无限小
LImage.Height := LImage.Height + (power(2,(EventInfo.Distance - FLastDistance)/10)-1)*10;//
end
else
begin
LImage.Width := LImage.Width + 2*(EventInfo.Distance - FLastDistance);
LImage.Height := LImage.Height + 2*(EventInfo.Distance - FLastDistance);
end;
LImage.Position.X := LImageCenter.X - LImage.Width / 2;
LImage.Position.Y := LImageCenter.Y - LImage.Height / 2;
// LImage.Position.Y :=(1-LImage.Width/NowWidth)*EventInfo.Location.Y -LImage.Position.y ;
// LImage.Position.x :=(1-LImage.Width/NowWidth)*EventInfo.Location.x -LImage.Position.x ;
// LImage.Position.Y :=(1-LImage.Width/a)*(EventInfo.Location.Y-LImage.Position.y)-LImage.Position.y ;
// LImage.Position.x :=(1-LImage.Width/a)*(EventInfo.Location.x-LImage.Position.X)-LImage.Position.X ;
// showmessage(EventInfo.Location.x.ToString+','+LImage.Position.x.ToString);
FZoomWidth := LImage.Width ;
FZoomheight := LImage.height ;
end;
FLastDistance := EventInfo.Distance;
end;
exit;
end;
//平移
if EventInfo.GestureID = igiPan then
begin
PanState:=true;
LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
if LObj is TImage then
begin
A:=LImage.Height;
if not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags) then
begin
LImage := TImage(LObj.GetObject);
// if LImage.Width>self.Width then
if True then
begin
// (power(2,(EventInfo.Location.X - FLastPosition.X)/10)-1)*10
//showmessage(EventInfo.Location.X.ToString +','+FLastPosition.X.ToString);
if (0.66*self.Width-LImage.Width<LImage.Position.x) and (LImage.Position.x<0.33*self.Width) then
begin
LImage.Position.X := LImage.Position.X +( EventInfo.Location.X - FLastPosition.X);
// end
// else
// if LImage.Position.x>=0 then
// begin
// showmessage((1/(power((EventInfo.Location.X - FLastPosition.X),2)+1)).tostring;//尝试控制速度
// showmessage((EventInfo.Location.X - FLastPosition.X).ToString);
// LImage.Position.X := LImage.Position.X +1/(power(2,((EventInfo.Location.X - FLastPosition.X)/10)-1)*10);
// showmessage((1/(power(2,(EventInfo.Location.X - FLastPosition.X))+1)).tostring);
end
else
if LImage.Position.x>0.33*self.Width then //右移滑动图片
begin
if TabEnlargeImage.ActiveTab<>TabEnlargeImage.Tabs[0] then
begin
//TabControl1.ActiveTab:=TabControl1.Tabs[TabControl1.TabIndex-1];
TabEnlargeImage.SetActiveTabWithTransition(TabEnlargeImage.Tabs[TabEnlargeImage.Tabindex-1],TTabTransition.Slide,
TTabTransitionDirection.Reversed);
handled:=true;
end;
end
else
if 0.66*self.Width-LImage.Width>LImage.Position.x then //左移滑动图片
begin
if TabEnlargeImage.ActiveTab<>TabEnlargeImage.Tabs[TabEnlargeImage.tabcount-1] then
begin
//TabControl1.ActiveTab:=TabControl1.Tabs[TabControl1.TabIndex+1];
TabEnlargeImage.SetActiveTabWithTransition(TabEnlargeImage.Tabs[TabEnlargeImage.Tabindex+1],TTabTransition.Slide ,
TTabTransitionDirection.Normal);
handled:=true;
end;
end;
end;
end;
//Set the Y coordinate.
if (LImage.Width*Ratio)>self.Height then
begin
// if (0.66*self.Height -LImage.Height <LImage.Position.y) and (LImage.Position.Y<0.33*self.Height) then
LImage.Position.Y := LImage.Position.Y + (EventInfo.Location.Y - FLastPosition.Y);
end;
end;
FZoomWidth := LImage.Width ;
FZoomheight := LImage.height ;
FLastPosition := EventInfo.Location;
exit;
end;
case EventInfo.GestureID of
sgiLeft:
begin
if TabEnlargeImage.ActiveTab<>TabEnlargeImage.Tabs[TabEnlargeImage.tabcount-1] then
begin
//TabControl1.ActiveTab:=TabControl1.Tabs[TabControl1.TabIndex+1];
TabEnlargeImage.SetActiveTabWithTransition(TabEnlargeImage.Tabs[TabEnlargeImage.Tabindex+1],TTabTransition.Slide ,
TTabTransitionDirection.Normal);
handled:=true;
end;
end;
sgiRight:
begin
if TabEnlargeImage.ActiveTab<>TabEnlargeImage.Tabs[0] then
begin
//TabControl1.ActiveTab:=TabControl1.Tabs[TabControl1.TabIndex-1];
TabEnlargeImage.SetActiveTabWithTransition(TabEnlargeImage.Tabs[TabEnlargeImage.Tabindex-1],TTabTransition.Slide,
TTabTransitionDirection.Reversed);
handled:=true;
end;
end;
end;
end;
procedure TFrmPreviewImage.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Single);
begin
//
end;
procedure TFrmPreviewImage.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Single);
begin
inherited;
// if Sender is Timage then
if FIsDown then
begin
FIsDown := false;
if FTmpDownPos.X = x then
TDRForm.Create(self).Release ;
end;
if LImage.Position.X > 0 then //让图片弹回左边框
begin
LImage.Position.X := 0;
end;
if LImage.Position.X-self.Width+LImage.Width <0 then //让图片弹回右边框
begin
LImage.Position.X :=self.Width-LImage.Width;
end;
if (LImage.Width*Ratio)>self.Height then //图片bitmap超过屏幕高上下滑
begin
if (LImage.Height-Ratio*LImage.Width)/2+LImage.Position.y>0 then //上边框
begin
LImage.Position.y := -(LImage.Height-Ratio*LImage.Width)/2;
end;
if LImage.Position.y+(LImage.Height-(LImage.Height-Ratio*LImage.Width)/2)<self.Height then //下边框
begin
LImage.Position.y :=self.Height -(LImage.Height-(LImage.Height-Ratio*LImage.Width)/2);
end;
end
else
if (LImage.Width*Ratio)<self.Height then
begin
LImage.Position.y := -(LImage.Height-FOriginalHeight)/2;
end;
if FZoomWidth<FOriginalWidth then //缩的太小就返回原来大小
begin
LImage.Position.X := FOriginalX;
LImage.Position.Y := FOriginalY ;
LImage.Width := FOriginalWidth ;
LImage.Height := FOriginalHeight ;
end;
if FZoomWidth>3.1*FOriginalWidth then //最大放大3倍
begin
LImage.Width := 3*FOriginalWidth ;
LImage.Height := 3*FOriginalHeight ;
LImage.Position.X :=FOriginalX-(LImage.Width-FOriginalWidth)/2;
LImage.Position.y :=FOriginaly-(LImage.Height-FOriginalHeight)/2;
end;
FZoomWidth:=LImage.Width;
// showmessage(LImage.Height.ToString+','+LImage.Bitmap.Height.ToString+','+Ratio.ToString);
NowWidth:=LImage.Width;
NowHeight:=LImage.Height;
ZoomState:=false;
if PanState=true then
begin
// if LImage.Width<=self.Width then
// begin
//
// if TabEnlargeImage.ActiveTab<>TabEnlargeImage.Tabs[TabEnlargeImage.tabcount-1] then
// begin
//
// //TabControl1.ActiveTab:=TabControl1.Tabs[TabControl1.TabIndex+1];
// TabEnlargeImage.SetActiveTabWithTransition(TabEnlargeImage.Tabs[TabEnlargeImage.Tabindex+1],TTabTransition.Slide ,
// TTabTransitionDirection.Normal);
//
// end;
// if TabEnlargeImage.ActiveTab<>TabEnlargeImage.Tabs[0] then
// begin
// //TabControl1.ActiveTab:=TabControl1.Tabs[TabControl1.TabIndex-1];
// TabEnlargeImage.SetActiveTabWithTransition(TabEnlargeImage.Tabs[TabEnlargeImage.Tabindex-1],TTabTransition.Slide,
// TTabTransitionDirection.Reversed);
//
// end;
// end;
end;
end;
procedure TFrmPreviewImage.PreviewImage;
var
Bitmaplist: Tlist<FMX.Graphics.TBitmap>;
GuIDlist : Tstringlist;
Number : string;
AFrame : TFrame ;
AItem : TTabItem;
AImage : TImage;
i : integer;
ATag : integer ;
Err : Boolean;
MSCarrierObject_ID,Type_ID,errmsg:string;
ADataInfo : TSelectPictureInfo ;
begin
if TabEnlargeImage.TabCount >0 then
begin
for I :=0 to TabEnlargeImage.TabCount - 1 do
begin
TabEnlargeImage.Delete(0);
end;
end;
Bitmaplist:= Tlist<FMX.Graphics.TBitmap>.create;
GuIDlist :=Tstringlist.Create;
for I := 0 to FSendData.Count-1 do
begin
for ADataInfo in FSendData.Values do
begin
if ADataInfo.IndexTag=I then
BitmapList.Add(ADataInfo.Bitmap);
end;
end;
// AStr := copy(AStr,1,length(AStr)-1);
// Err :=TBitmapManager.DownLoadMultipleBitMap(MSCarrierObject_ID,
// Type_ID,BitmapList,GuIDlist,errmsg);
begin
for I := 0 to Bitmaplist.Count - 1 do
begin
AItem := TTabItem.Create(nil) ;
AItem.Text :='';
AItem.Name := 'TabItem'+inttostr(i+1);
AItem.Parent := TabEnlargeImage ;
AItem.Width := self.Width ;
AItem.HitTest:=true;
AImage :=TImage.Create(nil);
AImage.Align :=TAlignLayOut.Center;
AImage.Parent:=AItem;
AImage.Parent:=AItem;
AImage.Width:=self.Width;
aimage.Height:=self.Height;
AImage.MarginWrapMode:=TImageWrapMode.Stretch;
AImage.Bitmap.Assign(Bitmaplist[i]);
AImage.HitTest:=true;
// AImage.Touch.GestureManager:=GestureManager2;
// AImage.Touch.InteractiveGestures:=[TInteractiveGesture.Zoom,TInteractiveGesture.Pan,TInteractiveGesture.Rotate,
// TInteractiveGesture.TwoFingerTap,TInteractiveGesture.PressAndTap,TInteractiveGesture.LongTap,TInteractiveGesture.DoubleTap];
// AImage.OnGesture:= FormGesture;
AImage.OnMouseUp:= FormMouseUp;
Aimage.OnMouseDown:=TabEnlargeImageMouseDown;
//Aimage.OnClick:=FormClose;
FOriginalWidth := AImage.Width ;
FOriginalHeight := AImage.Height ;
NowWidth := AImage.Width ;
NowHeight := AImage.Height ;
FOriginalX := AImage.Position.X ;
FOriginalY := AImage.Position.Y ;
//Ratio:= AImage.Bitmap.Height/AImage.Height;
//image放大后,bitmap放大比例跟image不一样,只能让bitmap显示宽等于屏宽 ,放大后Ratio*image.width=bitmap.height.
Ratio:= AImage.Bitmap.Height/AImage.Bitmap.Width;
LImage:= AImage;
end;
TabEnlargeImage.ActiveTab := TabEnlargeImage.Tabs[FNumber] ;
end;
end;
class procedure TFrmPreviewImage.ShowFrm(ASendData:TDictionary<integer, TSelectPictureInfo>;ANumber:
integer;AMSCarrierObject_ID:string='';AType_ID:string=''); //缩略图字典;第几张图;原图载体id;原图类型id
var
DrFrmFind: TFrmPreviewImage;
begin
DrFrmFind := (TDRForm.Create(TFrmPreviewImage).TCCF as TFrmPreviewImage);
with DrFrmFind do
begin
FSendData := TDictionary<integer, TSelectPictureInfo>.Create ;
FSendData := ASendData;
FNumber := ANumber;
FMSCarrierObject_ID := AMSCarrierObject_ID;
FType_ID := AType_ID;
show;
PreviewImage;
end;
end;
procedure TFrmPreviewImage.TabEnlargeImageGesture(Sender: TObject;
const EventInfo: TGestureEventInfo; var Handled: Boolean);
begin
case EventInfo.GestureID of
sgiLeft:
begin
if TabEnlargeImage.ActiveTab<>TabEnlargeImage.Tabs[TabEnlargeImage.tabcount-1] then
begin
//TabControl1.ActiveTab:=TabControl1.Tabs[TabControl1.TabIndex+1];
TabEnlargeImage.SetActiveTabWithTransition(TabEnlargeImage.Tabs[TabEnlargeImage.Tabindex+1],TTabTransition.Slide ,
TTabTransitionDirection.Normal);
handled:=true;
end;
end;
sgiRight:
begin
if TabEnlargeImage.ActiveTab<>TabEnlargeImage.Tabs[0] then
begin
//TabControl1.ActiveTab:=TabControl1.Tabs[TabControl1.TabIndex-1];
TabEnlargeImage.SetActiveTabWithTransition(TabEnlargeImage.Tabs[TabEnlargeImage.Tabindex-1],TTabTransition.Slide,
TTabTransitionDirection.Reversed);
handled:=true;
end;
end;
end;
end;
procedure TFrmPreviewImage.TabEnlargeImageMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
inherited;
FTmpDownPos := TPointF.Create(x,y); //
FIsDown := true ;
end;
end.