swift - 拖放在 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*)
解决方案
推荐阅读
- ios - 崩溃问题:iOS 12.0.1 ( 16A404 ),App 自动关闭
- reactjs - 我的简单 react-dnd 不起作用 - 拖动一个项目会导致整个列表消失
- python - 连接被对方拒绝:111:连接被拒绝。在 linux 服务器中使用 Scrapy Crawlera 时
- shell - 如何将大写工作日时间戳从大写转换为小写?
- java - 如何在彼此正下方添加 JLabels 序列?
- javascript - 根据另一个数组的排序顺序对数组进行排序的数据结构或过程
- c - xv6 源代码中的 cga_init() 中的 0xa55a 是什么意思?
- google-apps-script - 如何在 Google 脚本中检查已完成的 Google 任务?
- windows - 如何在 Visual Studio 2017 和英特尔 Visual Fortran Composer XE 之间创建链接?
- powershell - 使用管道和直接使用 InputObject 参数之间有什么效率差异吗?