如何在 WKWebView 中注入多个用户脚本以获得暗模式效果?
Posted
技术标签:
【中文标题】如何在 WKWebView 中注入多个用户脚本以获得暗模式效果?【英文标题】:How to inject multiple user scripts in WKWebView to obtain darkmode effect? 【发布时间】:2019-07-09 09:42:42 【问题描述】:我已经使用来自这个伟大的tutorial 的源代码成功地在网站 html 页面上获得了随机 HTML 的暗模式效果。
我上传了这些照片以更好地解释我获得的东西。
我试图在 WKWebView 上获得相同的结果。 HTML 是从 API 加载的,因此我使用 WKWebView.loadHTMLString 方法。 对于此示例,演示 HTML 保存在 Xcode 项目的文件中。 我还在 Xcode 中添加了 2 个 javascript 文件:darkmode.min.js(这是库)和 darkmode-options.js(页面底部切换的位置和文本标签)。 我认为我没有正确注入使用 WKUserScript 的 2 个脚本。显然,darkmode.min.js 必须在 darkmode-options.js 之前加载。这就是我使用 WKUserScriptInjectionTime.atDocumentStart 和 WKUserScriptInjectionTime.atDocumentEnd 的原因。
此外,当我在控制台中打印 HTML 的视图源时,它不会显示已插入的脚本。
private func initWebView()
let html = self.demoHTML
let jsLibrary = self.darkModeLibraryJS
let jsOptions = self.darkModeOptionsJS
let webConfiguration = WKWebViewConfiguration()
let contentController = WKUserContentController()
// Libray script an document start
let userScript = WKUserScript(source: jsLibrary, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
contentController.addUserScript(userScript)
// Options script and document end
let optionsScript = WKUserScript(source: jsOptions, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: false)
contentController.addUserScript(optionsScript)
webConfiguration.userContentController = contentController
self.webview = WKWebView(frame: CGRect.zero, configuration: webConfiguration)
self.webview?.navigationDelegate = self
self.view.addSubview(webview!)
self.webview!.loadHTMLString(html, baseURL: nil)
self.webview!.fillSuperview() // after view has been added as subview
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
self.chechHTML()
private func chechHTML()
let script = "document.documentElement.outerHTML.toString()"
self.webview?.evaluateJavaScript(script, completionHandler: (html, error) in
if html != nil
print("❌: check html response", html ?? "")
if error != nil
print("❌: check html with error", error ?? "")
)
项目上传到github:https://github.com/CristiGhn/darkmode-webview。 Xcode 项目还包含一个 darkmode.html,它的工作原理与上面的照片完全相同。
谢谢!
【问题讨论】:
我刚刚在 darkmode-options.js 中添加了一些步骤日志。它一直正确执行,直到 darkmode = new Darkmode(options);但在此调用中崩溃。所以我猜你的 swift 是正确的,但是 darkmode.min.js 脚本有一些不适合 ios 模拟器的功能。 【参考方案1】:使用这个tutorial,我使用 mix-blend-mode: difference 实现了效果。
在文档开始和文档结束的webiew中注入多个WKUserScript:
-
在文档开始时具有切换功能的 JavaScript 文件
注入带有背景和搅拌器的 div 容器,这将产生不同的混合效果(在文档末尾)
文档末尾CSS文件的内部样式标签内容
let webConfiguration = WKWebViewConfiguration()
let contentController = WKUserContentController()
// Libray script an document start
let darkModeScript = WKUserScript(source: self.darkModeLibraryJS, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
contentController.addUserScript(darkModeScript)
let injectDarkModeScript = WKUserScript(source: self.injectDarkModeJS, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: false)
contentController.addUserScript(injectDarkModeScript)
let injectCSScript = WKUserScript(source: self.injectCSS, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: false)
contentController.addUserScript(injectCSScript)
webConfiguration.userContentController = contentController
self.webview = WKWebView(frame: CGRect.zero, configuration: webConfiguration)
self.webview?.navigationDelegate = self
self.view.addSubview(webview!)
self.webview!.loadHTMLString(html, baseURL: nil)
带有切换功能的 JavaScript 和注入 CSS (darkmode.js)
function injectCSS(css)
head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
head.appendChild(style);
style.type = 'text/css';
if (style.styleSheet)
// This is required for IE8 and below.
style.styleSheet.cssText = css;
else
style.appendChild(document.createTextNode(css));
function showDarkMode()
var blender = document.getElementById('blender')
if (blender.hasAttribute("hidden"))
blender.removeAttribute("hidden")
function showOriginalMode()
var blender = document.getElementById('blender')
if (!blender.hasAttribute("hidden"))
blender.setAttribute("hidden", true)
将 div 容器添加到 webview 的 DOM 的 JavaScript (inject-darkmode.js)
var container = document.createElement('div')
container.id = 'darkmode-container'
document.body.appendChild(container)
var background = document.createElement('div')
background.classList.add('darkmode-background')
container.appendChild(background)
var blender = document.createElement('div')
blender.id = 'blender'
blender.setAttribute('hidden', true)
container.appendChild(blender)
用于定义搅拌器和背景的 CSS (darkmode.css)
#blender
width: 100vw;
height: 100vh;
left: 0pt;
top: 0pt;
position: fixed;
background: white;
transition: all 1s ease;
mix-blend-mode: difference;
img
isolation: isolate;
.darkmode-background
position: fixed;
background: white;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: -1;
带有工作项目的存储库:https://github.com/CristiGhn/darkmode-webview
【讨论】:
以上是关于如何在 WKWebView 中注入多个用户脚本以获得暗模式效果?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 3 的 WKWebView 中注入 javascript
如何在 iOS webview 的多个页面中注入/评估 JS?
如何使用 iOS WKWebView 注入 JavaScript 回调来检测 onclick 事件?
如何在没有 JavaScript 的情况下将 cookie 注入 WKWebView 或 WKWebSiteDataStore?