Ios 如何在UIView中缩放CGPoints并重新缩放
我的应用程序代表一个小型ReportReview我有一个自定义的画布视图(Ios 如何在UIView中缩放CGPoints并重新缩放,ios,swift,Ios,Swift,我的应用程序代表一个小型ReportReview我有一个自定义的画布视图(UIView),用户可以在其中绘制。 当用户完成绘制时,将能够单击添加ui按钮,并将涂鸦附加到对象上。每个对象表示表中的一行。 当用户单击任意一行时,画布视图上的涂鸦颜色将更改,以便用户更容易看到。 当用户完成所有绘图后,可以单击保存ui按钮,在CoreData中将报告序列化并保存为数据。 用户可以将报告反序列化回查看报告 问题是涂鸦没有正确缩放(我认为),画布视图上的CG点位于不同的位置 以下是我的小项目的链接: 序列
UIView
),用户可以在其中绘制。
当用户完成绘制时,将能够单击添加ui按钮
,并将涂鸦附加到对象上。每个对象表示表中的一行。
当用户单击任意一行时,画布视图上的涂鸦颜色将更改,以便用户更容易看到。
当用户完成所有绘图后,可以单击保存ui按钮
,在CoreData中将报告序列化并保存为数据
。
用户可以将报告反序列化回查看报告
问题是涂鸦没有正确缩放(我认为),画布视图上的CG点位于不同的位置
以下是我的小项目的链接:
序列化时,我正在使用此函数:
func serializeDamageItemsTTable(damageItems: [DamageItem], canvas: CanvasView) -> TTable {
var metaDamage: [TMeta] = []
metaDamage.append(TMeta(type: .s, name: "descript")) // DamageItem Name
metaDamage.append(TMeta(type: .z, name: "scribble")) // Coordinates for each scribble recorded on the image for DamageItem
let ttDamageItems = TTable(meta: metaDamage)
print("SERIALIZATION STARTED")
damageItems.forEach { damageItem in
let row = TRow(tMeta: metaDamage)
row.cell.append(TCell(s: damageItem.name)) // DamageItem Name
var scribbleCoord = [UInt8]()
damageItem.scribbles.forEach { scribble in
var firstPointInScribble = true
scribble.forEach { coordinate in
// ------ Scale all CGPoints ---------
let factor: CGFloat = 240 / canvas.bounds.width
let scaledX = UInt8(coordinate.x * factor)
let scaledY = UInt8(coordinate.y * factor)
if (coordinate.x > 0 && coordinate.x < 255) && (coordinate.y > 0 && coordinate.y < 127) {
scribbleCoord.append(scaledX) // Append X coord
if firstPointInScribble {
firstPointInScribble = false
scribbleCoord.append(scaledY | Scribble.yMarkerBitmask) // Append value 1 in front of Y coord + Y coord
} else {
scribbleCoord.append(scaledY)
}
}
}
}
row.cell.append(TCell(data: scribbleCoord)) // Coordinates for each scribble recorded on the image for DamageItem
print("Damage Item Scribble: \(scribbleCoord)")
print("SERIALIZATION ENDED")
do{
try ttDamageItems.add(row: row)
} catch{
print("serializeDamageTTable: Row can't be added: \(error)")
}
}
return ttDamageItems
}
谢谢你读这篇文章 这对夫妇需要改变 防止坐标越界。当用户拖动以绘制线时,如果坐标超出“canvas”视图的边界,请将x/y更改为最小值0(零),并将最大值更改为bounds.maxX/bounds.maxY
将画布视图高度更改为imageView纵横比的结果高度(在您的特定情况下,图像始终为
240:127
ratio)。首先,您的GitHub回购与您在问题中发布的代码不匹配。在项目代码中,您没有缩放任何值,因此任何大于x:254,y:126的点都将被忽略。如果你想保存相对点进行缩放,我建议保存百分比。。。i、 e.savedX=actualX/canvaswitch
和``savedY=actualY/canvaswitheight`,然后用相反的步调将它们调回来。Hi@DonMag。我真的很抱歉,我刚刚意识到我没有提交更改。我实现了你的想法,我非常接近一个解决方案,但我有一个复制错误。请再次检查项目的链接。下面是一个屏幕记录:执行以下操作:打印(“Stroking\(isSelected):\(points)”)
在strokePath(…)
中的第一行。。。画一条尽可能短的线(所以你只有几个点)。。。保存它。。。加载它并检查调试输出。你会看到,这一行被调用了两次,分别是未缩放坐标和缩放坐标。@DonMag我解决了涂鸦位置的问题。我还有一个问题,如果我在画布外绘制并保存报告,会导致应用程序崩溃。如果用户在边缘之外,我需要以某种方式停止绘图。您可以通过将让scaledX=UInt8(坐标.x*因子)
(和scaledY)移动到如果(坐标.x>0&&…
block。这将忽略任何负坐标。但是,我被你的let factor:CGFloat=240/canvas.bounds.width
弄糊涂了,然后你将其用于x和Y值?另外,如果我在图像下方放置一个涂鸦点,但仍然在画布的边界内,它会重新绘制,直到我保存并删除它为止重新加载报告…此时它不再绘制正确的笔划。
// Resize back all CGPoints
func scaleAllCGPoints(damageItems: [DamageItem], canvas: CanvasView) -> [[CGPoint]] {
return damageItems.flatMap { damageItem in
damageItem.scribbles.map { scribble in
scribble.map { point in
let factor: CGFloat = 240 / canvas.bounds.width
let scaledX = point.x / factor
let scaledY = point.y / factor
return CGPoint(x: scaledX, y: scaledY)
}
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
// Cell with the image recorded + scribbles on the image
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "reviewCanvasCell", for: indexPath) as! ReviewCanvasCell
// ------ Resize back all CGPoints ---------
let scribbleCGPoints = scaleAllCGPoints(damageItems: reviewDamageItems, canvas: cell.reviewCanvas)
cell.reviewCanvas.currentScribble = scribbleCGPoints
// ------ Unscaled version ---------
cell.reviewImageView.image = UIImage(data: report.imageRecorded ?? Data()) // Load Image recorded from CoreData
cell.reviewCanvas.damageItems = reviewDamageItems // Load Scribbles on the image from CoreData
cell.selectedDamageIndex = tableView.indexPathForSelectedRow?.row
return cell
default: return UITableViewCell()
}
}