Как переместить CALayer на NSImageView

Существует подкласс 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

    }
}     

1 ответ

Решение

Вы очень близки к своей цели, просто реализуйте события мыши!

Вот рабочий фрагмент:


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 действительно мощная!

Пожалуйста, дайте мне знать, если вам нужны разъяснения,

Я надеюсь, что это помогло, если это так, отметьте этот ответ как правильный, чтобы другие могли его использовать!

Приветствия.

Другие вопросы по тегам