- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一个 ImageView ,它响应捏合、旋转和平移手势。我希望图像的收缩和旋转是相对于放置在屏幕中间的 anchor 完成的,就像使用 Xcode iPhone 模拟器通过按下选项键完成的那样。如果图像的中心可能被缩放和平移到不同的位置,我如何将 anchor 放置在屏幕中间?
这是我的缩放和旋转手势功能:
@IBAction func pinchGesture(_ gestureRecognizer: UIPinchGestureRecognizer) {
// Move the achor point of the view's layer to the touch point
// so that scaling the view and the layer becames simpler.
self.adjustAnchorPoint(gestureRecognizer: gestureRecognizer)
// Scale the view by the current scale factor.
if(gestureRecognizer.state == .began) {
// Reset the last scale, necessary if there are multiple objects with different scales
lastScale = gestureRecognizer.scale
}
if (gestureRecognizer.state == .began || gestureRecognizer.state == .changed) {
let currentScale = gestureRecognizer.view!.layer.value(forKeyPath:"transform.scale")! as! CGFloat
// Constants to adjust the max/min values of zoom
let kMaxScale:CGFloat = 15.0
let kMinScale:CGFloat = 1.0
var newScale = 1 - (lastScale - gestureRecognizer.scale)
newScale = min(newScale, kMaxScale / currentScale)
newScale = max(newScale, kMinScale / currentScale)
let transform = (gestureRecognizer.view?.transform)!.scaledBy(x: newScale, y: newScale);
gestureRecognizer.view?.transform = transform
lastScale = gestureRecognizer.scale // Store the previous scale factor for the next pinch gesture call
scale = currentScale // Save current scale for later use
}
}
@IBAction func rotationGesture(_ gestureRecognizer: UIRotationGestureRecognizer) {
// Move the achor point of the view's layer to the center of the
// user's two fingers. This creates a more natural looking rotation.
self.adjustAnchorPoint(gestureRecognizer: gestureRecognizer)
// Apply the rotation to the view's transform.
if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
gestureRecognizer.view?.transform = (gestureRecognizer.view?.transform.rotated(by: gestureRecognizer.rotation))!
// Set the rotation to 0 to avoid compouding the
// rotation in the view's transform.
angle += gestureRecognizer.rotation // Save rotation angle for later use
gestureRecognizer.rotation = 0.0
}
}
func adjustAnchorPoint(gestureRecognizer : UIGestureRecognizer) {
if gestureRecognizer.state == .began {
let view = gestureRecognizer.view
let locationInView = gestureRecognizer.location(in: view)
let locationInSuperview = gestureRecognizer.location(in: view?.superview)
// Move the anchor point to the the touch point and change the position of the view
view?.layer.anchorPoint = CGPoint(x: (locationInView.x / (view?.bounds.size.width)!), y: (locationInView.y / (view?.bounds.size.height)!))
view?.center = locationInSuperview
}
}
编辑
我发现人们并不急于参与其中。让我通过分享我在过去几天取得的一些进展来提供帮助。
首先,我编写了一个函数 centerAnchorPoint
,它可以将图像的 anchor 正确地放置在屏幕的中心,而不管该 anchor 之前位于何处。但是,不得缩放或旋转图像才能正常工作。
func setAnchorPoint(_ anchorPoint: CGPoint, forView view: UIView) {
var newPoint = CGPoint(x: view.bounds.size.width * anchorPoint.x, y: view.bounds.size.height * anchorPoint.y)
var oldPoint = CGPoint(x: view.bounds.size.width * view.layer.anchorPoint.x, y: view.bounds.size.height * view.layer.anchorPoint.y)
newPoint = newPoint.applying(view.transform)
oldPoint = oldPoint.applying(view.transform)
var position = view.layer.position
position.x -= oldPoint.x
position.x += newPoint.x
position.y -= oldPoint.y
position.y += newPoint.y
view.layer.position = position
view.layer.anchorPoint = anchorPoint
}
func centerAnchorPoint(gestureRecognizer : UIGestureRecognizer) {
if gestureRecognizer.state == .ended {
view?.layer.anchorPoint = CGPoint(x: (photo.bounds.midX / (view?.bounds.size.width)!), y: (photo.bounds.midY / (view?.bounds.size.height)!))
}
}
func centerAnchorPoint() {
// Position of the current anchor point
let currentPosition = photo.layer.anchorPoint
self.setAnchorPoint(CGPoint(x: 0.5, y: 0.5), forView: photo)
// Center of the image
let imageCenter = CGPoint(x: photo.center.x, y: photo.center.y)
self.setAnchorPoint(currentPosition, forView: photo)
// Center of the screen
let screenCenter = CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY)
// Distance between the centers
let distanceX = screenCenter.x - imageCenter.x
let distanceY = screenCenter.y - imageCenter.y
// Find new anchor point
let newAnchorPoint = CGPoint(x: (imageCenter.x+2*distanceX)/(UIScreen.main.bounds.size.width), y: (imageCenter.y+2*distanceY)/(UIScreen.main.bounds.size.height))
//photo.layer.anchorPoint = newAnchorPoint
self.setAnchorPoint(newAnchorPoint, forView: photo)
let dotPath = UIBezierPath(ovalIn: CGRect(x: photo.layer.position.x-2.5, y: photo.layer.position.y-2.5, width: 5, height: 5))
layer.path = dotPath.cgPath
}
函数 setAchorPoint
用于在不移动图像的情况下将 anchor 设置到新位置。
然后我更新了 panGesture
函数,在它的末尾插入:
if gestureRecognizer.state == .ended {
self.centerAnchorPoint()
}
编辑 2
好的,所以我将尝试简单地解释上面的代码。
我正在做的是:
newAnchorPointX = (imageCenter.x-distanceX)/screenWidth + distanceX/screenWidth
然后对 y 位置做同样的事情。
setAnchorPoint
函数将此点设置为新的 anchor 而不移动照片正如我所说,如果图像未缩放,这会很好用。如果是,则 anchor 不会停留在中心。
奇怪的是 distanceX 或 distanceY 并不完全取决于比例值,所以像这样的东西不太管用:
newAnchorPointX = (imageCenter.x-distanceX)/screenWidth + distanceX/(scaleValue*screenWidth)
编辑 3
我想出了缩放比例。看起来正确的比例因子必须是:
scaleFactor = photo.frame.size.width/photo.layer.bounds.size.width
我用它代替 scaleValue
并且效果非常好。
这样平移和缩放就完成了。剩下的就是轮换了,但看起来是最难的。
我首先想到的是将旋转矩阵应用于 X 和 Y 方向的增量,如下所示:
let incrementX = (distanceX)/(screenWidth)
let incrementY = (distanceY)/(screenHeight)
// Applying rotation matrix
let incX = incrementX*cos(angle)+incrementY*sin(angle)
let incY = -incrementX*sin(angle)+incrementY*cos(angle)
// Find new anchor point
let newAnchorPoint = CGPoint(x: 0.5+incX, y: 0.5+incY)
但是这不起作用。
最佳答案
由于问题大部分在编辑中得到了回答,我不想重复太多。
大致上我对原始问题中发布的代码所做的更改:
adjustAnchorPoint
函数的调用。 将这段代码放在平移手势函数中,使 anchor 在平移照片后更新其位置:
如果 gestureRecognizer.state == .ended { self.centerAnchorPoint()
更新了用于旋转的 centerAnchorPoint
函数。
一个完整的 centerAnchorPoint
函数(包括旋转):
func centerAnchorPoint() {
// Scale factor
photo.transform = photo.transform.rotated(by: -angle)
let curScale = photo.frame.size.width / photo.layer.bounds.size.width
photo.transform = photo.transform.rotated(by: angle)
// Position of the current anchor point
let currentPosition = photo.layer.anchorPoint
self.setAnchorPoint(CGPoint(x: 0.5, y: 0.5), forView: photo)
// Center of the image
let imageCenter = CGPoint(x: photo.center.x, y: photo.center.y)
self.setAnchorPoint(currentPosition, forView: photo)
// Center of the screen
let screenCenter = CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY)
// Distance between the centers
let distanceX = screenCenter.x - imageCenter.x
let distanceY = screenCenter.y - imageCenter.y
// Apply rotational matrix to the distances
let distX = distanceX*cos(angle)+distanceY*sin(angle)
let distY = -distanceX*sin(angle)+distanceY*cos(angle)
let incrementX = (distX)/(curScale*UIScreen.main.bounds.size.width)
let incrementY = (distY)/(curScale*UIScreen.main.bounds.size.height)
// Find new anchor point
let newAnchorPoint = CGPoint(x: 0.5+incrementX, y: 0.5+incrementY)
self.setAnchorPoint(newAnchorPoint, forView: photo)
}
这里要注意的关键是旋转矩阵必须应用于 distanceX 和 distanceY。比例因子也会更新以在整个旋转过程中保持不变。
关于ios - 做手势时将 anchor 放在屏幕中央,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45809994/
我当前项目中的许多类都有几个只能从类本身内部调用的属性和方法。此外,根据类(class)的当前状态,它们可能会扰乱类(class)的工作。 目前,所有这些接口(interface)都在 .h 文件的主
我想使用ngbTabSet将nav-pills in card-header 和tab-content in card-body。但我不知道该怎么做。 这是我尝试实现的示例(使用 bootstrap.
我正在浏览文档以查找如何允许放置在停靠栏图标上。据我所知,建议您使用 LSItemContentTypes,因为 CFBundleTypeOSTypes 已弃用。但是,我无法让 LSItemConte
我正在尝试在书签中使用 jquery UI 作为 slider 。并且 jquery ui 要求在普通 jquery 文件之后包含该文件。 所以到目前为止我所尝试的只是将脚本附加到 header ,同
您好,我尝试了广泛的谷歌搜索,但似乎没有任何帮助。 这是我的场景: 公司 Logo 存储在外部域/网址(矩形)中。 带有谷歌地图的 Ionic 应用程序,将这些 Logo 作为标记放置在 map 上。
我今天在阅读我的一些 C# 代码时发现了这一行: if (ProgenyList.ItemContainerGenerator.Status != System.Windows.Controls.Pr
我刚遇到this question在 Go FAQ 中,它让我想起了困扰我一段时间的事情。不幸的是,我真的不明白答案是什么。 似乎几乎所有非 C 类语言都将类型放在变量名之后,如下所示: var :
这是有效的 HTML 吗? 最佳答案 作为元素可以包含 phrasing content ,以及属于该组,则有效。 从语义上(并且具有一些常识),如果唯一的内容是 , 不;如果它同时包含文本和图像
这是有效的 HTML 吗? 最佳答案 作为元素可以包含 phrasing content ,以及属于该组,则有效。 从语义上(并且具有一些常识),如果唯一的内容是 , 不;如果它同时包含文本和图像
我有两本 T.Parr 写的关于 ANTLR 的书,我到处都看到美元符号和符号的引用。它也对我有用: term : IDENT -> { new TokenNode($IDENT) }; 或更复杂的东
我在实现段控制时遇到了一些问题。因为我希望它是一个固定的标题,所以当我滚动时我总是可以看到它,我已经在 - (UIView *)tableView:(UITableView *)tableView v
我有一个 20x36px (10x18pt) 的箭头图像,当我选择一个 UIImageView 时,将它拖到我的 View Controller 上然后设置图像,它总是模糊的。我只在我的项目中包含 @
How can I put background image when I hover a link Insert Bg in this a when hov
我需要在我的 .container 中添加(最新的第一个)新分区,但在 .controls (按钮)之后。可能吗? 注意:添加新的分区来保存按钮下方的前置控件对我来说不是一个选择。 HTML 需要保持
我是一名优秀的程序员,十分优秀!