当前位置:首页 > HTML打包EXE > 正文内容

HTML打包EXE透明窗口教程 - 打造炫酷无边框透明桌面应用

使用HTML打包EXE工具的无边框窗口功能,结合CSS透明背景和 -webkit-app-region 拖动属性,可以打造出炫酷的透明桌面应用程序。告别千篇一律的标准窗口,让你的应用拥有独特的视觉风格。

下载最新版本

实现原理

透明窗口的实现需要两个关键步骤配合:

  1. 打包工具端:勾选「无边框窗口」选项,去掉系统默认的标题栏和窗口边框

  2. HTML/CSS端:将页面背景设为透明,让窗口呈现透明效果;同时使用 -webkit-app-region: drag 让用户可以拖动窗口

打包工具配置

在打包工具主界面切换到高级配置标签页,勾选无边框窗口选项:

勾选无边框窗口

配置项说明
无边框窗口勾选后,打包的EXE文件将没有窗口边框和标题栏

提示:勾选无边框窗口后,系统自带的标题栏(包括最小化、最大化、关闭按钮)将被移除,需要在HTML中自行实现这些功能。

设置透明背景

在HTML文件中,将 htmlbody 的背景色设置为透明:

html,
body {
    margin: 0;
    padding: 0;
    background: transparent !important;
}

这样窗口中没有内容覆盖的区域将直接透明,可以看到桌面背景。

实现窗口拖动

无边框窗口去掉了系统标题栏,用户无法通过标题栏拖动窗口。此时需要使用 -webkit-app-region 属性来指定可拖动区域:

/* 设置整个容器可拖动 */
.drag-area {
    -webkit-app-region: drag;
}

/* 按钮、输入框等交互元素需要排除拖动,否则无法点击 */
button,
input,
a,
.no-drag {
    -webkit-app-region: no-drag;
}

关键规则

属性值说明
drag设置该区域可以拖动窗口,类似系统标题栏的效果
no-drag排除该区域的拖动行为,使其可以正常点击和交互

注意:被设置为 drag 的区域将无法响应鼠标点击事件。因此按钮、链接、输入框等需要交互的元素,必须单独设置 no-drag,否则用户将无法点击。

自定义关闭/最小化按钮

去掉系统标题栏后,需要自己实现窗口控制按钮。可以通过开启API支持来调用窗口控制功能:

  1. 在高级配置中勾选 开启API支持

  2. 在HTML中使用以下JS API控制窗口:

// 最小化窗口
window.HTMLPackHelper.minimize();

// 最大化/还原窗口
window.HTMLPackHelper.maximize();

// 恢复窗口大小
window.HTMLPackHelper.restore();

// 关闭窗口
window.HTMLPackHelper.close();

完整示例:赛博朋克桌面时钟

下面是一个赛博朋克风格的透明桌面时钟组件,带有霓虹灯光效、扫描线动画和实时时钟,可以直接用于打包:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Cyber Clock</title>
        <style>
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }

            html,
            body {
                background: transparent !important;
                height: 100%;
                font-family: 'Consolas', 'Courier New', monospace;
                overflow: hidden;
                -webkit-user-select: none;
                user-select: none;
            }

            .panel {
                width: 100%;
                height: 100%;
                display: flex;
                flex-direction: column;
                border: 1px solid rgba(0, 255, 200, 0.25);
                background: rgba(0, 10, 15, 0.85);
                position: relative;
            }

            /* 扫描线动画 */
            .panel::after {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                height: 2px;
                background: linear-gradient(
                    90deg,
                    transparent,
                    rgba(0, 255, 200, 0.4),
                    transparent
                );
                animation: scanline 3s linear infinite;
                pointer-events: none;
                z-index: 10;
            }
            @keyframes scanline {
                0% {
                    top: 0;
                    opacity: 1;
                }
                50% {
                    opacity: 0.5;
                }
                100% {
                    top: 100%;
                    opacity: 0;
                }
            }

            /* 顶栏 - 可拖动 */
            .top-bar {
                -webkit-app-region: drag;
                display: flex;
                align-items: center;
                justify-content: space-between;
                padding: 8px 14px;
                border-bottom: 1px solid rgba(0, 255, 200, 0.12);
                flex-shrink: 0;
            }
            .top-bar .sys-label {
                font-size: 10px;
                color: rgba(0, 255, 200, 0.5);
                letter-spacing: 3px;
                text-transform: uppercase;
            }
            .top-bar .dot {
                display: inline-block;
                width: 6px;
                height: 6px;
                border-radius: 50%;
                background: #0fa;
                margin-right: 8px;
                box-shadow: 0 0 6px #0fa;
                animation: blink 2s ease infinite;
            }
            @keyframes blink {
                0%,
                100% {
                    opacity: 1;
                }
                50% {
                    opacity: 0.3;
                }
            }

            /* 窗口按钮 */
            .win-btns {
                display: flex;
                gap: 6px;
                -webkit-app-region: no-drag;
            }
            .win-btns button {
                width: 18px;
                height: 18px;
                border: 1px solid rgba(0, 255, 200, 0.25);
                background: transparent;
                color: rgba(0, 255, 200, 0.6);
                font-size: 10px;
                cursor: pointer;
                display: flex;
                align-items: center;
                justify-content: center;
                transition: all 0.15s;
            }
            .win-btns button:hover {
                background: rgba(0, 255, 200, 0.12);
                border-color: rgba(0, 255, 200, 0.6);
                color: #0fa;
            }
            .win-btns .btn-x:hover {
                background: rgba(255, 60, 60, 0.2);
                border-color: rgba(255, 60, 60, 0.6);
                color: #ff5050;
            }

            /* 时钟主体 */
            .clock-body {
                flex: 1;
                display: flex;
                flex-direction: column;
                align-items: center;
                justify-content: center;
                padding: 0 24px;
            }
            .time {
                font-size: 64px;
                font-weight: 700;
                color: #0fa;
                letter-spacing: 4px;
                text-shadow: 0 0 20px rgba(0, 255, 200, 0.35);
                font-variant-numeric: tabular-nums;
                line-height: 1;
            }
            .time .colon {
                animation: blink 1s step-end infinite;
            }
            .date-row {
                margin-top: 8px;
                font-size: 13px;
                color: rgba(0, 255, 200, 0.4);
                letter-spacing: 2px;
            }

            /* 分隔线 */
            .sep {
                margin: 0 24px;
                height: 1px;
                background: linear-gradient(
                    90deg,
                    transparent,
                    rgba(0, 255, 200, 0.2),
                    transparent
                );
                flex-shrink: 0;
            }

            /* 底部信息 */
            .info-grid {
                display: grid;
                grid-template-columns: 1fr 1fr 1fr;
                gap: 0;
                padding: 12px 24px;
                text-align: center;
                flex-shrink: 0;
            }
            .info-item {
                padding: 6px 0;
            }
            .info-item:not(:last-child) {
                border-right: 1px solid rgba(0, 255, 200, 0.08);
            }
            .info-val {
                font-size: 18px;
                color: #0fa;
                font-weight: 700;
                display: block;
            }
            .info-label {
                font-size: 9px;
                color: rgba(0, 255, 200, 0.35);
                letter-spacing: 2px;
                text-transform: uppercase;
                margin-top: 4px;
                display: block;
            }
        </style>
    </head>
    <body>
        <div class="panel">
            <div class="top-bar">
                <span><span class="dot"></span><span class="sys-label">System Monitor</span></span>
                <div class="win-btns">
                    <button onclick="window.HTMLPackHelper.minimize()">─</button>
                    <button class="btn-x" onclick="window.HTMLPackHelper.close()">✕</button>
                </div>
            </div>

            <div class="clock-body">
                <div class="time" id="clock">
                    00<span class="colon">:</span>00<span class="colon">:</span>00
                </div>
                <div class="date-row" id="date-row">----/--/--</div>
            </div>

            <div class="sep"></div>

            <div class="info-grid">
                <div class="info-item">
                    <span class="info-val" id="run-time">00:00</span>
                    <span class="info-label">运行时长</span>
                </div>
                <div class="info-item">
                    <span class="info-val" id="fps">--</span>
                    <span class="info-label">FPS</span>
                </div>
                <div class="info-item">
                    <span class="info-val" id="mem">-- MB</span>
                    <span class="info-label">内存</span>
                </div>
            </div>
        </div>

        <script>
            const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
            const startTime = Date.now();
            let frames = 0,
                lastFpsTime = Date.now(),
                currentFps = 0;

            function pad(n) {
                return n < 10 ? '0' + n : n;
            }

            function tick() {
                const now = new Date();
                document.getElementById('clock').innerHTML =
                    pad(now.getHours()) +
                    '<span class="colon">:</span>' +
                    pad(now.getMinutes()) +
                    '<span class="colon">:</span>' +
                    pad(now.getSeconds());

                document.getElementById('date-row').textContent =
                    now.getFullYear() +
                    '/' +
                    pad(now.getMonth() + 1) +
                    '/' +
                    pad(now.getDate()) +
                    '  星期' +
                    weekdays[now.getDay()];

                // 运行时长
                const elapsed = Math.floor((Date.now() - startTime) / 1000);
                const m = Math.floor(elapsed / 60),
                    s = elapsed % 60;
                document.getElementById('run-time').textContent = pad(m) + ':' + pad(s);

                // FPS
                frames++;
                if (Date.now() - lastFpsTime >= 1000) {
                    currentFps = frames;
                    frames = 0;
                    lastFpsTime = Date.now();
                }
                document.getElementById('fps').textContent = currentFps || '--';

                // 内存
                if (performance.memory) {
                    const mb = (performance.memory.usedJSHeapSize / 1048576).toFixed(1);
                    document.getElementById('mem').textContent = mb + ' MB';
                }

                requestAnimationFrame(tick);
            }
            requestAnimationFrame(tick);
        </script>
    </body>
</html>

打包配置要点

使用上面的HTML打包时,需要在打包工具中做以下配置:

  1. 快速打包页面:选择该HTML文件作为本地主文件

  2. 高级配置页面:

    • ✅ 勾选 无边框窗口

    • ✅ 勾选 开启API支持(用于窗口控制按钮)

    • ✅ 勾选 置顶窗口, 可以让整个html时钟始终显示在最前面

    • 窗口大小建议设为 宽度 350高度 200

  3. 内核选择 Chrome内核(透明效果仅Chrome内核支持)

效果预览

打包后运行效果如下,赛博朋克风格的时钟面板悬浮在桌面上,带有扫描线动画和霓虹灯光效果:

透明窗口效果

进阶技巧

1. 只让部分区域可拖动

如果只想让标题栏可拖动,其余区域正常交互:

/* 仅标题栏可拖动 */
.title-bar {
    -webkit-app-region: drag;
}

/* 标题栏内的按钮排除拖动 */
.title-bar button {
    -webkit-app-region: no-drag;
}

2. 半透明磨砂背景

可以在深色背景上使用 rgbabackdrop-filter 实现层叠的半透明磨砂效果:

.container {
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
}

3. 异形窗口效果

利用 border-radius 制作圆角甚至圆形窗口:

.card {
    border-radius: 20px; /* 圆角矩形 */
}

.circle-window {
    border-radius: 50%; /* 圆形窗口 */
    width: 300px;
    height: 300px;
}

4. 窗口阴影效果

可以用CSS阴影为内部元素添加浮层感:

.card {
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
}

注意事项

  • 透明窗口效果仅Chrome内核支持,IE内核不支持

  • 勾选无边框窗口后,系统标题栏将被移除,请务必自行添加关闭按钮

  • 透明区域可以穿透点击到桌面或下层窗口

  • 使用 -webkit-app-region: drag 的区域无法响应鼠标事件,交互元素需设为 no-drag

  • 建议搭配 开启API支持 使用,方便调用窗口最小化、最大化、关闭等功能

相关阅读

扫描二维码推送至手机访问。

版权声明:本文由H5开发工具网站发布,如需转载请注明出处。

如您需要下载软件, 可以点击进入官方软件网址


本文链接:https://www.h5pack.com/post//html2exe-transparent-window-guide.html