Ios 如何在UIView中缩放CGPoints并重新缩放

Ios 如何在UIView中缩放CGPoints并重新缩放,ios,swift,Ios,Swift,我的应用程序代表一个小型ReportReview我有一个自定义的画布视图(UIView),用户可以在其中绘制。 当用户完成绘制时,将能够单击添加ui按钮,并将涂鸦附加到对象上。每个对象表示表中的一行。 当用户单击任意一行时,画布视图上的涂鸦颜色将更改,以便用户更容易看到。 当用户完成所有绘图后,可以单击保存ui按钮,在CoreData中将报告序列化并保存为数据。 用户可以将报告反序列化回查看报告 问题是涂鸦没有正确缩放(我认为),画布视图上的CG点位于不同的位置 以下是我的小项目的链接: 序列

我的应用程序代表一个小型ReportReview我有一个自定义的画布视图(
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()
        }
    }