मैं एक साधारण एक TScrollingWinControl
(और एक TScrollBox
से नकल कोड) एक TImage
नियंत्रण के साथ के आधार पर नियंत्रण बना रहा हूं। मुझे कुछ हद तक काम करने के लिए ज़ूमिंग मिल गई, लेकिन यह जरूरी नहीं कि एक केंद्रित बिंदु पर ज़ूम करें - स्क्रॉलबार केंद्र बिंदु को ध्यान में रखने के लिए तदनुसार नहीं बदलते हैं।किसी विशेष फोकस के लिए एक TScrollBox के अंदर एक TImage में ज़ूम इन/आउट करना?
मैं कहाँ करने के लिए ध्यान केंद्रित ज़ूम करने के लिए यह बताने के लिए इस पर नियंत्रण ZoomTo(const X, Y, ZoomBy: Integer);
बताने के लिए सक्षम होने के लिए करना चाहते हैं। तो जब यह ज़ूम करता है, तो मेरे द्वारा पारित निर्देशांक 'केंद्रित' रहेंगे। साथ ही, मुझे ZoomBy(const ZoomBy: Integer);
भी होना चाहिए जो इसे वर्तमान दृश्य में केंद्रित रखने के लिए कहता है।
उदाहरण के लिए, एक परिदृश्य होगा जहां माउस छवि के किसी विशेष बिंदु पर इंगित किया गया है, और माउस पकड़ने पर नियंत्रण और माउस स्क्रॉल करते समय, इसे माउस पॉइंटर पर ध्यान केंद्रित करना चाहिए। दूसरी तरफ, एक और परिदृश्य ज़ूम स्तर को समायोजित करने के लिए नियंत्रण को स्लाइड करेगा, इस स्थिति में इसे केवल वर्तमान दृश्य (आवश्यक रूप से छवि का केंद्र नहीं) केंद्रित करने की आवश्यकता है।
समस्या मेरी गणित इस बिंदु पर खो जाए है, और मुझे सही फार्मूला को समझ नहीं सकता इन स्क्रॉल बार समायोजित करने के लिए। मैंने गणना के कुछ अलग तरीकों की कोशिश की है, कुछ भी सही काम नहीं करता है।
यहाँ मेरी नियंत्रण का एक छीन संस्करण है। मैंने केवल प्रासंगिक सामग्री को हटा दिया है, मूल इकाई कोड की 600 से अधिक पंक्तियां हैं। नीचे सबसे महत्वपूर्ण प्रक्रिया SetZoom(const Value: Integer);
unit JD.Imaging;
interface
uses
Windows, Classes, SysUtils, Graphics, Jpeg, PngImage, Controls, Forms,
ExtCtrls, Messages;
type
TJDImageBox = class;
TJDImageZoomEvent = procedure(Sender: TObject; const Zoom: Integer) of object;
TJDImageBox = class(TScrollingWinControl)
private
FZoom: Integer; //level of zoom by percentage
FPicture: TImage; //displays image within scroll box
FOnZoom: TJDImageZoomEvent; //called when zoom occurs
FZoomBy: Integer; //amount to zoom by (in pixels)
procedure MouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
procedure SetZoom(const Value: Integer);
procedure SetZoomBy(const Value: Integer);
public
constructor Create(AOwner: TComponent); override;
published
property Zoom: Integer read FZoom write SetZoom;
property ZoomBy: Integer read FZoomBy write SetZoomBy;
property OnZoom: TJDImageZoomEvent read FOnZoom write FOnZoom;
end;
implementation
{ TJDImageBox }
constructor TJDImageBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
OnMouseWheel:= MouseWheel;
ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
csSetCaption, csDoubleClicks, csPannable, csGestures];
AutoScroll := True;
TabStop:= True;
VertScrollBar.Tracking:= True;
HorzScrollBar.Tracking:= True;
Width:= 100;
Height:= 100;
FPicture:= TImage.Create(nil);
FPicture.Parent:= Self;
FPicture.AutoSize:= False;
FPicture.Stretch:= True;
FPicture.Proportional:= True;
FPicture.Left:= 0;
FPicture.Top:= 0;
FPicture.Width:= 1;
FPicture.Height:= 1;
FPicture.Visible:= False;
FZoom:= 100;
FZoomBy:= 10;
end;
destructor TJDImageBox.Destroy;
begin
FImage.Free;
FPicture.Free;
inherited;
end;
procedure TJDImageBox.MouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
NewScrollPos: Integer;
begin
if ssCtrl in Shift then begin
if WheelDelta > 0 then
NewScrollPos := Zoom + 5
else
NewScrollPos:= Zoom - 5;
if NewScrollPos >= 5 then
Zoom:= NewScrollPos;
end else
if ssShift in Shift then begin
NewScrollPos := HorzScrollBar.Position - WheelDelta;
HorzScrollBar.Position := NewScrollPos;
end else begin
NewScrollPos := VertScrollBar.Position - WheelDelta;
VertScrollBar.Position := NewScrollPos;
end;
Handled := True;
end;
procedure TJDImageBox.SetZoom(const Value: Integer);
var
Perc: Single;
begin
FZoom := Value;
if FZoom < FZoomBy then
FZoom:= FZoomBy;
Perc:= FZoom/100;
//Resize picture to new zoom level
FPicture.Width:= Trunc(FImage.Width * Perc);
FPicture.Height:= Trunc(FImage.Height * Perc);
//Move scroll bars to properly position the center of the view
//This is where I don't know how to calculate the 'center'
//or by how much I need to move the scroll bars.
HorzScrollBar.Position:= HorzScrollBar.Position - (FZoomBy div 2);
VertScrollBar.Position:= VertScrollBar.Position - (FZoomBy div 2);
if assigned(FOnZoom) then
FOnZoom(Self, FZoom);
end;
procedure TJDImageBox.SetZoomBy(const Value: Integer);
begin
if FZoomBy <> Value then begin
FZoomBy := EnsureRange(Value, 1, 100);
Paint;
end;
end;
end.
मैं यह भी कल्पना नहीं कर सकता कि "ज़ूम टू" बिंदु क्या करेगा। मैं एक बिंदु पर नहीं, एक आयताकार "ज़ूम" होगा। मैं अनुमान नहीं लगा सकता कि आपकी कक्षा का कार्यान्वयन कैसा दिखता है, इसलिए मैं अनुमान नहीं लगा सकता कि आपको किस गणित की आवश्यकता है, न ही कोई और। –
@WarrenP मान लीजिए कि कई लोगों की एक तस्वीर प्रदर्शित होती है, माउस को किसी व्यक्ति के चेहरे के केंद्र में इंगित किया जाता है। जब उपयोगकर्ता नियंत्रण कुंजी रखता है और माउस व्हील को स्क्रॉल करता है, तो वह उस व्यक्ति के चेहरे पर ज़ूम करेगा, माउस पॉइंटर अभी भी तस्वीर की एक ही स्थिति में होगा। यही कारण है कि मैं 'प्वाइंट' पर ज़ूम कर रहा हूं, न कि 'Rect'। मुझे यकीन है कि मैं माउस घटनाओं को कैसे संभालने का प्रदर्शन करने के लिए उपर्युक्त सभी प्रासंगिक कोड शामिल करता हूं। –