用一个 Bookmarklet(书签脚本),给任意网页挂一个可拖拽悬浮窗
最近写了一个挺有意思的小工具。
只要点击一下浏览器书签,就能在当前网页右下角弹出一个小窗口直接打开另一个网站。
而且支持:
- 拖拽移动
- 折叠
- 关闭
- iframe 内嵌网页
核心代码大概长这样:
javascript:(()=>{
const IFRAME_URL='https://ruankaodaren.com';
const WIDTH=520,HEIGHT=300;
if(document.getElementById('__mini_window__')) return;
const box=document.createElement('div');
box.id='__mini_window__';
Object.assign(box.style,{
position:'fixed',
right:'24px',
bottom:'24px',
width:WIDTH+'px',
height:HEIGHT+'px',
background:'#fff',
borderRadius:'10px',
boxShadow:'0 10px 30px rgba(0,0,0,.12)',
zIndex:999999,
overflow:'hidden',
fontFamily:'system-ui,-apple-system'
});
const header=document.createElement('div');
Object.assign(header.style,{
height:'32px',
display:'flex',
alignItems:'center',
justifyContent:'flex-end',
padding:'0 8px',
borderBottom:'1px solid #eee',
cursor:'move',
userSelect:'none'
});
const mkBtn=t=>{
const b=document.createElement('button');
b.innerText=t;
Object.assign(b.style,{
width:'28px',
height:'28px',
border:'none',
background:'transparent',
cursor:'pointer',
color:'#666',
fontSize:'16px'
});
return b;
};
const toggle=mkBtn('–'),
close=mkBtn('×');
header.append(toggle,close);
const iframe=document.createElement('iframe');
iframe.src=IFRAME_URL;
Object.assign(iframe.style,{
width:'100%',
height:'calc(100% - 32px)',
border:'none'
});
box.append(header,iframe);
document.body.appendChild(box);
let collapsed=false;
toggle.onclick=()=>{
collapsed=!collapsed;
box.style.height=collapsed?'32px':HEIGHT+'px';
toggle.innerText=collapsed?'+':'–';
};
close.onclick=()=>box.remove();
let dragging=false,sx,sy,sl,st;
header.onmousedown=e=>{
dragging=true;
sx=e.clientX;
sy=e.clientY;
const r=box.getBoundingClientRect();
sl=r.left;
st=r.top;
document.body.style.userSelect='none';
};
document.onmousemove=e=>{
if(!dragging)return;
box.style.left=sl+e.clientX-sx+'px';
box.style.top=st+e.clientY-sy+'px';
box.style.right='auto';
box.style.bottom='auto';
};
document.onmouseup=()=>{
dragging=false;
document.body.style.userSelect='';
};
})();
什么是 Bookmarklet(书签脚本)
很多人第一次看到:
javascript:(()=>{})()
都会有点懵。
其实它本质上就是:
把 JavaScript 当成浏览器书签执行。
也就是说:
普通书签:
https://google.com
会跳转网页。
但 Bookmarklet:
javascript:alert('hello')
点击后会直接执行 JS。
所以它能做很多有意思的事情:
- 自动填写表单
- 网页增强
- 页面调试
- 注入工具
- 快捷操作
- 网页悬浮助手
很多年前流行的玩法了。
这个小工具到底做了什么
整体逻辑其实很简单:
创建一个悬浮 div
↓
顶部做控制栏
↓
里面塞 iframe
↓
支持拖拽 / 折叠 / 关闭
最终效果有点像:
- 在线客服
- AI 助手
- 小窗播放器
- 浏览器侧边工具
这种悬浮 UI。
效果展示:
iframe 才是整个核心
真正关键的是:
iframe.src=IFRAME_URL;
它意味着:
在当前网页里,再打开另一个网页。
于是你就能实现:
- 网页里的 AI 助手
- 小窗文档
- 内部系统快捷入口
- 在线翻译
- 调试工具
甚至可以做:
“网页中的网页”
这也是 iframe 一直到今天还没被淘汰的原因。
拖拽功能其实很有意思
很多人第一次实现拖拽时都会发现:
原来拖拽本质上只是:
“计算鼠标移动距离”
代码核心其实就两步:
记录鼠标按下的位置:
sx=e.clientX;
sy=e.clientY;
然后移动时不断更新:
box.style.left=
sl+e.clientX-sx+'px';
于是元素就“跟着鼠标走”了。
很多 UI 框架里的:
- 弹窗拖拽
- 看板拖拽
- 编辑器拖拽
本质都是这一套。
为什么这种代码很适合练前端基础
因为它没有框架帮你处理。
你会真实接触:
- DOM
- 事件
- 坐标
- 定位
- iframe
- 浏览器行为
这些才是真正的浏览器底层能力。
很多人用 Vue、React 久了。
会逐渐忘记:
前端最终操作的其实一直都是 DOM。
这种东西能拿来干什么
其实用途非常多。
比如:
AI 助手
随时悬浮一个 ChatGPT。
内部系统快捷入口
不用切 Tab。
在线翻译
选中网页直接查。
接口调试
直接小窗打开 Swagger。
开发工具
甚至可以做:
- JSON 格式化
- 代码运行器
- 页面检查工具
但它也有局限性
不是所有网站都能 iframe 打开。
有些网站会主动禁止:
X-Frame-Options
或者:
Content-Security-Policy
这时候 iframe 会直接失效。
所以这种方案:
更适合:
- 自己的网站
- 内部系统
- 可控页面
最后
我一直觉得:
Bookmarklet 是一种很有意思的前端玩法。
它不复杂。
甚至代码量很小。
但你会非常直观地感受到:
浏览器 ≠ 网页浏览工具
浏览器其实本身就是一个运行环境。
而前端开发。
很多时候其实就是:
想办法让浏览器变得更有趣。
这个功能好像缺了点什么?缩放和快捷键?