【问题标题】:How to move CALayer on NSImageView如何在 NSImageView 上移动 CALayer
【发布时间】:2017-01-11 17:01:08
【问题描述】:

NSImageView 有一个子类,并创建了 CALayer 的实例,所以我们在图像上看到了一个矩形。问题是如何在鼠标按下(当鼠标指针在矩形内)并拖动时移动这个矩形。当鼠标向上时,这个矩形(CALayer)应该留在图像上的新位置。

例如

class ImageViewWithRectangle: NSImageView
{
    var shape : CAShapeLayer!

    func drawRectangle()
    {   
        shape = CAShapeLayer()
        shape.lineWidth = 1.0
        shape.fillColor = NSColor.clear().cgColor
        shape.strokeColor = NSColor.gray().cgColor
        shape.lineDashPattern = [1,1]
        self.layer?.addSublayer(shape)

        let path = CGMutablePath()
        path.moveTo(nil, x: 1, y: 1)
        path.addLineTo(nil, x: 1, y: 50)
        path.addLineTo(nil, x: 50, y: 50)
        path.addLineTo(nil, x: 50, y: 1)
        path.closeSubpath()
        self.shape.path = path

    }
}     

【问题讨论】:

标签: swift calayer nsimageview


【解决方案1】:

你已经非常接近你的目标了,只需实现鼠标事件!

这是一个有效的 sn-p:


class ImageViewWithRectangle: NSImageView {

    var shape : CAShapeLayer!

    var shapeRect = NSMakeRect(10, 10, 100, 50)

    var shouldMove = false;

    var anchorPoint : NSPoint!

    override func awakeFromNib() {

        //We MUST implement layers! Otherwise nothing will work!!
        //You could do it even through Interface Builder

        self.wantsLayer = true;

    }

    override func drawRect(dirtyRect: NSRect) {

        //Every time the view is drawn, remove the old layer
        self.layer?.sublayers?.forEach({ $0.removeFromSuperlayer() })

        //Draw the new one
        self.drawRectangle()
    }

    func drawRectangle()
    {

        //Draw the layer
        shape = CAShapeLayer()
        shape.lineWidth = 1.0
        shape.fillColor = NSColor(calibratedWhite: 1, alpha: 0).CGColor
        shape.strokeColor = NSColor.grayColor().CGColor
        shape.lineDashPattern = [1,1]
        shape.backgroundColor = NSColor.greenColor().CGColor

        //No need for CGPaths for a simple rect, just set the frame and fill it
        shape.frame = self.shapeRect

        self.layer?.addSublayer(shape)

    }

    //Implmenet mouse events
    override func mouseDown(theEvent: NSEvent) {

        //get coordinates
        let pos = theEvent.locationInWindow

        //Check if inside the rect
        if ((pos.x >= self.shapeRect.origin.x) && (pos.x <= self.shapeRect.origin.x + self.shapeRect.size.width)) {

            //X match, now check Y
            if ((pos.y >= self.shapeRect.origin.y) && (pos.y <= self.shapeRect.origin.y + self.shapeRect.size.height)) {

                //If we get here, then we're insisde the rect!
                self.shouldMove = true;

                //OPTIONAL : Set an anchor point
                self.anchorPoint = NSMakePoint(pos.x - self.shapeRect.origin.x, pos.y - self.shapeRect.origin.y);


            }

        }


    }

    override func mouseDragged(theEvent: NSEvent) {

        if (self.shouldMove) {

            let pos = theEvent.locationInWindow

            //Update rect origin, or whatever you want to use as anchor point
            self.shapeRect.origin = NSMakePoint(pos.x - self.anchorPoint.x, pos.y - self.anchorPoint.y)

            //Redraw the view
            self.display()

        }

    }

    override func mouseUp(theEvent: NSEvent) {

        if (self.shouldMove) {

            //Reset value
            self.shouldMove = false;

        }

    }

}

输出将是这样的(没有设置背景图像


您甚至可以添加过渡效果、边框、渐变等等!

CALayers 和更普遍的 CoreAnimation 真的很强大!

如果您需要澄清,请告诉我,

我希望这会有所帮助,如果有,请将此答案标记为正确,以便其他人可以使用它!

干杯。

【讨论】:

  • 感谢您的出色回答!这是很好的教学方法的一个很好的例子!
  • 很高兴它有帮助:)
  • macOS 新手在这里。请问为什么我们要更改 shapeRect 的原点而不是 mouseDragged 中的 shape 的原点?绿框的位置不应该改变吗?
猜你喜欢
  • 2013-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
相关资源
最近更新 更多