首页 > 解决方案 > 拖放在 NSImageView Swift MacOS 应用程序中呈现的动画 GIF

问题描述

我正在尝试构建一个 Mac OSX 应用程序,它可以呈现多个 gif,并允许用户拖放它们以将 gif 复制到其他应用程序中。我正在使用DragDropImageView符合 的(下面的代码)NSImageView来呈现启用拖放功能的 gif。

它工作正常,除了当我将 gif 拖放到另一个应用程序中时,它只复制 gif 的单个图像帧。我的目的是复制整个 gif 文件,而不仅仅是一个图像。

一般来说,我对 iOS/MacOS 开发还是很陌生,我不确定我构建这个可拖动 gif 组件的方法是否正确。

我正在使用 swiftUI 构建应用程序,并使用一个名为的自定义视图将GifImageView其转换DragDropImageView为 swiftUI 视图。

DragDropImageView.swift

import Cocoa

class DragDropImageView: NSImageView, NSDraggingSource {

    /// Holds the last mouse down event, to track the drag distance.
    var mouseDownEvent: NSEvent?

    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)

        isEditable = false
    }

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

        // Assure editable is set to true, to enable drop capabilities.
        isEditable = true
    }

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
    }

    // MARK: - NSDraggingSource
    // Since we only want to copy the current image we register
    // for .Copy operation.
    func draggingSession(_: NSDraggingSession,
                         sourceOperationMaskFor _: NSDraggingContext) -> NSDragOperation {
        return NSDragOperation.copy
    }

//    // Clear the ImageView on delete operation; e.g. the image gets
//    // dropped on the trash can in the dock.
//    func draggingSession(_: NSDraggingSession, endedAt _: NSPoint,
//                         operation: NSDragOperation) {
//        if operation == .delete {
//            image = nil
//        }
//    }

    // Track mouse down events and safe the to the poperty.
    override func mouseDown(with theEvent: NSEvent) {
        mouseDownEvent = theEvent
    }

    // Track mouse dragged events to handle dragging sessions.
    override func mouseDragged(with event: NSEvent) {

        // Calculate the dragging distance...
        let mouseDown = mouseDownEvent!.locationInWindow
        let dragPoint = event.locationInWindow
        let dragDistance = hypot(mouseDown.x - dragPoint.x, mouseDown.y - dragPoint.y)

        // Cancel the dragging session in case of an accidental drag.
        if dragDistance < 3 {
            return
        }

        guard let image = self.image else {
            return
        }

        let draggingImage = image

        // Create a new NSDraggingItem with the image as content.
        let draggingItem = NSDraggingItem(pasteboardWriter: image)

        // Calculate the mouseDown location from the window's coordinate system to the
        // ImageView's coordinate system, to use it as origin for the dragging frame.
        let draggingFrameOrigin = convert(mouseDown, from: nil)
        // Build the dragging frame and offset it by half the image size on each axis
        // to center the mouse cursor within the dragging frame.
        let draggingFrame = NSRect(origin: draggingFrameOrigin, size: draggingImage.size)
            .offsetBy(dx: -draggingImage.size.width / 2, dy: -draggingImage.size.height / 2)

        // Assign the dragging frame to the draggingFrame property of our dragging item.
        draggingItem.draggingFrame = draggingFrame

        // Provide the components of the dragging image.
        draggingItem.imageComponentsProvider = {
            let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon)

            component.contents = image
            component.frame = NSRect(origin: NSPoint(), size: draggingFrame.size)
            return [component]
        }

        // Begin actual dragging session. Woohow!
        beginDraggingSession(with: [draggingItem], event: mouseDownEvent!, source: self)
    }
}

GifImageView.swift

import AppKit;
import SwiftUI;

struct GifImageView: NSViewRepresentable {
    var image: NSImage
    
    func makeNSView(context: Context) -> DragDropImageView {
        let view = DragDropImageView()
        view.image = self.image
//        view.allowsCutCopyPaste = true
        return view
    }

    func updateNSView(_ view: DragDropImageView, context: Context) {
        
    }

}

struct GifImageView_Previews: PreviewProvider {
    static var previews: some View {
        GifImageView(image: NSImage(data: (NSDataAsset(name: "tenor")?.data)!)!)
    }
}

在我的ContentView.swift,我用我的GifImageView东西是这样的:

GifImageView(image: *some NSImage*)

标签: swiftmacosswiftuigif

解决方案


推荐阅读