问题描述
我有一个 CGRect
(我们称它为 A1
),它的大小和位置都知道,它的父 A
的大小已知。 A1
应用了各种 CGAffineTransform
。
我需要找到相对于已知(但尺寸不同)的父 B
的第二个矩形的位置和大小,该父 A1
看起来与 A
成正比,相对于 A1
基本上是“缩放”效果。当放置在 B
中时,public class CustomTestExecutionListener implements TestExecutionListener,Ordered {
public ByteArrayOutputStream request = new ByteArrayOutputStream();
public ByteArrayOutputStream response = new ByteArrayOutputStream();
public PrintStream requestvar = new PrintStream(request,true);
public PrintStream responseVar = new PrintStream(response,true);
public void beforeTestMethod(TestContext testContext) throws Exception {
RestAssured.filters(new ResponseLoggingFilter(LogDetail.ALL,responseVar),new RequestLoggingFilter(LogDetail.ALL,requestvar));
}
public void afterTestMethod(TestContext testContext) throws Exception {
logRequest(request);
logResponse(response);
}
@Override
public int getorder() {
return Integer.MAX_VALUE;
}
@Attachment(value = "Client RQ",type = "text/html")
public byte[] logRequest(ByteArrayOutputStream stream) {
return attach(stream);
}
@Attachment(value = "Client RS",type = "text/html")
public byte[] logResponse(ByteArrayOutputStream stream) {
return attach(stream);
}
public byte[] attach(ByteArrayOutputStream log) {
byte[] array = log.toString().getBytes(StandardCharsets.UTF_8);
log.reset();
return array;
}
}
的尺寸和位置看起来相似。有点像“缩放 CGAffineTransform”?
视觉指南:
来自:
致:
解决方法
假设你像这样转换矩形:
scale it
move it
rotate it
首先,您要计算两个尺寸之间的“scaleFactor”。所以...
- 如果矩形 A 是 100 x 100
- 和矩形 B 是 200 x 200
scaleFactor 将是 200 / 100 == 2 ...也就是说,B 是 2 倍大。
为了您的价值观:
- 矩形 A 为 375 x 375
- 矩形 B 为 1080 x 1080
比例因子是 1080 / 375 == 2.88
所以,让我们使用使数学变得简单(且显而易见)的值:
-
矩形 A 为 200 x 200
- 矩形 A1 原点是 x: 30 y: 20
- 矩形 A1 尺寸为 50 x 25
-
矩形 B 为 600 x 600
scaleFactor 是 600 / 200 == 3,所以
- 矩形 B1 原点是 x: (30 * 3) y: (20 * 3)
- 矩形 B1 大小为 (50 * 3) x (25 * 3)
如果这就是我们迄今为止所做的一切,我们会得到这样的结果:
接下来,我们需要移动(平移)它,并缩放平移。如果原文是:
CGAffineTransform(translationX: 30,y: 100)
新的翻译是:
CGAffineTransform(translationX: 30 * scaleFactor,y: 100 * scaleFactor)
我们不需要缩放旋转,因为它是相同的旋转。
因此,根据我们的原点和大小计算设置原始框架后,然后应用相同的缩放变换,加上缩放的平移变换,加上相同的旋转变换,我们得到:
这是我用来生成它的示例代码:
class ViewController: UIViewController {
let viewA: UIView = {
let v = UIView()
v.backgroundColor = .systemYellow
return v
}()
let viewARedView: UIView = {
let v = UIView()
v.backgroundColor = .systemRed
return v
}()
let viewABlueView: UIView = {
let v = UIView()
v.backgroundColor = .systemBlue
return v
}()
let viewB: UIView = {
let v = UIView()
v.backgroundColor = .systemYellow
return v
}()
let viewBRedView: UIView = {
let v = UIView()
v.backgroundColor = .systemRed
return v
}()
let viewBBlueView: UIView = {
let v = UIView()
v.backgroundColor = .systemBlue
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.setNavigationBarHidden(true,animated: false)
view.addSubview(viewA)
view.addSubview(viewB)
viewA.frame = CGRect(x: 20,y: 60,width: 200,height: 200)
viewB.frame = CGRect(x: 20,y: viewA.frame.maxY + 20,width: 600,height: 600)
viewA.addSubview(viewARedView)
viewA.addSubview(viewABlueView)
let origRect: CGRect = CGRect(x: 30,y: 20,width: 50,height: 25)
// set frames of red and blue rect to the same rectangles
// so blue is on top of red
// we're going to transform the blue rect
viewARedView.frame = origRect
viewABlueView.frame = origRect
// scale values
let scX: CGFloat = 2.25
let scY: CGFloat = 1.75
// translate values
let trX: CGFloat = 30.0
let trY: CGFloat = 100.0
// rotation value
let rot: CGFloat = .pi * -0.15
var tx: CGAffineTransform = .identity
// scale it
tx = tx.concatenating(CGAffineTransform(scaleX: scX,y: scY))
// move it
tx = tx.concatenating(CGAffineTransform(translationX: trX,y: trY))
// rotate it
tx = tx.concatenating(CGAffineTransform(rotationAngle: rot))
// apply the transform
viewABlueView.transform = tx
viewB.addSubview(viewBRedView)
viewB.addSubview(viewBBlueView)
// get the scale factor...
// in this case,// viewA width is 200
// viewB width is 700
// so viewB is 3.5 times bigger (700 / 200)
let scaleFactor: CGFloat = viewB.frame.width / viewA.frame.width
// make the original rect origin and size
// "scaleFactor bigger"
let newRect: CGRect = CGRect(x: origRect.origin.x * scaleFactor,y: origRect.origin.y * scaleFactor,width: origRect.width * scaleFactor,height: origRect.height * scaleFactor)
// set frames of red and blue rect to the same rectangles
// so blue is on top of red
// we're going to transform the blue rect
viewBRedView.frame = newRect
viewBBlueView.frame = newRect
// scale the translation values
let trXb: CGFloat = trX * scaleFactor
let trYb: CGFloat = trY * scaleFactor
var txb: CGAffineTransform = .identity
// we've already changed the initial size of the rectangle,// so use same scaling values
txb = txb.concatenating(CGAffineTransform(scaleX: scX,y: scY))
// we need to use scaled translation values
txb = txb.concatenating(CGAffineTransform(translationX: trXb,y: trYb))
// rotation doesn't change based on scale
txb = txb.concatenating(CGAffineTransform(rotationAngle: rot))
// apply the transform
viewBBlueView.transform = txb
}
}