当前位置: 首页 > news >正文

右侧悬浮ai插件

(function (window) { // 私有作用域,不污染全局 const AI_FLOAT_PLUGIN = function () { // 配置项 const config = { // iframe 地址,外部可修改 iframeSrc: "https://www.baidu.com", // 弹窗宽高 modalWidth: 420, modalHeight: 520, // 悬浮球大小 btnSize: 56, // 主题色 primaryColor: "#1677ff" }; // 拖拽状态 const state = { btnDrag: { isDrag: false, offsetX: 0, offsetY: 0 }, modalDrag: { isDrag: false, startX: 0, startY: 0, startLeft: 0, startTop: 0 } }; // 容器DOM let floatBtn = null; let modalWrap = null; let modalHeader = null; let closeBtn = null; let iframe = null; // ===================== 创建样式 ===================== function createStyle() { const style = document.createElement("style"); style.id = "ai-float-plugin-style"; style.textContent = ` #ai-float-btn { position: fixed; right: 20px; bottom: 120px; width: ${config.btnSize}px; height: ${config.btnSize}px; border-radius: 50%; background: ${config.primaryColor}; box-shadow: 0 4px 12px rgba(22, 119, 255, 0.3); cursor: move; z-index: 99999; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 24px; user-select: none; transition: transform 0.2s; } #ai-float-btn:hover { transform: scale(1.08); } #ai-modal-wrap { position: fixed; width: ${config.modalWidth}px; height: ${config.modalHeight}px; background: #fff; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.2); z-index: 99998; overflow: hidden; display: none; user-select: none; } #ai-modal-header { height: 40px; line-height: 40px; background: ${config.primaryColor}; color: #fff; padding: 0 15px; display: flex; align-items: center; justify-content: space-between; cursor: move; } #ai-modal-close { font-size: 20px; cursor: pointer; padding: 0 8px; } #ai-modal-close:hover { color: #f5f5f5; } #ai-iframe { width: 100%; height: calc(100% - 40px); border: none; } `; document.head.appendChild(style); } // ===================== 创建DOM结构 ===================== function createDom() { // 悬浮按钮 floatBtn = document.createElement("div"); floatBtn.id = "ai-float-btn"; floatBtn.innerText = "AI"; // 弹窗外层 modalWrap = document.createElement("div"); modalWrap.id = "ai-modal-wrap"; // 弹窗头部 modalHeader = document.createElement("div"); modalHeader.id = "ai-modal-header"; modalHeader.innerHTML = `<span>AI智能助手</span>`; // 关闭按钮 closeBtn = document.createElement("span"); closeBtn.id = "ai-modal-close"; closeBtn.innerText = "×"; modalHeader.appendChild(closeBtn); // iframe iframe = document.createElement("iframe"); iframe.id = "ai-iframe"; iframe.src = config.iframeSrc; // 组装 modalWrap.appendChild(modalHeader); modalWrap.appendChild(iframe); // 挂载到body document.body.appendChild(floatBtn); document.body.appendChild(modalWrap); } // ===================== 悬浮球拖拽 ===================== function bindBtnDrag() { floatBtn.addEventListener("mousedown", (e) => { if (e.button !== 0) return; state.btnDrag.isDrag = true; const rect = floatBtn.getBoundingClientRect(); state.btnDrag.offsetX = e.clientX - rect.left; state.btnDrag.offsetY = e.clientY - rect.top; floatBtn.style.transition = "none"; e.preventDefault(); }); document.addEventListener("mousemove", (e) => { if (!state.btnDrag.isDrag) return; const winW = window.innerWidth; const winH = window.innerHeight; const btnW = floatBtn.offsetWidth; const btnH = floatBtn.offsetHeight; let x = e.clientX - state.btnDrag.offsetX; let y = e.clientY - state.btnDrag.offsetY; x = Math.max(0, Math.min(x, winW - btnW)); y = Math.max(0, Math.min(y, winH - btnH)); floatBtn.style.left = x + "px"; floatBtn.style.right = "auto"; floatBtn.style.top = y + "px"; }); document.addEventListener("mouseup", () => { if (state.btnDrag.isDrag) { state.btnDrag.isDrag = false; floatBtn.style.transition = "transform 0.2s"; } }); } // ===================== 点击打开弹窗 ===================== function bindBtnClick() { floatBtn.addEventListener("click", () => { // 拖拽不触发点击 if (state.btnDrag.isDrag) return; modalWrap.style.display = "block"; // 弹窗居中 const winW = window.innerWidth; const winH = window.innerHeight; const mW = modalWrap.offsetWidth; const mH = modalWrap.offsetHeight; modalWrap.style.left = (winW - mW) / 2 + "px"; modalWrap.style.top = (winH - mH) / 2 + "px"; }); } // ===================== 弹窗关闭 ===================== function bindClose() { closeBtn.addEventListener("click", () => { modalWrap.style.display = "none"; }); // ESC关闭 document.addEventListener("keydown", (e) => { if (e.key === "Escape") { modalWrap.style.display = "none"; } }); } // ===================== 弹窗拖拽 ===================== function bindModalDrag() { modalHeader.addEventListener("mousedown", (e) => { if (e.button !== 0) return; state.modalDrag.isDrag = true; state.modalDrag.startX = e.clientX; state.modalDrag.startY = e.clientY; const rect = modalWrap.getBoundingClientRect(); state.modalDrag.startLeft = rect.left; state.modalDrag.startTop = rect.top; e.preventDefault(); }); document.addEventListener("mousemove", (e) => { if (!state.modalDrag.isDrag) return; const winW = window.innerWidth; const winH = window.innerHeight; const mW = modalWrap.offsetWidth; const mH = modalWrap.offsetHeight; const moveX = e.clientX - state.modalDrag.startX; const moveY = e.clientY - state.modalDrag.startY; let newLeft = state.modalDrag.startLeft + moveX; let newTop = state.modalDrag.startTop + moveY; newLeft = Math.max(0, Math.min(newLeft, winW - mW)); newTop = Math.max(0, Math.min(newTop, winH - mH)); modalWrap.style.left = newLeft + "px"; modalWrap.style.top = newTop + "px"; }); document.addEventListener("mouseup", () => { state.modalDrag.isDrag = false; }); } // ===================== 初始化 ===================== function init(options = {}) { // 合并外部配置 Object.assign(config, options); // 防止重复创建 if (document.getElementById("ai-float-btn")) return; createStyle(); createDom(); bindBtnDrag(); bindBtnClick(); bindClose(); bindModalDrag(); } // 对外暴露方法 return { init, // 手动关闭弹窗 closeModal() { if (modalWrap) modalWrap.style.display = "none"; }, // 手动打开弹窗 openModal() { if (modalWrap) modalWrap.style.display = "block"; }, // 更新iframe地址 setIframeSrc(url) { if (iframe) iframe.src = url; }, // 销毁插件 destroy() { const style = document.getElementById("ai-float-plugin-style"); style && style.remove(); floatBtn && floatBtn.remove(); modalWrap && modalWrap.remove(); } }; }; // 挂载到全局,兼容所有框架 window.AiFloatPlugin = AI_FLOAT_PLUGIN(); })(window);
http://www.rkmt.cn/news/1512619.html

相关文章:

  • 告别图片重复烦恼:AntiDupl 2.3.13 终极清理指南
  • 2026防城港市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • 南大通用GBase 8s数据库逻辑日志磁带备份的三个关键配置
  • AS5040磁旋转步进电机-幽冥大陆(一百37)-东方仙盟
  • 工业控制利器:飞思卡尔56F8145 DSC混合架构深度解析与应用实战
  • 5分钟快速掌握LayerDivider:AI图像分层工具的终极指南
  • OLTP vs OLAP:从“点餐”到“盘点”,两种数据库思维一次讲透
  • 一文读懂3D打印机全维度分类(基于Wohlers 2026全球增材制造报告)
  • 探寻生命真谛:在抉择与思考中书写自我答案
  • i茅台自动预约系统:5分钟快速部署,告别手动抢购的终极指南
  • 2026 福州豪宅装修公司排行 豪宅装修公司怎么选不踩坑 - 信息热点
  • 2026鄂州市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • Python网络编程避坑:手把手教你用socket.setsockopt()解决BrokenPipeError
  • 经期女性选什么暖宫腰带?2026实测,深层舒缓经期腹痛 - 资讯报道
  • 3个创意场景:如何用Mi-Create为小米手表设计真正属于你的个性表盘
  • 用 AI 辅助 Bug 排查和测试用例生成:一套适合开发者的可验证工作流
  • DA380三轴振动传感器Linux内核驱动源码(I2C接口,含mir3da.c/h)
  • 百度网盘macOS版下载限速破解指南:告别龟速下载的终极方案
  • Mac百度网盘终极加速指南:3步突破限速实现SVIP高速下载
  • OpenClaw+Serverless 实战:自动生成阿里云函数计算代码、部署无服务应用
  • 2026东营市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • 2026海南广告传媒公司注册避坑指南,四星以上优质财税代办口碑榜单推荐 - 信息热点
  • 【青岛大学IEEE联合主办 | IEEE出版,EI稳定检索,连续多届EI稳定检索 | 征稿主题范围广,EI期刊同步征稿中,高录用】第五届智能电网与能源系统国际学术会议(SGES 2026)
  • 轻量级AI背景移除实战:3大模型对比与移动端部署优化指南
  • CFR Java反编译器深度解析:从字节码迷雾到源码清晰
  • 从MCU到DSC:数字信号控制器如何赋能高性能电源与电机控制
  • 番茄小说下载器终极指南:免费保存番茄小说全攻略
  • 2026海口龙华区靠谱代理记账财税公司专访|五大机构实测评分对比避坑 - 信息热点
  • 终极指南:3分钟掌握d3dxSkinManage,轻松管理游戏皮肤MOD
  • 抖音无水印视频下载终极方案:douyin-downloader完整技术指南