@sanyueqi/web-components
Version:
Web components
179 lines (148 loc) • 6.8 kB
JavaScript
(function (factory) {
typeof define === 'function' && define.amd ? define(factory) :
factory();
})((function () { 'use strict';
/**
* 创建可拖动的Spine动画元素
* @param {Object} config - 配置对象
* @param {string} config.id - div元素的id,默认'drag-waifu'
* @param {string} config.width - div宽度,默认'200px'
* @param {string} config.height - div高度,默认'200px'
* @param {string} config.top - 初始top位置
* @param {string} config.bottom - 初始bottom位置
* @param {string} config.left - 初始left位置
* @param {string} config.right - 初始right位置
* @param {Array} config.spineConfig - Spine动画配置数组
* @returns {Object} 返回包含销毁方法的对象
*/
function createDraggableWaifu(config = {}) {
const {
position = 'fixed',
id = 'drag-waifu',
width = '200px',
height = '200px',
top,
bottom = '0',
left = '0',
right,
spineConfig
} = config;
// 创建可拖动的div元素
const draggableDiv = document.createElement('div');
draggableDiv.id = id;
// 设置div样式 - 使用fixed布局
draggableDiv.style.width = width;
draggableDiv.style.height = height;
draggableDiv.style.position = position;
draggableDiv.style.cursor = 'move';
draggableDiv.style.display = 'flex';
draggableDiv.style.alignItems = 'center';
draggableDiv.style.justifyContent = 'center';
draggableDiv.style.color = 'white';
draggableDiv.style.fontFamily = 'Arial, sans-serif';
draggableDiv.style.fontWeight = 'bold';
draggableDiv.style.userSelect = 'none';
draggableDiv.style.zIndex = '9999'; // 确保在其他元素之上
// 设置初始位置
if (top !== undefined) draggableDiv.style.top = top;
if (bottom !== undefined) draggableDiv.style.bottom = bottom;
if (left !== undefined) draggableDiv.style.left = left;
if (right !== undefined) draggableDiv.style.right = right;
// 添加到页面
document.body.appendChild(draggableDiv);
// 拖拽功能变量
let isDragging = false;
let offsetX, offsetY;
// 鼠标按下事件处理函数
const mouseDownHandler = function(e) {
isDragging = true;
// 计算鼠标在元素内的位置
const rect = draggableDiv.getBoundingClientRect();
offsetX = e.clientX - rect.left;
offsetY = e.clientY - rect.top;
e.preventDefault();
};
// 鼠标移动事件处理函数
const mouseMoveHandler = function(e) {
if (!isDragging) return;
// 计算新位置
let newX = e.clientX - offsetX;
let newY = e.clientY - offsetY;
// 边界检查 - 确保不超出视口
const maxX = window.innerWidth - draggableDiv.offsetWidth;
const maxY = window.innerHeight - draggableDiv.offsetHeight;
newX = Math.max(0, Math.min(newX, maxX));
newY = Math.max(0, Math.min(newY, maxY));
// 应用新位置
draggableDiv.style.left = newX + 'px';
draggableDiv.style.top = newY + 'px';
// 清除其他定位属性
draggableDiv.style.bottom = '';
draggableDiv.style.right = '';
};
// 鼠标松开事件处理函数
const mouseUpHandler = function() {
isDragging = false;
};
// 窗口尺寸变化处理函数
const adjustPosition = function() {
const rect = draggableDiv.getBoundingClientRect();
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
// 如果元素在屏幕外,则调整位置
if (rect.right < 0 || rect.bottom < 0 ||
rect.left > windowWidth || rect.top > windowHeight) {
// 重置到右下角
draggableDiv.style.left = (windowWidth - draggableDiv.offsetWidth) + 'px';
draggableDiv.style.top = (windowHeight - draggableDiv.offsetHeight) + 'px';
draggableDiv.style.bottom = '';
draggableDiv.style.right = '';
} else {
// 确保元素在视口内
let newX = parseFloat(draggableDiv.style.left) || 0;
let newY = parseFloat(draggableDiv.style.top) || 0;
const maxX = windowWidth - draggableDiv.offsetWidth;
const maxY = windowHeight - draggableDiv.offsetHeight;
newX = Math.max(0, Math.min(newX, maxX));
newY = Math.max(0, Math.min(newY, maxY));
draggableDiv.style.left = newX + 'px';
draggableDiv.style.top = newY + 'px';
}
};
// 添加事件监听
draggableDiv.addEventListener('mousedown', mouseDownHandler);
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
window.addEventListener('resize', adjustPosition);
// 初始化Spine动画
const spineManagerDrag = new SpineManager(`#${id}`, id);
spineManagerDrag.init(spineConfig || [], true);
// 返回销毁方法
return {
destroy: function() {
// 移除事件监听
draggableDiv.removeEventListener('mousedown', mouseDownHandler);
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
window.removeEventListener('resize', adjustPosition);
// 移除元素
if (document.body.contains(draggableDiv)) {
document.body.removeChild(draggableDiv);
}
// 销毁Spine管理器
if (spineManagerDrag && typeof spineManagerDrag.destroy === 'function') {
spineManagerDrag.destroy();
}
},
// 暴露调整位置方法供外部调用
adjustPosition: adjustPosition
};
}
// 导出函数
if (typeof module !== 'undefined' && module.exports) {
module.exports = createDraggableWaifu;
}
if (typeof window !== 'undefined') {
window.createDraggableWaifu = createDraggableWaifu;
}
}));