From 157ca32e2d75d1875ea84d6a1e92a37bb4290f8b Mon Sep 17 00:00:00 2001 From: yuantao Date: Tue, 12 Aug 2025 00:35:26 +0800 Subject: [PATCH] =?UTF-8?q?'=E4=BD=BF=E7=94=A8deepseek=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E4=BA=86=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91=EF=BC=9B'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.js | 497 ++++++++++++++++++++----------------------------------- 1 file changed, 180 insertions(+), 317 deletions(-) diff --git a/index.js b/index.js index fa52c74..85b23e7 100644 --- a/index.js +++ b/index.js @@ -1,354 +1,217 @@ +class BaseElement { + constructor(elementType = 'div', engineId) { + this.element = document.createElement(elementType) + this.element.style.position = 'absolute' + this.engineId = engineId + this.x = 0 + this.y = 0 + this.width = 0 + this.height = 0 + } + + setPosition(x = 0, y = 0) { + this.element.style.left = `${x}px` + this.element.style.top = `${y}px` + this.x = x + this.y = y + } + + setSize(width = 0, height = 0) { + if (width) { + this.element.style.width = typeof width === 'number' ? `${width}px` : width + this.width = width + } + if (height) { + this.element.style.height = typeof height === 'number' ? `${height}px` : height + this.height = height + } + } + + setStyle(style) { + Object.assign(this.element.style, style) + } + + add(child) { + child && this.element.appendChild(child.element || child) + } + + remove(child) { + child && this.element.removeChild(child.element || child) + } + + on(event, callback) { + this.element.addEventListener(event, callback) + } + + off(event, callback) { + this.element.removeEventListener(event, callback) + } + + hide() { + this.element.style.display = 'none' + } + + show() { + this.element.style.display = 'block' + } +} + +class Sprite extends BaseElement { + constructor(img, x, y, width, height, engineId) { + super('div', engineId) + this.imgElement = document.createElement('img') + this.imgElement.src = img.src + this.imgElement.style.cssText = '-webkit-user-drag: none; user-drag: none;' + this.element.appendChild(this.imgElement) + + this.setPosition(x, y) + this.setSize(width, height) + this.element.setAttribute('data-sprite-id', engineId) + + // 精灵特有方法 + this.name = name => this.element.setAttribute('data-name', name) + this.animate = keyframes => (this.element.style.animation = keyframes) + } +} + +class Box extends BaseElement { + constructor(x, y, width, height, engineId) { + super('div', engineId) + this.setPosition(x, y) + this.setSize(width, height) + this.element.setAttribute('data-box-id', engineId) + } +} + +class TextElement extends BaseElement { + constructor(text, x, y, engineId) { + super('div', engineId) + this.element.innerText = text + this.setPosition(x, y) + this.element.setAttribute('data-text-id', engineId) + + // 文本特有方法 + this.set = text => (this.element.innerText = text) + this.setColor = color => (this.element.style.color = color) + this.setFont = font => (this.element.style.font = font) + } +} + +class HtmlElement extends BaseElement { + constructor(html, x, y, engineId) { + super('div', engineId) + this.element.innerHTML = html + this.setPosition(x, y) + this.element.setAttribute('data-html-id', engineId) + + // HTML特有方法 + this.set = html => (this.element.innerHTML = html) + this.get = () => this.element.innerHTML + this.getSize = () => { + const rect = this.element.getBoundingClientRect() + return { width: rect.width, height: rect.height } + } + } +} + +class SvgElement extends BaseElement { + constructor(x, y, width, height, content, engineId) { + super('div', engineId) + this.element.innerHTML = content + this.setPosition(x, y) + this.setSize(width, height) + this.element.setAttribute('data-svg-id', engineId) + + // SVG特有方法 + this.setContent = content => (this.element.innerHTML = content) + } +} + class Engine { constructor(element = document.body, options = {}) { - // 默认配置 const defaultOptions = { - // 舞台宽度 width: 800, - // 舞台高度 height: 600, - // 舞台背景颜色 background: 'transparent', } - // 合并配置 + this.options = { ...defaultOptions, ...options } this.images = [] this.width = this.options.width this.height = this.options.height + this.element = typeof element === 'string' ? document.querySelector(element) : element + this.id = Date.now().toString(16) - // 创建舞台 - this.element = document.querySelector(element) + this.createStage() + } + + createStage() { this.stage = document.createElement('div') - // 引擎ID - const engineId = new Date().getTime() - // 转换为16进制 - const engineIdHex = engineId.toString(16) - this.id = engineIdHex this.stage.setAttribute('data-engine-id', this.id) - // 设置舞台样式 - this.stage.style.width = `${this.options.width}px` - this.stage.style.height = `${this.options.height}px` - this.stage.style.position = 'relative' - this.stage.style.userSelect = 'none' - this.stage.style.overflow = 'hidden' - this.stage.style.background = this.options.background - // 启用硬件加速 - this.stage.style.transform = 'translateZ(0)' - // 添加子元素 - this.stage.add = function (child) { - child && this.appendChild(child) - } - // 移除子元素 - this.stage.remove = function (child) { - child && this.removeChild(child) - } + Object.assign(this.stage.style, { + width: `${this.options.width}px`, + height: `${this.options.height}px`, + position: 'relative', + userSelect: 'none', + overflow: 'hidden', + background: this.options.background, + transform: 'translateZ(0)', + }) + + // 添加舞台操作方法 + this.stage.add = child => child && this.stage.appendChild(child.element || child) + this.stage.remove = child => child && this.stage.removeChild(child.element || child) this.element.appendChild(this.stage) - return this } - // 加载资源 - Load(src = '') { + + load(src = '') { return new Promise((resolve, reject) => { - let img = new Image() + const img = new Image() img.src = src - img.onload = () => { - resolve(img) - } - img.onerror = e => { - reject(e) - } + img.onload = () => resolve(img) + img.onerror = reject + this.images.push(img) }) } - // 创建精灵 - CreateSprite(img, x = 0, y = 0, width = 0, height = 0) { - const div = document.createElement('div') - const imgElement = document.createElement('img') - imgElement.src = img.src - imgElement.style.cssText = '-webkit-user-drag: none;user-drag: none;' - div.style.position = 'absolute' - div.setAttribute('data-sprite-id', this.id) - div.appendChild(imgElement) - this.images.push(imgElement) - - // 设置图片位置 - div.setPosition = function (x = 0, y = 0) { - div.style.left = `${x}px` - div.style.top = `${y}px` - div.x = x - div.y = y - } - div.setPosition(x, y) - // 设置图片尺寸 - div.setSize = function (width = 0, height = 0) { - if (width) { - if (typeof width === 'number') { - div.style.width = `${width}px` - } else { - div.style.width = width - } - } - if (height) { - if (typeof height === 'number') { - div.style.height = `${height}px` - } else { - div.style.height = height - } - } - div.width = width - div.height = height - } - div.setSize(width, height) - // 设置样式 - div.setStyle = function (style) { - div.style.cssText += style - } - // 添加子元素 - div.add = function (child) { - child && div.appendChild(child) - } - // 移除子元素 - div.remove = function (child) { - child && div.removeChild(child) - } - // 添加事件 - div.on = function (event, callback) { - div.addEventListener(event, callback) - } - // 移除事件 - div.off = function (event, callback) { - div.removeEventListener(event, callback) - } - // 添加动画 - div.animate = function (keyframes) { - div.style.keyframes = keyframes - } - // 设置别名 - div.name = function (name) { - div.setAttribute('data-name', name) - } - // 隐藏图片 - div.hide = function () { - div.style.display = 'none' - } - // 显示图片 - div.show = function () { - div.style.display = 'block' - } - return div + createSprite(img, x = 0, y = 0, width = 0, height = 0) { + return new Sprite(img, x, y, width, height, this.id) } - // 创建容器 - CreateBox(x = 0, y = 0, width = 0, height = 0) { - const div = document.createElement('div') - div.style.position = 'absolute' - div.setAttribute('data-box-id', this.id) - // 设置容器位置 - div.setPosition = function (x = 0, y = 0) { - div.style.left = `${x}px` - div.style.top = `${y}px` - div.x = x - div.y = y - } - div.setPosition(x, y) - // 设置容器尺寸 - div.setSize = function (width = 0, height = 0) { - if (width) { - if (typeof width === 'number') { - div.style.width = `${width}px` - } else { - div.style.width = width - } - } - if (height) { - if (typeof height === 'number') { - div.style.height = `${height}px` - } else { - div.style.height = height - } - } - div.width = width - div.height = height - } - div.setSize(width, height) - // 设置容器样式 - div.setStyle = function (style) { - div.style.cssText += style - } - // 添加子元素 - div.add = function (child) { - child && div.appendChild(child) - } - // 移除子元素 - div.remove = function (child) { - child && div.removeChild(child) - } - // 添加事件 - div.on = function (event, callback) { - div.addEventListener(event, callback) - } - // 移除事件 - div.off = function (event, callback) { - div.removeEventListener(event, callback) - } - // 隐藏容器 - div.hide = function () { - div.style.display = 'none' - } - // 显示容器 - div.show = function () { - div.style.display = 'block' - } - return div + createBox(x = 0, y = 0, width = 0, height = 0) { + return new Box(x, y, width, height, this.id) } - // 创建文本 - CreateText(text = '', x = 0, y = 0) { - const div = document.createElement('div') - div.style.position = 'absolute' - div.setAttribute('data-text-id', this.id) - // 设置文本位置 - div.setPosition = function (x = 0, y = 0) { - div.style.left = `${x}px` - div.style.top = `${y}px` - div.x = x - div.y = y - } - div.setPosition(x, y) - // 设置文本内容 - div.set = function (text = '') { - div.innerText = text - } - div.set(text) - // 设置文本颜色 - div.setColor = function (color = '#000') { - div.style.color = color - } - div.setColor(color) - // 设置文本字体 - div.setFont = function (font = '16px sans-serif') { - div.style.font = font - } - // 设置样式 - div.setStyle = function (style = 'color: #000;') { - div.style.cssText += style - } - // 添加子元素 - div.add = function (child) { - child && div.appendChild(child) - } - // 移除子元素 - div.remove = function (child) { - child && div.removeChild(child) - } - return div + createText(text = '', x = 0, y = 0) { + return new TextElement(text, x, y, this.id) } - // 创建Html文本 - CreateHtml(html = '', x = 0, y = 0) { - const div = document.createElement('div') - div.style.position = 'absolute' - div.setAttribute('data-html-id', this.id) - // 设置Html位置 - div.setPosition = function (x = 0, y = 0) { - div.style.left = `${x}px` - div.style.top = `${y}px` - div.x = x - div.y = y - } - div.setPosition(x, y) - // 设置Html内容 - div.set = function (html = '') { - div.innerHTML = html - } - // 获取Html内容 - div.get = function () { - return div.innerHTML - } - div.set(html) - // 设置样式 - div.setStyle = function (style = 'color: #000;') { - div.style.cssText += style - } - div.setStyle() - // 获取尺寸 - div.getSize = function () { - const { width, height } = div.getBoundingClientRect() - return { width, height } - } - // 添加子元素 - div.add = function (child) { - child && div.appendChild(child) - } - // 移除子元素 - div.remove = function (child) { - child && div.removeChild(child) - } - return div + createHtml(html = '', x = 0, y = 0) { + return new HtmlElement(html, x, y, this.id) } - // 创建svg - CreateSvg(x = 0, y = 0, width = 0, height = 0, content = '') { - const div = document.createElement('div') - div.innerHTML = content - div.style.position = 'absolute' - div.setAttribute('data-svg-id', this.id) - // 设置svg位置 - div.setPosition = function (x = 0, y = 0) { - div.style.left = `${x}px` - div.style.top = `${y}px` - div.x = x - div.y = y - } - div.setPosition(x, y) - // 设置svg尺寸 - div.setSize = function (width = 0, height = 0) { - if (width) { - if (typeof width === 'number') { - div.style.width = `${width}px` - } else { - div.style.width = width - } - } - if (height) { - if (typeof height === 'number') { - div.style.height = `${height}px` - } else { - div.style.height = height - } - } - div.width = width - div.height = height - } - div.setSize(width, height) - // 设置样式 - div.setStyle = function (style) { - div.style.cssText += style - } - // 设置svg内容 - div.setContent = function (content = '') { - div.innerHTML = content - } - // 添加事件 - div.on = function (event, callback) { - div.addEventListener(event, callback) - } - // 移除事件 - div.off = function (event, callback) { - div.removeEventListener(event, callback) - } - return div + createSvg(x = 0, y = 0, width = 0, height = 0, content = '') { + return new SvgElement(x, y, width, height, content, this.id) } - // 销毁舞台 - Destroy() { - this.element.removeChild(this.stage) - // 内存回收 - this.images = null + + destroy() { + if (this.stage && this.stage.parentNode) { + this.stage.parentNode.removeChild(this.stage) + } + + // 清理所有图像引用 + this.images.forEach(img => { + img.onload = null + img.onerror = null + img.src = '' + }) + + // 清除所有引用 + this.images = [] this.stage = null this.element = null this.options = null - this.width = null - this.height = null - this.id = null } }