You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS:如何实现WKWebView中视频点击按钮全屏填充视图

视频全屏填充视图的实现方案

核心实现思路

  1. 建立SwiftUI视图与WebView的状态绑定,让按钮能触发全屏/退出全屏的状态切换
  2. 通过注入JavaScript控制网页内的视频元素,让其占满整个WebView视口
  3. 调整SwiftUI布局,在全屏状态下让WebView忽略安全区,隐藏多余控件

代码修改实现

1. 修改WebView组件(添加状态绑定与JS控制)

import SwiftUI
import WebKit
import AppKit

struct WebView: NSViewRepresentable {
    typealias NSViewType = WKWebView
    
    let webView: WKWebView
    @Binding var isVideoFullscreen: Bool
    
    init(isVideoFullscreen: Binding<Bool>) {
        self._isVideoFullscreen = isVideoFullscreen
        webView = WKWebView(frame: .zero)
        webView.load(URLRequest(url: URL(string: "https://www.youtube.com/watch?v=FT3ODSg1GFE")!))
    }
    
    func makeNSView(context: Context) -> WKWebView {
        webView.configuration.preferences.setValue(true, forKey: "fullScreenEnabled")
        webView.autoresizingMask = [.width, .height]
        return webView
    }
    
    func updateNSView(_ uiView: WKWebView, context: Context) {
        // 全屏状态切换时执行对应JS逻辑
        if isVideoFullscreen {
            let fullscreenJS = """
            const videos = document.querySelectorAll('video');
            if (videos.length > 0) {
                const video = videos[0];
                // 设置视频占满视口
                video.style.width = '100%';
                video.style.height = '100%';
                video.style.objectFit = 'cover';
                // 调整页面布局,隐藏多余元素
                document.body.style.margin = '0';
                document.body.style.padding = '0';
                document.body.style.overflow = 'hidden';
                // 调整视频父容器,确保层级最高
                const parent = video.parentElement;
                if (parent) {
                    parent.style.width = '100vw';
                    parent.style.height = '100vh';
                    parent.style.position = 'fixed';
                    parent.style.top = '0';
                    parent.style.left = '0';
                    parent.style.zIndex = '9999';
                }
                video.play();
            }
            """
            uiView.evaluateJavaScript(fullscreenJS) { _, error in
                error.map { print("JS执行错误: \($0.localizedDescription)") }
            }
        } else {
            // 恢复原有布局
            let resetJS = """
            const videos = document.querySelectorAll('video');
            if (videos.length > 0) {
                const video = videos[0];
                video.style.width = '';
                video.style.height = '';
                video.style.objectFit = '';
                document.body.style.margin = '';
                document.body.style.padding = '';
                document.body.style.overflow = '';
                const parent = video.parentElement;
                if (parent) {
                    parent.style.width = '';
                    parent.style.height = '';
                    parent.style.position = '';
                    parent.style.top = '';
                    parent.style.left = '';
                    parent.style.zIndex = '';
                }
            }
            """
            uiView.evaluateJavaScript(resetJS) { _, error in
                error.map { print("JS重置错误: \($0.localizedDescription)") }
            }
        }
    }
}

2. 修改ContentView(添加状态控制与布局切换)

import SwiftUI
import WebKit

struct ContentView: View {
    @State private var isVideoFullscreen = false
    
    var body: some View {
        ZStack {
            if !isVideoFullscreen {
                VStack {
                    HStack{
                        Button(isVideoFullscreen ? "退出全屏" : "Zoom Video") {
                            isVideoFullscreen.toggle()
                        }
                        .padding()
                    }
                    
                    WebView(isVideoFullscreen: $isVideoFullscreen)
                }
                .padding()
            } else {
                // 全屏状态下WebView占满整个视图
                WebView(isVideoFullscreen: $isVideoFullscreen)
                    .edgesIgnoringSafeArea(.all)
                
                // 添加角落退出按钮
                Button("退出全屏") {
                    isVideoFullscreen.toggle()
                }
                .padding()
                .background(Color.black.opacity(0.7))
                .foregroundColor(.white)
                .cornerRadius(8)
                .position(x: 50, y: 50)
            }
        }
    }
}

关键细节说明

  • 状态绑定:通过@Binding实现ContentView与WebView的状态同步,状态变化时自动触发JS执行
  • JS适配:针对通用视频元素编写控制逻辑,若需适配特定网站(如YouTube),可调整元素选择器(比如通过类名定位视频容器)
  • 布局切换:全屏状态下让WebView忽略安全区,隐藏顶部按钮栏,保证视频完全填充视图

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 07:55:32