我正在尝试使用来自用户的触摸来翻译已旋转和/或缩放的UIView。我尝试用用户输入翻译它:
- (void)handleObjectMove:(UIPanGestureRecognizer *)recognizer
{
static CGPoint lastPoint;
UIView *moveView = [recognizer view];
CGPoint newCoord = [recognizer locationInView:playArea];
// Check if this is the first touch
if( [recognizer state]==UIGestureRecognizerStateBegan )
{
// Store the initial touch so when we change positions we do not snap
lastPoint = newCoord;
}
// Create the frame offsets to use our finger position in the view.
float dX = newCoord.x;
float dY = newCoord.y;
dX-=lastPoint.x;
dY-=lastPoint.y;
// Figure out the translation based on how we are scaled
CGAffineTransform transform = [moveView transform];
CGFloat xScale = transform.a;
CGFloat yScale = transform.d;
dX/=xScale;
dY/=yScale;
lastPoint = newCoord;
[moveView setTransform:CGAffineTransformTranslate( transform, dX, dY )];
[recognizer setTranslation:CGPointZero inView:playArea];
}
但是当我触摸并移动视图时,它会以各种奇怪的方式进行翻译。我可以使用旋转值来应用某种公式来正确翻译吗?
答案 0 :(得分:2)
我发现必须使用最少量数学的最佳解决方案是分别存储原始平移,旋转和缩放值,并在更改时重做变换。我的解决方案是使用以下属性为UIView创建子类:
@property (nonatomic) CGPoint translation;
@property (nonatomic) CGFloat rotation;
@property (nonatomic) CGPoint scaling;
以下功能:
- (void)rotationDelta:(CGFloat)delta
{
[self setRotation:[self rotation]+delta];
}
- (void)scalingDelta:(CGPoint)delta
{
[self setScaling:
(CGPoint){ [self scaling].x*delta.x, [self scaling].y*delta.y }];
}
- (void)translationDelta:(CGPoint)delta
{
[self setTranslation:
(CGPoint){ [self translation].x+delta.x, [self translation].y+delta.y }];
}
- (void)transformMe
{
// Start with the translation
CGAffineTransform transform = CGAffineTransformMakeTranslation( [self translation].x, [self translation].y );
// Apply scaling
transform = CGAffineTransformScale( transform, [self scaling].x, [self scaling].y );
// Apply rotation
transform = CGAffineTransformRotate( transform, [self rotation] );
[self setTransform:transform];
}
- (void)setScaling:(CGPoint)newScaling
{
scaling = newScaling;
[self transformMe];
}
- (void)setRotation:(CGFloat)newRotation
{
rotation = newRotation;
[self transformMe];
}
- (void)setTranslation:(CGPoint)newTranslation
{
translation = newTranslation;
[self transformMe];
}
并在处理程序中使用以下内容:
- (void)handleObjectPinch:(UIPinchGestureRecognizer *)recognizer
{
if( [recognizer state] == UIGestureRecognizerStateEnded
|| [recognizer state] == UIGestureRecognizerStateChanged )
{
// Get my stuff
if( !selectedView )
return;
SelectableImageView *view = selectedView;
CGFloat scaleDelta = [recognizer scale];
[view scalingDelta:(CGPoint){ scaleDelta, scaleDelta }];
[recognizer setScale:1.0];
}
}
- (void)handleObjectMove:(UIPanGestureRecognizer *)recognizer
{
static CGPoint lastPoint;
SelectableImageView *moveView = (SelectableImageView *)[recognizer view];
CGPoint newCoord = [recognizer locationInView:playArea];
// Check if this is the first touch
if( [recognizer state]==UIGestureRecognizerStateBegan )
{
// Store the initial touch so when we change positions we do not snap
lastPoint = newCoord;
}
// Create the frame offsets to use our finger position in the view.
float dX = newCoord.x;
float dY = newCoord.y;
dX-=lastPoint.x;
dY-=lastPoint.y;
lastPoint = newCoord;
[moveView translationDelta:(CGPoint){ dX, dY }];
[recognizer setTranslation:CGPointZero inView:playArea];
}
- (void)handleRotation:(UIRotationGestureRecognizer *)recognizer
{
if( [recognizer state] == UIGestureRecognizerStateEnded
|| [recognizer state] == UIGestureRecognizerStateChanged )
{
if( !selectedView )
return;
SelectableImageView *view = selectedView;
CGFloat rotation = [recognizer rotation];
[view rotationDelta:rotation];
[recognizer setRotation:0.0];
}
}
答案 1 :(得分:0)
尝试直接更改moveView.center而不是Set(x,y)或“CGAffineTransformTranslate”
答案 2 :(得分:0)
这是可转换 UIView 的 Swift 4/5 版本
class TransformableImageView: UIView{
var translation:CGPoint = CGPoint(x:0,y:0)
var scale:CGPoint = CGPoint(x:1, y:1)
var rotation:CGFloat = 0
override init (frame : CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func rotationDelta(delta:CGFloat) {
rotation = rotation + delta
}
func scaleDelta(delta:CGPoint){
scale = CGPoint(x: scale.x*delta.x, y: scale.y * delta.y)
}
func translationDelta(delta:CGPoint){
translation = CGPoint(x: translation.x+delta.x, y: translation.y + delta.y)
}
func transform(){
self.transform = CGAffineTransform.identity.translatedBy(x: translation.x, y: translation.y).scaledBy(x: scale.x, y: scale.y ).rotated(by: rotation )
}
}
答案 3 :(得分:-1)
我离开这里,因为我也遇到了同样的问题。以下是如何在swift 2中执行此操作:
将您的俯视图作为子视图添加到底部视图中:
self.view.addSubview(topView)
然后添加PanGesture识别器以继续触摸:
//Add PanGestureRecognizer to move
let panMoveGesture = UIPanGestureRecognizer(target: self, action: #selector(YourViewController.moveViewPanGesture(_:)))
topView.addGestureRecognizer(panMoveGesture)
移动的功能:
//Move function
func moveViewPanGesture(recognizer:UIPanGestureRecognizer)
{
if recognizer.state == .Changed {
var center = recognizer.view!.center
let translation = recognizer.translationInView(recognizer.view?.superview)
center = CGPoint(x:center.x + translation.x,
y:center.y + translation.y)
recognizer.view!.center = center
recognizer.setTranslation(CGPoint.zero, inView: recognizer.view)
}
}
基本上,您需要根据底视图翻译视图,而视图是超视图本身。像这样:recognizer.view?.superview
或者,如果您还旋转底部视图,则可以添加一个不会有任何转换的视图,并将底部视图添加到不转换视图(非常底部视图),并将顶视图相应地添加到底视图作为子视图。然后,您应该根据最底层视图翻译您的顶视图。