[js] 在面包屑旁添加全屏按钮,快捷切换全屏

本贴最后更新于 230 天前,其中的信息可能已经时移世改

效果是在面包屑旁添加一个全屏按钮,快捷切换页签的全屏状态:

JS 片段:

// 在面包屑旁添加全屏按钮,快捷切换全屏 JS片段 // author by JeffreyChen https://ld246.com/article/1731698559408 // 参考 @wilsons 的方法进行了优化 https://ld246.com/article/1731683038390/comment/1731693866270#comments ,不再需要全屏切换快捷键 (function() { function addFullScreenButton(protyleElement) { // 检查该 protyle 是否已经有了 fullScreen_simulate 按钮 if (protyleElement.querySelector('.fullScreen_simulate')) { return; // 如果已存在,直接返回 } let mode = protyleElement.querySelector('.protyle-breadcrumb .block__icon[data-type="readonly"]'); if (mode) { mode.insertAdjacentHTML( "beforebegin", '<button class="fullScreen_simulate block__icon fn__flex-center ariaLabel" aria-label="全屏切换"></button>' ); let fullScreenBtn = protyleElement.querySelector(".fullScreen_simulate"); fullScreenBtn.innerHTML = `<svg><use xlink:href="#iconFullscreen"></use></svg>`; fullScreenBtn.addEventListener("click", function (e) { // 获取 .layout-tab-container > .protyle .protyle-breadcrumb__space 元素 const breadcrumbSpace = protyleElement.querySelector('.protyle-breadcrumb__space'); // 如果元素存在,则模拟点击,聚焦当前页签 if (breadcrumbSpace) { breadcrumbSpace.click(); } toggleFullScreen(protyleElement, fullScreenBtn); // 切换全屏状态 }); } } // 切换全屏状态的函数 function toggleFullScreen(protyle, fullScreenBtn) { if (!window.siyuan.editorIsFullscreen) { enterFullScreen(protyle, fullScreenBtn); } else { exitFullScreen(protyle, fullScreenBtn); } } function enterFullScreen(protyle, fullScreenBtn) { protyle.classList.add("fullscreen"); window.siyuan.editorIsFullscreen = true; updateFullScreenButton(fullScreenBtn, true); // 更新按钮 } function exitFullScreen(protyle, fullScreenBtn) { protyle.classList.remove("fullscreen"); window.siyuan.editorIsFullscreen = false; updateFullScreenButton(fullScreenBtn, false); // 更新按钮 } function updateFullScreenButton(fullScreenBtn, isFullScreen) { const iconUse = fullScreenBtn.querySelector('use'); // 切换图标 iconUse.setAttribute('xlink:href', isFullScreen ? '#iconFullscreenExit' : '#iconFullscreen'); fullScreenBtn.setAttribute('aria-label', isFullScreen ? '退出全屏' : '全屏'); } // 定期检查 .layout__center 是否存在于 DOM 中 function checkForLayoutCenter() { const targetNode = document.querySelector('.layout__center'); if (targetNode) { startObserving(targetNode); // 立即检查一次 protyle-breadcrumb checkProtyleElements(targetNode); } else { setTimeout(checkForLayoutCenter, 200); } } function checkProtyleElements(targetNode) { const protyles = targetNode.querySelectorAll('.layout-tab-container > .protyle'); protyles.forEach(protyle => { addFullScreenButton(protyle); }); } function startObserving(targetNode) { const observer = new MutationObserver((mutations) => { mutations.forEach(mutation => { if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { // 检查添加的节点是否是 .protyle 元素 if (node.nodeType === 1 && node.matches('.layout-tab-container > .protyle')) { addFullScreenButton(node); } }); } else if (mutation.type === 'attributes' && mutation.target.matches('.layout-tab-container > .protyle')) { // 如果已有的 protyle 的类名发生变化,尝试添加全屏按钮 addFullScreenButton(mutation.target); } }); }); // 配置并开始观察 const config = { childList: true, subtree: true, attributes: true }; observer.observe(targetNode, config); } checkForLayoutCenter(); })();
旧方案(全屏切换需要设置快捷键)
// 在面包屑旁添加全屏按钮,快捷切换全屏 JS片段 // author by JeffreyChen https://ld246.com/article/1731698559408 // 注意:需要为全屏切换设置一个快捷键 (function() { function addFullScreenButton(protyleElement) { // 检查该 protyle 是否已经有了 fullScreen_simulate 按钮 if (protyleElement.querySelector('.fullScreen_simulate')) { return; // 如果已存在,直接返回 } let mode = protyleElement.querySelector('.protyle-breadcrumb .block__icon[data-type="readonly"]'); if (mode) { mode.insertAdjacentHTML( "beforebegin", '<button class="fullScreen_simulate block__icon fn__flex-center ariaLabel" aria-label="全屏切换"></button>' ); let fullScreenBtn = protyleElement.querySelector(".fullScreen_simulate"); fullScreenBtn.innerHTML = `<svg><use xlink:href="#iconFullscreen"></use></svg>`; fullScreenBtn.addEventListener("click", function (e) { // 获取 .layout-tab-container > .protyle .protyle-breadcrumb__space 元素 const breadcrumbSpace = protyleElement.querySelector('.protyle-breadcrumb__space'); // 如果元素存在,则模拟点击,聚焦当前页签 if (breadcrumbSpace) { breadcrumbSpace.click(); } dispatchKeyEvent(); // 切换图标 const iconUse = fullScreenBtn.querySelector('use'); if (iconUse.getAttribute('xlink:href') === '#iconFullscreen') { iconUse.setAttribute('xlink:href', '#iconFullscreenExit'); } else { iconUse.setAttribute('xlink:href', '#iconFullscreen'); } }); } } function dispatchKeyEvent() { let keyInit = parseHotKeyStr(window.top.siyuan.config.keymap.editor.general.fullscreen.custom); keyInit["bubbles"] = true; let keydownEvent = new KeyboardEvent('keydown', keyInit); document.getElementsByTagName("body")[0].dispatchEvent(keydownEvent); let keyUpEvent = new KeyboardEvent('keyup', keyInit); document.getElementsByTagName("body")[0].dispatchEvent(keyUpEvent); } /** * @param {*} hotkeyStr 思源hotkey格式 Refer: https://github.com/siyuan-note/siyuan/blob/d0f011b1a5b12e5546421f8bd442606bf0b5ad86/app/src/protyle/util/hotKey.ts#L4 * @returns KeyboardEventInit Refer: https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/KeyboardEvent */ function parseHotKeyStr(hotkeyStr) { let result = { ctrlKey: false, altKey: false, metaKey: false, shiftKey: false, key: 'A', keyCode: 0 } if (hotkeyStr == "" || hotkeyStr == undefined || hotkeyStr == null) { console.error("解析快捷键设置失败", hotkeyStr); throw new Error("解析快捷键设置失败"); } let onlyKey = hotkeyStr; if (hotkeyStr.indexOf("⌘") != -1) { result.ctrlKey = true; onlyKey = onlyKey.replace("⌘", ""); } if (hotkeyStr.indexOf("⌥") != -1) { result.altKey = true; onlyKey = onlyKey.replace("⌥", ""); } if (hotkeyStr.indexOf("⇧") != -1) { result.shiftKey = true; onlyKey = onlyKey.replace("⇧", ""); } // 未处理 windows btn (MetaKey) result.key = onlyKey; // 在https://github.com/siyuan-note/siyuan/commit/70acd57c4b4701b973a8ca93fadf6c003b24c789#diff-558f9f531a326d2fd53151e3fc250ac4bd545452ba782b0c7c18765a37a4e2cc // 更改中,思源改为使用keyCode判断快捷键按下事件,这里进行了对应的转换 // 另请参考该提交中涉及的文件 result.keyCode = keyCodeList[result.key]; console.assert(result.keyCode != undefined, `keyCode转换错误,key为${result.key}`); switch (result.key) { case "→": { result.key = "ArrowRight"; break; } case "←": { result.key = "ArrowLeft"; break; } case "↑": { result.key = "ArrowUp"; break; } case "↓": { result.key = "ArrowDown"; break; } case "⌦": { result.key = "Delete"; break; } case "⌫": { result.key = "Backspace"; break; } case "↩": { result.key = "Enter"; break; } } return result; } const keyCodeList = { "⌫": 8, "⇥": 9, "↩": 13, "⇧": 16, "⌘": 91, "⌥": 18, "Pause": 19, "CapsLock": 20, "Escape": 27, " ": 32, "PageUp": 33, "PageDown": 34, "End": 35, "Home": 36, "←": 37, "↑": 38, "→": 39, "↓": 40, "PrintScreen": 44, "Insert": 45, "⌦": 46, "0": 48, "1": 49, "2": 50, "3": 51, "4": 52, "5": 53, "6": 54, "7": 55, "8": 56, "9": 57, "A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70, "G": 71, "H": 72, "I": 73, "J": 74, "K": 75, "L": 76, "M": 77, "N": 78, "O": 79, "P": 80, "Q": 81, "R": 82, "S": 83, "T": 84, "U": 85, "V": 86, "W": 87, "X": 88, "Y": 89, "Z": 90, "ContextMenu": 93, "MyComputer": 182, "MyCalculator": 183, ";": 186, "=": 187, ",": 188, "-": 189, ".": 190, "/": 191, "`": 192, "[": 219, "\\": 220, "]": 221, "'": 222, "*": 106, "+": 107, "-": 109, ".": 110, "/": 111, "F1": 112, "F2": 113, "F3": 114, "F4": 115, "F5": 116, "F6": 117, "F7": 118, "F8": 119, "F9": 120, "F10": 121, "F11": 122, "F12": 123, "NumLock": 144, "ScrollLock": 145 }; // 定期检查 .layout__center 是否存在于 DOM 中 function checkForLayoutCenter() { const targetNode = document.querySelector('.layout__center'); if (targetNode) { startObserving(targetNode); // 立即检查一次 protyle-breadcrumb checkProtyleElements(targetNode); } else { setTimeout(checkForLayoutCenter, 200); } } function checkProtyleElements(targetNode) { const protyles = targetNode.querySelectorAll('.layout-tab-container > .protyle'); protyles.forEach(protyle => { addFullScreenButton(protyle); }); } function startObserving(targetNode) { const observer = new MutationObserver((mutations) => { mutations.forEach(mutation => { if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { // 检查添加的节点是否是 .protyle 元素 if (node.nodeType === 1 && node.matches('.layout-tab-container > .protyle')) { addFullScreenButton(node); } }); } else if (mutation.type === 'attributes' && mutation.target.matches('.layout-tab-container > .protyle')) { // 如果已有的 protyle 的类名发生变化,尝试添加全屏按钮 addFullScreenButton(mutation.target); } }); }); // 配置并开始观察 const config = { childList: true, subtree: true, attributes: true }; observer.observe(targetNode, config); } checkForLayoutCenter(); })();
打赏 50 积分后可见
50 积分 • 6 打赏
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    26187 引用 • 108800 回帖 • 1 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    194 引用 • 1388 回帖
2 操作
JeffreyChen 在 2024-11-16 03:51:10 更新了该帖
JeffreyChen 在 2024-11-16 03:49:59 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
JeffreyChen
思源笔记同步教程:https://ld246.com/article/1692089679062 爱发电:https://afdian.com/a/JeffreyChen

推荐标签 标签

  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    181 引用 • 400 回帖
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 678 关注
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    82 引用 • 412 回帖
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 50 关注
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 736 关注
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    440 引用 • 1238 回帖 • 593 关注
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    36 引用 • 200 回帖 • 36 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 585 回帖 • 1 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • AWS
    11 引用 • 28 回帖 • 7 关注
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 37 关注
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    142 引用 • 442 回帖
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    17 引用 • 7 回帖
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    167 引用 • 597 回帖 • 1 关注
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 823 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    26186 引用 • 108799 回帖 • 1 关注
  • 安全

    安全永远都不是一个小问题。

    199 引用 • 818 回帖
  • 工具

    子曰:“工欲善其事,必先利其器。”

    300 引用 • 768 回帖
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    91 引用 • 384 回帖 • 1 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 38 关注
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    4 引用 • 7 回帖
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 312 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖
  • Office

    Office 现已更名为 Microsoft 365. Microsoft 365 将高级 Office 应用(如 Word、Excel 和 PowerPoint)与 1 TB 的 OneDrive 云存储空间、高级安全性等结合在一起,可帮助你在任何设备上完成操作。

    5 引用 • 34 回帖 • 2 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    89 引用 • 113 回帖