JS 飘窗效果
JS 飘窗效果插件
demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS 飘窗</title>
<script src="./pWindow.js"></script>
<style>
.pWindow {
width: 100px;
height: 200px;
background-color: pink;
}
.pWindow::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 35px;
background-color: #fff;
border: 1px solid #eee;
}
.cancel {
width: 35px;
height: 35px;
position: absolute;
right: 0;
top: 0;
display: flex;
justify-content: center;
align-items: center;
}
.content {
position: absolute;
top: 35px;
width: 100%;
height: calc(100% - 35px);
background-color: orange;
}
</style>
</head>
<body>
<div class="pWindow">
<div class="cancel">×</div>
<div class="content">
<a href="https://www.baidu.com" target="_blank">百度一下</a>
</div>
</div>
</body>
<script>
pWindow({ bayWindowSelector: ".pWindow", cancelSelector: ".cancel", contentSelector: ".content" })
</script>
</html>
pWindow.js文件
/**
*
* @param {:飘窗元素选择器, 取消飘窗按钮元素选择器,内容区元素选择器,鼠标点击时的位置} bayWindow
*/
function pWindow(
bayWindow = {
bayWindowSelector,
cancelSelector,
contentSelector,
mouseOnClickSite,
}
) {
let x = 1,
y = 1,
xStatus = generateRandom() > 0.5 ? -1 : 1,
yStatus = generateRandom() > 0.5 ? -1 : 1,
dom,
domBox,
currentLeft,
currentTop,
clientWidth,
clientHeight,
animationID,
cancelBtn,
content,
clientX,
clientY;
const {
bayWindowSelector,
cancelSelector,
contentSelector,
mouseOnClickSite,
} = bayWindow;
init();
// 初始化函数,初始化飘窗信息
function init() {
dom = document.querySelector(bayWindowSelector);
domBox = dom.getBoundingClientRect();
// 初始化时,飘窗距离浏览器窗口左侧距离,随机生成
const left = generateRandom({
max: document.documentElement.clientWidth - domBox.width,
fixed: 0,
});
// 初始化时,飘窗距离浏览器窗口顶部距离,随机生成
const top = generateRandom({
max: document.documentElement.clientHeight - domBox.height,
fixed: 0,
});
dom.style.cssText = `position:fixed;left:${left}px;top:${top}px;visibility:visible;z-index:99999;`;
start();
// 监听鼠标移入飘窗
dom.addEventListener("mouseenter", mouseenterBayWindow); //已注册在销毁函数中
// 监听鼠标按下后抬起
dom.addEventListener("mouseup", mouseupBayWindow); //已注册在销毁函数中
// 监听鼠标离开飘窗
dom.addEventListener("mouseleave", mouseleaveBayWindow); //已注册在销毁函数中
// 监听鼠标离开飘窗
dom.addEventListener("mouseout", mouseoutBayWindow); //已注册在销毁函数中
// 飘窗内部其他元素事件
// 取消按钮
if (cancelSelector) {
cancelBtn = document.querySelector(cancelSelector);
cancelBtn.addEventListener("mousedown", mousedownCancel); //已注册在销毁函数中
}
// 内容区
if (contentSelector) {
content = document.querySelector(contentSelector);
content.addEventListener("mousedown", mousedownContent); //已注册在销毁函数中
}
}
/**
* 飘窗动画
*/
function start() {
domBox = dom.getBoundingClientRect();
currentLeft = domBox.x;
currentTop = domBox.y;
clientHeight = document.documentElement.clientHeight;
clientWidth = document.documentElement.clientWidth;
if (clientHeight <= currentTop + domBox.height || currentTop < 0) {
yStatus = -yStatus;
}
if (clientWidth <= currentLeft + domBox.width || currentLeft < 0) {
xStatus = -xStatus;
}
// 防止飘窗移动到窗口边界出被吸附开始
if (domBox.left <= 0) {
xStatus = 1;
}
if (domBox.top <= 0) {
yStatus = 1;
}
if (domBox.right >= document.documentElement.clientWidth) {
xStatus = -1;
}
if (domBox.bottom >= document.documentElement.clientHeight) {
yStatus = -1;
}
// 防止飘窗移动到窗口边界出被吸附结束
dom.style.top = (currentTop += y * yStatus) + "px";
dom.style.left = (currentLeft += x * xStatus) + "px";
animationID = requestAnimationFrame(start);
}
/**
* 生成随机函数,可以用做初始化时飘窗位置与移动速度计算
* @param {} obj
* max:最大区间
* fixed:随机数截取小数点位数
* @returns
*/
function generateRandom(obj = { max: 1, fixed: 2 }) {
return +(Math.random() * obj.max).toFixed(obj.fixed);
}
/**
* 飘窗区鼠标进入回调,事件监听回调函数
*/
function mouseenterBayWindow() {
console.log("鼠标进入了");
cancelAnimationFrame(animationID);
dom.addEventListener("mousedown", mousedownMousemove); //已注册在销毁函数中
}
/**
* 飘窗区鼠标点击后抬起,取消mousemove监听事件和飘窗跟随事件
* @param {*} event
*/
function mouseupBayWindow(event) {
console.log("鼠标抬起了");
dom.style.cursor = "default";
dom.removeEventListener("mousemove", mousemoveBayWindow); //已注册在销毁函数中
}
/**
* 飘窗区鼠标离开后,取消mousemove事件监听和飘窗跟随事件
*/
function mouseoutBayWindow() {
console.log("鼠标离开了-事件冒泡");
dom.style.cursor = "default";
dom.removeEventListener("mousemove", mousemoveBayWindow); //已注册在销毁函数中
}
/**
* 飘窗区鼠标离开后,飘窗继续移动动画
* @param {*} event
*/
function mouseleaveBayWindow(event) {
console.log("鼠标离开了");
start();
}
/**
* 取消按钮鼠标点击回调事件,点击后飘窗消失
* @param {*} event
*/
function mousedownCancel(event) {
console.log("点击了取消,鼠标按下了");
destoryEvent();
event.stopPropagation();
// dom.style.cssText = "display:none;";
dom.remove();
}
/**
* 飘窗内容鼠标点击时回调事件,阻止内容点击时事件冒泡
* @param {*} event
*/
function mousedownContent(event) {
event.stopPropagation();
console.log("内容去点击");
}
/**
* 飘窗内容去,鼠标按下未抬起时的回调函数
* @param {*} event
*/
function mousedownMousemove(event) {
console.log("鼠标按下了", event.y);
clientX = event.clientX;
clientY = event.clientY;
dom.style.cursor = "move";
mousemoveBayWindow(event);
dom.addEventListener("mousemove", mousemoveBayWindow); //已注册在销毁函数中
}
/**
* 飘窗跟随鼠标移动事件
* @param {*} event
*/
function mousemoveBayWindow(event) {
let topDistance, leftDistance, bottomDistance, rightDistance;
// 点击飘窗时,鼠标自动位移到飘窗的中心
if (mouseOnClickSite === "center") {
topDistance = event.y - domBox.height / 2;
leftDistance = event.x - domBox.width / 2;
bottomDistance = event.y + domBox.height / 2;
rightDistance = event.x + domBox.width / 2;
if (bottomDistance >= document.documentElement.clientHeight) {
dom.style.top =
document.documentElement.clientHeight - domBox.height + "px";
} else if (topDistance <= 0) {
dom.style.top = "0px";
} else {
dom.style.top = event.y - domBox.height / 2 + "px";
}
if (rightDistance >= document.documentElement.clientWidth) {
dom.style.left =
document.documentElement.clientWidth - domBox.width + "px";
} else if (leftDistance <= 0) {
dom.style.left = "0px";
} else {
dom.style.left = event.x - domBox.width / 2 + "px";
}
} else {
domBox = dom.getBoundingClientRect();
const x = event.clientX - clientX;
const y = event.clientY - clientY;
clientX = event.clientX;
clientY = event.clientY;
if (domBox.bottom > document.documentElement.clientHeight) {
dom.style.top =
document.documentElement.clientHeight - domBox.height + "px";
} else if (domBox.top < 0) {
dom.style.top = "0px";
} else {
dom.style.top = domBox.top + y + "px";
}
if (domBox.right > document.documentElement.clientWidth) {
dom.style.left =
document.documentElement.clientWidth - domBox.width + "px";
} else if (domBox.left < 0) {
dom.style.left = "0px";
} else {
dom.style.left = domBox.left + x + "px";
}
}
}
// 销毁监听事件函数
function destoryEvent() {
dom.removeEventListener("mouseenter", mouseenterBayWindow);
dom.removeEventListener("mouseup", mouseupBayWindow);
dom.removeEventListener("mouseleave", mouseleaveBayWindow);
dom.removeEventListener("mousedown", mousedownMousemove);
dom.removeEventListener("mousemove", mousemoveBayWindow);
dom.removeEventListener("mouseout", mouseoutBayWindow);
cancelBtn.removeEventListener("mousedown", mousedownCancel);
content.removeEventListener("mousedown", mousedownContent);
}
}
分类:
Javascript
, 前端特效
标签:
前端开发第二年
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具