【问题标题】:Drawn lines with touch location shrinking and fading into background Swift 3.0绘制的线条与触摸位置缩小并淡入背景 Swift 3.0
【发布时间】:2017-05-30 04:41:14
【问题描述】:

我在 Swift 3.0 上遇到了一个奇怪的错误,我成功地绘制到位于 UIView 内的 UIImageView,但是当我绘制之前绘制的线开始褪色并缩小到 UIImageView 的顶部并变得非常模糊时如附图所示。 Beginning of Drawing, Image becoming blurry.

如果能提供任何帮助/指导,我将不胜感激。

class DrawView: UIView {
    var drawArea: UIImageView!
    var clearDrawArea: UIButton!
    var lastTouch = CGPoint.zero

    init(){
        super.init(frame: CGRect(x: UIScreen.main.bounds.width*0.135, y:UIScreen.main.bounds.height*0.05, width: UIScreen.main.bounds.width*0.8, height: UIScreen.main.bounds.height*0.9))
        drawArea = UIImageView(frame: CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: self.bounds.width*0.9, height: self.bounds.height*0.86))
        drawArea.backgroundColor = UIColor.white

        let buttonWidth = self.bounds.width*0.2
        let buttonHeight = self.bounds.height*0.1
        clearDrawArea = UIButton(frame: CGRect(x: (self.bounds.width*0.61)-(buttonWidth/2), y: self.bounds.height*0.94, width: buttonWidth, height: buttonHeight))
        clearDrawArea.setTitle("Clear Draw Area", for: .normal)
        clearDrawArea.backgroundColor = UIColor(red: 49/255, green: 200/255, blue: 134/255, alpha: 255)
        clearDrawArea.addTarget(self, action: #selector(resetImage), for: .touchUpInside)

        self.addSubview(clearDrawArea)
        self.addSubview(drawArea)

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        if let firstTouch = touches.first{

            lastTouch = firstTouch.location(in: drawArea)
        }

    }
    func drawLines(_ from: CGPoint, to: CGPoint){
        UIGraphicsBeginImageContext(drawArea.frame.size)
        let context = UIGraphicsGetCurrentContext()

        context?.move(to: CGPoint(x: from.x, y: from.y))
        context?.addLine(to: CGPoint(x: to.x, y: to.y))

        context?.setLineCap(.round)
        context?.setLineWidth(3)
        context?.setStrokeColor(UIColor.black.cgColor)

        context?.strokePath()

        drawArea.image?.draw(in: drawArea.bounds)
        drawArea.image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {


        if let firstTouch = touches.first{
            let touchLocation = firstTouch.location(in: drawArea)
            drawLines(lastTouch, to: touchLocation)

            lastTouch = touchLocation
        }
    }

    func resetImage(){

        drawArea.image = nil            
    }
}

【问题讨论】:

  • 你想用这段代码实现什么?
  • 感谢您的帮助。我只是试图让用户在他们触摸的任何地方都可以在屏幕上绘图,只是为了让它被抛在后面。当我使用整个屏幕的边界在视图控制器类中实现代码时,它按预期工作,但是当我尝试限制为 UIView 时它不起作用。

标签: ios swift uikit


【解决方案1】:

稍微修改一下你的代码试试下面的..

class DrawView: UIView {
var drawArea: UIImageView!
var clearDrawArea: UIButton!
var lastTouch = CGPoint.zero
let pathAnimation: CABasicAnimation = CABasicAnimation(keyPath:"animation")
let tempPathLayer: CAShapeLayer = CAShapeLayer()
var lineLayer:CAShapeLayer=CAShapeLayer()
init(){
    super.init(frame: CGRect(x: UIScreen.main.bounds.width*0.135, y:UIScreen.main.bounds.height*0.05, width: UIScreen.main.bounds.width*0.8, height: UIScreen.main.bounds.height*0.9))
    drawArea = UIImageView(frame: CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: self.bounds.width*0.9, height: self.bounds.height*0.86))
    drawArea.backgroundColor = UIColor.white

    let buttonWidth = self.bounds.width*0.2
    let buttonHeight = self.bounds.height*0.1
    clearDrawArea = UIButton(frame: CGRect(x: (self.bounds.width*0.61)-(buttonWidth/2), y: self.bounds.height*0.94, width: buttonWidth, height: buttonHeight))
    clearDrawArea.setTitle("Clear Draw Area", for: .normal)
    clearDrawArea.backgroundColor = UIColor(red: 49/255, green: 200/255, blue: 134/255, alpha: 255)
    clearDrawArea.addTarget(self, action: #selector(resetImage), for: .touchUpInside)

    self.addSubview(clearDrawArea)
    self.addSubview(drawArea)

}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    //fatalError("init(coder:) has not been implemented")
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    if let firstTouch = touches.first{

        lastTouch = firstTouch.location(in: drawArea)
    }

}
func drawLines(_ from: CGPoint, to: CGPoint){
    UIGraphicsBeginImageContext(drawArea.frame.size)

    //let context = UIGraphicsGetCurrentContext()
    let tempPath: UIBezierPath = UIBezierPath()
    var lineLayer:CAShapeLayer=CAShapeLayer()
    tempPath.move(to: from)
    tempPath.addLine(to: to)
    let strokeColor = UIColor.red
    UIColor.blue.setFill()
    strokeColor.setStroke()

    let tempPathLayer: CAShapeLayer = CAShapeLayer()
    tempPathLayer.frame = self.bounds
    tempPathLayer.position=self.layer.position
    tempPathLayer.strokeColor = UIColor.green.cgColor
    tempPathLayer.fillColor = UIColor.red.cgColor
    tempPathLayer.lineWidth = 1.0
    tempPathLayer.path = tempPath.cgPath
    lineLayer=tempPathLayer
    pathAnimation.beginTime=CACurrentMediaTime()
    pathAnimation.duration = 2
    pathAnimation.fromValue = NSNumber(value: 0.0)
    pathAnimation.toValue = NSNumber(value:1.0)

    lineLayer.add(pathAnimation, forKey: "animation")
    self.layer.addSublayer(lineLayer)

    drawArea.image?.draw(in: drawArea.bounds)
    drawArea.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {


    if let firstTouch = touches.first{
        let touchLocation = firstTouch.location(in: drawArea)
        drawLines(lastTouch, to: touchLocation)

        lastTouch = touchLocation
    }
}

func resetImage(){

    drawArea.image = nil            
}

}

【讨论】:

  • 我尝试使用您添加的代码并进行了修改,但绘制的线条不会保留,并且在用户触摸后留下一小段痕迹
  • 你能再检查一次吗?因为相同的代码为我提供了结果。
  • 我再次检查,它仍然像我提到的那样。我也在 iPad 上进行了测试以确保。奇怪的是它适用于你的。为了进一步隔离问题,我在一个完全空白的视图控制器上测试了我的代码,该控制器的图像视图与屏幕大小相同,并且运行良好。只有在 UIView 类的 imageview 中实现它时才会出现问题。我还减小了该视图控制器上图像视图的大小,它仍然可以按预期工作。
  • 如果我将功能移到 UIView 的父控制器中可能会带来一些运气?
  • 您是说代码在空白视图控制器上按预期工作吗?
【解决方案2】:

我终于让它正常工作了。我利用您的想法改用贝塞尔路径并对其进行了修改以将绘图范围限制为 UIView。

class DrawView: UIView {
var drawArea: UIImageView!
var clearDrawArea: UIButton!
var lastTouch = CGPoint.zero
var context: CGContext!
var path: UIBezierPath!
init(){
    context = UIGraphicsGetCurrentContext()
    path = UIBezierPath()
    super.init(frame: CGRect(x: UIScreen.main.bounds.width*0.135, y:UIScreen.main.bounds.height*0.05, width: UIScreen.main.bounds.width*0.8, height: UIScreen.main.bounds.height*0.9))
    drawArea = UIImageView(frame: CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: self.bounds.width*0.9, height: self.bounds.height*0.86))
    drawArea.backgroundColor = UIColor.white

    let buttonWidth = self.bounds.width*0.2
    let buttonHeight = self.bounds.height*0.1
    clearDrawArea = UIButton(frame: CGRect(x: (self.bounds.width*0.61)-(buttonWidth/2), y: self.bounds.height*0.94, width: buttonWidth, height: buttonHeight))
    clearDrawArea.setTitle("Clear Draw Area", for: .normal)
    clearDrawArea.backgroundColor = UIColor(red: 49/255, green: 200/255, blue: 134/255, alpha: 255)
    clearDrawArea.addTarget(self, action: #selector(resetImage), for: .touchUpInside)

    self.addSubview(clearDrawArea)
    self.addSubview(drawArea)

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    if let firstTouch = touches.first{

        lastTouch = firstTouch.location(in: drawArea)
    }

}
func drawLines(_ from: CGPoint, to: CGPoint){
    UIGraphicsBeginImageContext(drawArea.frame.size)

    path.move(to: CGPoint(x: from.x, y: from.y))
    path.addLine(to: CGPoint(x: to.x, y: to.y))

    UIColor.black.setStroke()
    path.lineWidth = 3
    path.stroke()

    context?.saveGState()
    context?.addPath(path.cgPath)
    context?.closePath()
    context?.restoreGState()

    drawArea.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {


    if let firstTouch = touches.first {
        let touchLocation = firstTouch.location(in: drawArea)
        drawLines(lastTouch, to: touchLocation)

        lastTouch = touchLocation
    }
}

func resetImage(){
    path.removeAllPoints()
    drawArea.image = nil            
}

}

【讨论】:

    【解决方案3】:

    我也有这个问题。我通过更改约束来修复它,以便将视图固定到视图控制器。我最初有一个纵横比,它在 6/7 尺寸中导致了这个问题,但不是 5/SE 尺寸或 PLUS 尺寸。这可能就是为什么在测试另一个答案提交的代码时,它对他们有效,但对您无效。如果 uiView 和绘图区域未正确对齐和调整大小,它会扭曲您的绘图/导致“条纹”大线似乎来自任何地方/仅在某些区域上绘图/您将触摸一个地方,它会在某个地方绘制别的。

    我建议测试所有屏幕尺寸,以确保您的功能适用于所有屏幕尺寸,并且在您拥有的约束设置下看起来正确。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-29
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多