首页 >> 大全

结合UIImageView实现图片的移动和缩放

2023-12-13 大全 29 作者:考证青年

因为种种原因,需要在应用中实现图片查看功能,由于屏幕支持多点触摸,于是是想到用“手势”来实现图片的实时缩放和移动。借鉴无所不在的网络资料之后,终于实现此一功能,过程如下。

为方便大家下载,示例代码已上传到资源:

一、首先实现原图显示(不缩放)

新建类,继承。用于加载一个。它有两个主要的成员,一个对象用于指定一个内存图片,一个控件用于显示图片。

@ : {

* ;

* ;

-(void):(*);

@end

@

-(id):()frame{

if (self=[:frame]) {

=[[]init];

[:];

// 使图片视图支持交互和多点触摸

[:YES];

[:YES];

;

-(void){

=nil;

=nil;

[];

-(void):( *){

=[[]:.];

[:];

[:(0, 0, .size.width, .size.)];

// [ ];

@end

最主要的就是方法。

的使用很简单。在中构造一个,然后用一个加载了图片文件的对象设置其image成员:

* image=[:@"df.jpg"];

* [[loc]:

(0, 44, 320, 436)];

[:image];

由于在这里我们没有对图片进行任何的缩放处理,对于小图片会位于屏幕的左上角,并在其他地方留下空白;对于尺寸大于屏幕的图片,则图片不能完全显示:

一、识别手势(单点触摸与多点触摸)

要想识别手势(),必须响应4个手势的通知方法(参考“开发基础教程”第13章的内容):

,,和。

首先,我们先来考虑单点触摸情况,这比较简单一些。在单点触摸情况下,移动手指,中的图片可以被拖动,这样,对于比较大的图片,我们可以通过拖动来浏览图片的各个部分,当然,对于能一次显示下全部的图片就不需要拖动了。

修改类,在.h中增加一些声明:

@ : {

* ;

* ;

oint;//手势开始时起点

实现缩放效果的属性__移动端缩放事件

,;//移动时x,y方向上的偏移量

,;//现在截取的图片内容的原点坐标

-(void):(*);

-(void):()x ToY:()y;

@end

然后实现和方法。

方法比较简单,记录下手指第一次触摸的位置。因为任何一个拖动都必然有一个起点和终点。

-(void):(NSSet *) :( *)event{

*touch=[ ];

=[touch :self];

// NSLog(@"touch:%f,%f",.x,.y);

然后是手指移动后回调的方法:

-(void):(NSSet *) :( *)event{

* touch=[ ];

=[touch :self];

//分别计算x,和y方向上的移动

=.x-.x;

=.y-.y;

//只要在任一方向上移动的距离超过,判定手势有效

if(fabsf()>= ||fabsf()>=){

[::];

.x=.x;

.y=.y;

在这里我们做了一个简单的判断,只有手指移动了超过一定像素(常量)后,才识别为拖动手势,并调用方法。在这个方法中,需要不断的更新手指移动的坐标,因为这是一个连续的过程。

-(void):()x ToY:()y{

//计算移动后的矩形框,原点x,y坐标,矩形宽高

destX,destY,destW,destH;

=destX=-x;

=destY=-y;

destW=self.frame.size.width;

destH=self.frame.size.;

if (.size.) {//右边界越界处理

=destY=.size.-destH;

//创建矩形框为本fame

rect = (destX, destY,

self.frame.size.width, self.frame.size.);

.image=[age:([], rect)];

在这个方法中,我们采用了一种特殊的处理方式:截取大图片的一部分,并将截取部分显示在里。我这样做的理由,是因为这是最简单、最容易的实现方式。我参考过网上的几种实现方式,发现基本上都需要使用,并且实现起来要复杂得多。最终从闭路电视监控系统中得到了启发(想象一下,安保人员通过移动鼠标控制镜头移动的场景)。

我们设计了一个矩形框,用它作为模拟的镜头:

;//设置镜头的大小

同时还设计了一个全局变量用于记录图片缩放过程中的缩放倍率:

;//缩放比例

当跟踪到手指移动时,让“镜头”做反向运动(为什么是反向运动?因为我们模拟的是“拖动”效果,而不是“跟踪”效果,二者是恰恰相反的)。并通过 age: 方法,将镜头中的图像捕捉到中。

这样,移动操作实际上转换成了计算矩形框的位置。当然,我们也要做好边界判断,否则当矩形框超出图片原来的范围时,会发生扭曲缩放的现象。

接下来看怎样识别多点触摸。识别单点触摸和多点触摸其实非常简单,判断的参数的count属性即可:

-(void):(NSSet *) :( *)event{

if ([ count]==2) {//识别两点触摸,并记录两点间距离

* =[ ];

=[:[[ :0] :self]

:[[ :1]:self]];

} ([ count]==1){

*touch=[ ];

=[:self];

在上面的方法中,我们根据的count判断是否是单点触摸并进行分别的处理。对于2点触摸,我们记录了两指间的距离并记录在全局的变量中。方法是一个简单函数,使用中学中学过的3角函数计算2点间距离:

-():()first :()two{//计算两点之间的距离

float x = first.x - two.x;

float y = first.y - two.y;

(x * x + y * y);

在两点触摸中,需要识别2个手势:外向捏合、内向捏合。通常前者使图像放大,而后者可使图像缩小。

在方法中,这样处理:

if ([ count]==2) {

* =[ ];

=[:[[ :0] :self]

:[[ :1]:self]];

//如果先触摸一根手指,再触摸另一根手指,则触发方法而不是方法

//此时应该是0,我们要正确设置它的值为当前检测到的距离,否则可能导致0除错误

if (==0) {

=;

if (fabsf(-)>=) {//两指间移动距离超过,识别为手势“捏合”

s=/;//计算缩放比例

[:s];

}([ count]==1){

⋯⋯(省略了部分代码)

先简单判断了是否为有效捏合(我们为此定义了一个常量),如果是,则计算手指有效移动长度和手势开始时的两指间距的商,以此作为缩放比例。然后调用方法:

-(void):()x{

scale*=x;

//缩放限制:>=0.1,.size.width){

width=.size.width;

if (>.size.) {

=.size.;

//计算镜头移动的位置(等比缩放)

x=..x-point.x/scale;

y=..y-point.y/scale;

//左边界越界处理

x=(.size.)?.size.-:y;

//镜头等比缩放

=(x, y, width, );

这些代码跟原来方法中的代码有些许的不同,主要是增加了对scale变量的引入,因为在缩放模式下,镜头的移动都是被scale系数缩放过的。通代码中的注释,我们不难理解整个代码。

这样,大图片经过“捏合”操作可以在屏幕上完全显示出来(上面原来基本看不清楚的第2张图片现在是一台苹果电脑):

当然,把小图片“捏合”放大成大图片也是可以的。此外通过手指的移动,能查看图片的不同部分。

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了