首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何计算不接触UIView的随机CGPoint

如何计算不接触UIView的随机CGPoint
EN

Stack Overflow用户
提问于 2017-08-09 22:25:18
回答 7查看 1.3K关注 0票数 6

这是一个示例视图:

我想计算一个带有CGPoint的帧,在那里我可以在不接触任何现有卡片的情况下产生另一张卡片(UIView)。当然,这是可选的,因为视图中可能充满了卡片,因此没有空位。

这就是我在屏幕上看到任何卡片的方式,以及我的函数现在的样子:

代码语言:javascript
复制
func freeSpotCalculator() -> CGPoint?{
    var takenSpots = [CGPoint]()
    for card in playableCards{
        takenSpots.append(card.center)
    }

}

我不知道从哪里开始,也不知道如何计算屏幕上的随机CGPoint。随机帧与屏幕上的卡片具有相同的widthheight

EN

回答 7

Stack Overflow用户

发布于 2017-08-10 00:15:55

这种幼稚的方法非常简单,但是一旦屏幕被填满,可能会出现问题。生成一个x坐标介于0和屏幕宽度之间,y坐标介于0和屏幕高度之间的随机CGPoint。检查以该点为中心的矩形是否与任何现有视图相交。如果没有,你就有了你的随机位置。

出现问题的地方是当屏幕开始填满的时候。在这一点上,在找到放置卡片的位置之前,您可以尝试许多许多随机的点。你也可能会遇到一种情况,那就是没有更多的牌可以放进去。你怎么知道你已经做到了呢?生成随机点的循环会永远运行吗?

一个更聪明的解决方案是跟踪屏幕上的空闲空间。始终在这些自由空间中生成您的随机点。如果近似值足够近,您可以使用栅格来完成此操作。是否有一张卡片占据了每个网格位置?然后,当最大可用空间小于卡片矩形的大小时,您就知道完成了。这比单纯的方法要多得多,但当屏幕开始填满时,它会更快,当你完成时,你就会确定。

如果你知道你的屏幕空间总是会超过卡片所能占用的空间,那么天真的方法是不错的。

票数 5
EN

Stack Overflow用户

发布于 2017-08-14 12:37:11

这个想法

您知道容器UIView的宽度和高度。而且,每张卡片都有相同的宽度和高度。我会通过计算网格来实现这一点。

即使你想随机显示卡片,依赖网格也会给你一个标准化的中心数组,你可以用它来生成随机性的外观(例如,将一张卡片放在网格中的任何随机中心)。

如果您要将卡放在任何随机位置,您可能只想使用CGRectIntersectsRect(card1.frame, card2.frame)来检测冲突。

模式

首先,让我们将卡片的宽度和高度存储为常量。

代码语言:javascript
复制
let cardWidth = card.bounds.size.width
let cardHeight = card.bounds.size.height

作为基本的概念证明,假设您的容器视图宽度为250磅。假设卡片宽度为5点。这意味着您可以在一行中容纳250 /5= 50张卡片,其中一行的高度相当于一张卡片的高度。

一行中的中心数=该行中的卡片数。每个中心之间的距离是相等的。在下图中(如果我可以这样称呼它的话),[]表示一行的边缘。-|-表示一张卡片,其中|是卡片的中心。

[ - | - - | - - | - - | - - | - ]

请注意,每个中心距离下一个中心有两个短划线。唯一要考虑的是,边缘旁边的中心离边缘只有一小段距离。就牌而言,每个中心与下一张牌相距一整张牌,而边缘旁边的中心与边缘相距半张牌。

模式的关键

此模式意味着特定行中任何卡片中心的x位置= (cardWidth / 2) + (the card index * cardWidth)。事实上,这个伪方程也适用于y位置。

代码

这是一些使用这种方法创建中心数组的Swift。

代码语言:javascript
复制
var centers = [CGPoint]()

let numberOfRows: CGFloat = containerView.bounds.size.height / cardHeight
let numberOfCardsPerRow: CGFloat = containerView.bounds.size.width / cardWidth

for row in 0 ..< Int(numberOfRows) {
    for card in 0 ..< Int(numberOfCardsPerRow) {

        // The row we are on affects the y values of all the centers
        let yBasedOnRow = (cardHeight / 2) + (CGFloat(row) * cardHeight)

        // The xBasedOnCard formula is effectively the same as the yBasedOnRow one
        let xBasedOnCard = (cardWidth / 2) + (CGFloat(card) * cardWidth)

        // Each possible center for this row gets appended to the centers array
        centers.append(CGPoint(x: xBasedOnCard, y: yBasedOnRow))

    }
}

这段代码应该会为你的卡片创建一个中心网格。您可以围绕它构建一个函数,该函数返回要放置的卡片的随机中心,并跟踪使用的中心。

潜在的改进

首先,我认为可以将centers数组做成一个矩阵([[CGPoint]]()),用于更多的点逻辑存储。

其次,这段代码目前假设容器视图的宽度和高度可以被卡片的宽度和高度整除。例如,容器宽度为177,卡片宽度为5会导致一些问题。代码可以通过多种不同的方式来解决这个问题。

票数 2
EN

Stack Overflow用户

发布于 2017-08-20 15:12:47

最好的解决方案最简单/性能是随机显示卡片,但在网格内。诀窍是让网格大于卡片大小,这样卡片在网格中的位置将是随机的。

很容易检查哪个位置被占用,并且卡片将在“随机”帧上。

1-创建一个集合视图控制器,其中包含您想要显示的卡片总数(假设..在屏幕中输入的最大卡片?)

2-设置比卡片更大的原型单元大小。如果卡是50x80,那么单元应该是70x110。

3-向有约束的单元格添加UIImageView,这将是您的卡片图像

4-创建一个UICollectionViewCell,使用一个在单元格内随机设置卡片框架的方法(修改约束)

完成了!

没有卡片的单元格将没有图像或如您所愿的空单元格。因此,要添加新的卡片,只需在空单元格之间执行随机操作,并在单元格内添加具有随机坐标的卡片。

你的UICollectionViewCell会喜欢这样的

代码语言:javascript
复制
class CardCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var card: UIImageView!

override func awakeFromNib() {
    super.awakeFromNib()

    let newX = CGFloat(arc4random_uniform(UInt32(bounds.size.width-card.bounds.size.width+1)))
    let newY = CGFloat(arc4random_uniform(UInt32(bounds.size.height-card.bounds.size.height+1)))

    card.leftAnchor.constraintEqualToAnchor(leftAnchor, constant: newX).active = true
    card.topAnchor.constraintEqualToAnchor(rightAnchor, constant: newY).active = true
   }
}

你的集合视图控制器应该像这样的Collection View Image

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45593466

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档