【问题标题】:How to bound the drawn shape to square as mouse dragged如何在鼠标拖动时将绘制的形状绑定为正方形
【发布时间】:2021-06-22 00:22:41
【问题描述】:

当鼠标按下事件开始时,我正在绘制一个形状,并且该动画是在鼠标拖动事件上绘制的。下面是使用的代码:

override func mouseDown(with event: NSEvent) {

    self.startPoint = self.convert(event.locationInWindow, from: nil)
    if self.shapeLayer != nil {
        self.shapeLayer.removeFromSuperlayer()
        self.shapeLayer = nil
    }
    var pixelColor: NSColor = NSReadPixel(startPoint) ?? NSColor()
    shapeLayer = CAShapeLayer()
    shapeLayer.lineWidth = 1.0
    shapeLayer.fillColor = NSColor.clear.cgColor
    if pixelColor == NSColor.black {
        pixelColor = NSColor.color_white
    } else {
        pixelColor = NSColor.black
    }
    shapeLayer.strokeColor = pixelColor.cgColor
    shapeLayer.lineDashPattern = [1]
    self.layer?.addSublayer(shapeLayer)

    var dashAnimation = CABasicAnimation()
    dashAnimation = CABasicAnimation(keyPath: "lineDashPhase")
    dashAnimation.duration = 0.75
    dashAnimation.fromValue = 0.0
    dashAnimation.toValue = 15.0
    dashAnimation.repeatCount = 0.0
    shapeLayer.add(dashAnimation, forKey: "linePhase")
}

override func mouseDragged(with event: NSEvent) {
    let point: NSPoint = self.convert(event.locationInWindow, from: nil)
    let path = CGMutablePath()
    path.move(to: self.startPoint)
    path.addLine(to: NSPoint(x: self.startPoint.x, y: point.y))
    path.addLine(to: point)
    path.addLine(to: NSPoint(x: point.x, y: self.startPoint.y))
    path.closeSubpath()
    self.shapeLayer.path = path
}

目前它也会像这样绘制矩形:

我们能不能把它绑定成方形,这样当用户开始拖动鼠标时,它就会一直跟随方形?

【问题讨论】:

    标签: ios swift macos crop nsimage


    【解决方案1】:

    开启mouseDragged

    • 获取startPoint.xpoint.x的距离
    • 获取startPoint.ypoint.y的距离
    • 使用这两者的 MAX 或 MIN(abs() 值)作为轮廓形状的宽度和高度

    使用 MAX 将绘制一个更大的正方形,并且当您穿过轴时它会“翻转”。使用 MIN 将绘制一个正方形,当您接近轴时,该正方形会收缩到中心。发现差异的最简单方法是尝试一下:

    var startPoint: CGPoint = .zero
    
    override func mouseDown(with event: NSEvent) {
        self.startPoint = self.convert(event.locationInWindow, from: nil)
    }
    
    override func mouseDragged(with event: NSEvent) {
        let point: NSPoint = self.convert(event.locationInWindow, from: nil)
    
        var newPoint: CGPoint = self.startPoint
        
        let xDiff = point.x - self.startPoint.x
        let yDiff = point.y - self.startPoint.y
        
        // using min() will cause the square to "shrink"
        //  as you get closer to an axis
        let dist = min(abs(xDiff), abs(yDiff))
        
        // using max() will cause the square to "flip"
        //  when crossing an axis
        //let dist = max(abs(xDiff), abs(yDiff))
        
        newPoint.x += xDiff > 0 ? dist : -dist
        newPoint.y += yDiff > 0 ? dist : -dist
        
        let path = CGMutablePath()
        path.move(to: self.startPoint)
        path.addLine(to: NSPoint(x: self.startPoint.x, y: newPoint.y))
        path.addLine(to: newPoint)
        path.addLine(to: NSPoint(x: newPoint.x, y: self.startPoint.y))
        path.closeSubpath()
        self.shapeLayer.path = path
    }
    

    如果有人在 iOS 中寻找类似功能:

    var startPoint: CGPoint = .zero
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            startPoint = touch.location(in: self)
        }
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            let point = touch.location(in: self)
            
            var newPoint: CGPoint = startPoint
            
            let xDiff = point.x - startPoint.x
            let yDiff = point.y - startPoint.y
    
            // using min() will cause the square to "shrink"
            //  as you get closer to an axis
            //let dist = min(abs(xDiff), abs(yDiff))
            
            // using max() will cause the square to "flip"
            //  when crossing an axis
            let dist = max(abs(xDiff), abs(yDiff))
    
            newPoint.x += xDiff > 0 ? dist : -dist
            newPoint.y += yDiff > 0 ? dist : -dist
    
            let path = CGMutablePath()
            path.move(to: startPoint)
            path.addLine(to: CGPoint(x: startPoint.x, y: newPoint.y))
            path.addLine(to: newPoint)
            path.addLine(to: CGPoint(x: newPoint.x, y: startPoint.y))
            path.closeSubpath()
            shapeLayer.path = path
        }
    }
    

    【讨论】:

    • 我建议在扩展中将该 CGRect 计算逻辑提取到 CGRect 上的初始化器中。
    猜你喜欢
    • 1970-01-01
    • 2019-04-21
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    相关资源
    最近更新 更多