卡厄思
梦
境
菜单
首页
回到首页
WIKI工具
全站样式
全站JS
修改导航栏
测试
沙盒
可视化管理器
战斗员管理器
卡牌管理器
伙伴管理器
装备管理器
词典管理器
图鉴
战斗员
伙伴
装备
怪物卡牌
中立卡牌
词典
小工具
配队模拟器
节奏榜生成器
搜索
链入页面
相关更改
特殊页面
页面信息
最近更改
登录
微件
查看“︁TierListMaker”︁的源代码
←
微件:TierListMaker
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您没有权限编辑
微件
命名空间内的页面。
您可以查看和复制此页面的源代码。
<includeonly> <style> .tier-row { position: relative; background-color: #fafafa; border: 2px dashed transparent; transition: all 0.2s ease; display: flex; flex-wrap: wrap; gap: 5px; align-content: flex-start; padding: 10px; min-height: 80px; .tier-row.drag-over { background-color: #e3f2fd; border-color: #2196F3; } #character-pool { position: relative; display: flex; flex-wrap: wrap; gap: 5px; align-content: flex-start; padding: 10px; min-height: 100px; } #character-pool.drag-over { background-color: #fff3e0; } .tierlist-table { width: 100%; table-layout: fixed; border-collapse: collapse; } .tierlist-table th { width: 100px; position: relative; vertical-align: top; } .tierlist-table td { padding: 0 !important; vertical-align: top; .tierlist-controls { margin-bottom: 20px; display: flex; gap: 10px; } .tierlist-btn { padding: 10px 20px; font-size: 16px; color: white; border: none; border-radius: 5px; cursor: pointer; transition: all 0.2s ease; display: inline-block; text-align: center; user-select: none; } .tierlist-btn-save { background-color: #4CAF50; } .tierlist-btn-save:hover { background-color: #45a049; } .tierlist-btn-reset { background-color: #f44336; } .tierlist-btn-reset:hover { background-color: #da190b; } .tierlist-btn-add { background-color: #2196F3; } .tierlist-btn-add:hover { background-color: #0b7dda; } .tierlist-btn-edit { background-color: #ff9800; } .tierlist-btn-edit:hover { background-color: #e68900; } .tierlist-btn-edit.active { background-color: #ff5722; } .tierlist-btn:active { transform: scale(0.98); } .character-pool-container { background-color: #f9f9f9; padding: 15px; border: 2px dashed #ccc; border-radius: 5px; margin-top: 20px; } .character-pool-container h3 { margin-top: 0; color: #333; } /* 编辑模式下的样式 */ .tier-header.editable { cursor: pointer; position: relative; } .tier-header.editable:hover::after { content: '✎'; position: absolute; right: 5px; top: 50%; transform: translateY(-50%); font-size: 16px; } .delete-row-btn { position: absolute; right: 5px; top: 50%; transform: translateY(-50%); background-color: #f44336; color: white; border: none; border-radius: 3px; padding: 3px 8px; cursor: pointer; font-size: 12px; display: none; z-index: 100; } .edit-mode .delete-row-btn { display: block; } .delete-row-btn:hover { background-color: #da190b; } /* 颜色选择器容器 */ .color-picker-popup { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); z-index: 1000; min-width: 300px; } .color-picker-popup h4 { margin-top: 0; } .color-picker-popup label { display: block; margin: 10px 0 5px 0; } .color-picker-popup input[type="text"], .color-picker-popup input[type="color"] { width: 100%; padding: 5px; margin-bottom: 10px; box-sizing: border-box; } .color-picker-popup .button-group { display: flex; gap: 10px; margin-top: 15px; } .color-picker-popup button { flex: 1; padding: 8px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; } .color-picker-popup .btn-confirm { background-color: #4CAF50; color: white; } .color-picker-popup .btn-cancel { background-color: #f44336; color: white; } .overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 999; } /* 确保avatar-frame正确显示 */ .avatar-frame { display: inline-block; margin: 0; cursor: move; /* 显示可移动光标 */ } .avatar-frame.dragging { opacity: 0.5; } /* 空的tier-row显示提示 */ .tier-row:empty::before { content: '拖放角色到这里'; color: #999; font-size: 14px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); pointer-events: none; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script> <script> (function() { 'use strict'; if (window.TierlistMakerInitialized) { console.log('TierlistMaker already initialized'); return; } const TierlistMaker = { draggedElement: null, sourceContainer: null, editMode: false, initRetryCount: 0, maxRetries: 10, init: function() { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this.setup()); } else { this.setup(); } }, setup: function() { const characterPool = document.getElementById('character-pool'); const avatars = characterPool ? characterPool.querySelectorAll('.avatar-frame') : []; if (avatars.length === 0 && this.initRetryCount < this.maxRetries) { this.initRetryCount++; console.log('等待角色加载...', this.initRetryCount); setTimeout(() => this.setup(), 300); return; } console.log('找到角色数量:', avatars.length); this.cleanupContainers(); this.initDragAndDrop(); this.initButtons(); }, cleanupContainers: function() { const containers = document.querySelectorAll('.tier-row, #character-pool'); containers.forEach(container => { const children = Array.from(container.childNodes); children.forEach(child => { if (child.nodeType === Node.TEXT_NODE && !child.textContent.trim()) { container.removeChild(child); } else if (child.nodeType === Node.ELEMENT_NODE) { if (!child.classList.contains('avatar-frame') && !child.querySelector('.avatar-frame') && !child.textContent.trim()) { container.removeChild(child); } } }); }); }, initDragAndDrop: function() { console.log('初始化拖拽功能...'); // 初始化所有avatar的拖拽 this.initAvatarsDraggable(); // 初始化所有drop区域 this.initDropZones(); }, // 初始化所有avatar元素的拖拽功能 initAvatarsDraggable: function() { const allAvatars = document.querySelectorAll('.avatar-frame'); console.log('设置可拖拽的角色数量:', allAvatars.length); allAvatars.forEach(avatar => { if (!avatar.hasAttribute('draggable')) { avatar.setAttribute('draggable', 'true'); // 移除旧的事件监听器(如果存在) avatar.ondragstart = null; avatar.ondragend = null; // 添加新的事件监听器 avatar.addEventListener('dragstart', (e) => { this.handleDragStart(e, avatar); }); avatar.addEventListener('dragend', (e) => { this.handleDragEnd(e, avatar); }); console.log('已设置拖拽:', avatar); } }); }, // 初始化所有drop区域 initDropZones: function() { // 为所有tier行添加drop事件 const tierRows = document.querySelectorAll('.tier-row'); console.log('初始化drop区域数量:', tierRows.length); tierRows.forEach(row => { // 移除旧的事件监听器 const newRow = row.cloneNode(true); row.parentNode.replaceChild(newRow, row); // 添加新的事件监听器 newRow.addEventListener('dragover', (e) => { e.preventDefault(); e.stopPropagation(); e.dataTransfer.dropEffect = 'move'; newRow.classList.add('drag-over'); }); newRow.addEventListener('dragleave', (e) => { e.preventDefault(); e.stopPropagation(); // 检查是否真的离开了该元素 const rect = newRow.getBoundingClientRect(); if (e.clientX < rect.left || e.clientX >= rect.right || e.clientY < rect.top || e.clientY >= rect.bottom) { newRow.classList.remove('drag-over'); } }); newRow.addEventListener('drop', (e) => { e.preventDefault(); e.stopPropagation(); this.handleDrop(e, newRow); }); // 重新设置该行中已有avatar的拖拽 newRow.querySelectorAll('.avatar-frame').forEach(avatar => { if (!avatar.hasAttribute('draggable')) { avatar.setAttribute('draggable', 'true'); avatar.addEventListener('dragstart', (e) => this.handleDragStart(e, avatar)); avatar.addEventListener('dragend', (e) => this.handleDragEnd(e, avatar)); } }); }); // 为角色池添加drop事件 const characterPool = document.getElementById('character-pool'); if (characterPool) { // 移除旧的事件监听器 const newPool = characterPool.cloneNode(true); characterPool.parentNode.replaceChild(newPool, characterPool); newPool.addEventListener('dragover', (e) => { e.preventDefault(); e.stopPropagation(); e.dataTransfer.dropEffect = 'move'; newPool.classList.add('drag-over'); }); newPool.addEventListener('dragleave', (e) => { e.preventDefault(); e.stopPropagation(); const rect = newPool.getBoundingClientRect(); if (e.clientX < rect.left || e.clientX >= rect.right || e.clientY < rect.top || e.clientY >= rect.bottom) { newPool.classList.remove('drag-over'); } }); newPool.addEventListener('drop', (e) => { e.preventDefault(); e.stopPropagation(); this.handleDrop(e, newPool); }); // 重新设置角色池中avatar的拖拽 newPool.querySelectorAll('.avatar-frame').forEach(avatar => { if (!avatar.hasAttribute('draggable')) { avatar.setAttribute('draggable', 'true'); avatar.addEventListener('dragstart', (e) => this.handleDragStart(e, avatar)); avatar.addEventListener('dragend', (e) => this.handleDragEnd(e, avatar)); } }); } }, handleDragStart: function(e, element) { console.log('开始拖拽:', element); this.draggedElement = element; this.sourceContainer = element.parentElement; element.classList.add('dragging'); e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('text/html', element.innerHTML); }, handleDragEnd: function(e, element) { console.log('结束拖拽'); element.classList.remove('dragging'); document.querySelectorAll('.drag-over').forEach(el => { el.classList.remove('drag-over'); }); this.cleanupContainers(); this.saveState(); this.draggedElement = null; this.sourceContainer = null; }, handleDrop: function(e, targetContainer) { console.log('放置到:', targetContainer); targetContainer.classList.remove('drag-over'); if (this.draggedElement && this.draggedElement.parentElement !== targetContainer) { // 从原位置移除 if (this.draggedElement.parentElement) { this.draggedElement.parentElement.removeChild(this.draggedElement); } // 添加到新位置 targetContainer.appendChild(this.draggedElement); // 确保样式正常 this.draggedElement.style.opacity = '1'; const img = this.draggedElement.querySelector('img'); if (img) { img.style.opacity = '1'; } this.cleanupContainers(); console.log('放置成功'); } }, initButtons: function() { const saveBtn = document.getElementById('save-tierlist-btn'); const resetBtn = document.getElementById('reset-tierlist-btn'); const addRowBtn = document.getElementById('add-row-btn'); const editModeBtn = document.getElementById('edit-mode-btn'); if (saveBtn) { saveBtn.onclick = () => this.saveTierlist(); } if (resetBtn) { resetBtn.onclick = () => this.resetTierlist(); } if (addRowBtn) { addRowBtn.onclick = () => this.addRow(); } if (editModeBtn) { editModeBtn.onclick = () => this.toggleEditMode(); } }, toggleEditMode: function() { this.editMode = !this.editMode; const btn = document.getElementById('edit-mode-btn'); const table = document.getElementById('tierlist-table'); if (this.editMode) { btn.classList.add('active'); btn.textContent = '完成编辑'; table.classList.add('edit-mode'); document.querySelectorAll('.tier-header').forEach(header => { header.classList.add('editable'); if (!header.querySelector('.delete-row-btn')) { const deleteBtn = document.createElement('button'); deleteBtn.className = 'delete-row-btn'; deleteBtn.textContent = '删除'; deleteBtn.onclick = (e) => { e.stopPropagation(); this.deleteRow(header.closest('tr')); }; header.appendChild(deleteBtn); } header.onclick = () => this.editTierHeader(header); }); } else { btn.classList.remove('active'); btn.textContent = '编辑模式'; table.classList.remove('edit-mode'); document.querySelectorAll('.tier-header').forEach(header => { header.classList.remove('editable'); header.onclick = null; }); } }, editTierHeader: function(header) { const currentText = header.textContent.replace('删除', '').trim(); const currentBgColor = header.style.backgroundColor || '#000000'; const overlay = document.createElement('div'); overlay.className = 'overlay'; const popup = document.createElement('div'); popup.className = 'color-picker-popup'; popup.innerHTML = ` <h4>编辑Tier</h4> <label>Tier名称:</label> <input type="text" id="tier-name-input" value="${currentText}" maxlength="10"> <label>背景颜色:</label> <input type="color" id="tier-color-input" value="${this.rgbToHex(currentBgColor)}"> <div class="button-group"> <button class="btn-confirm">确定</button> <button class="btn-cancel">取消</button> </div> `; document.body.appendChild(overlay); document.body.appendChild(popup); const nameInput = popup.querySelector('#tier-name-input'); const colorInput = popup.querySelector('#tier-color-input'); popup.querySelector('.btn-confirm').onclick = () => { const newName = nameInput.value.trim(); const newColor = colorInput.value; if (newName) { header.setAttribute('data-tier', newName); const deleteBtn = header.querySelector('.delete-row-btn'); if (deleteBtn) deleteBtn.remove(); header.textContent = newName; header.style.backgroundColor = newColor; const newDeleteBtn = document.createElement('button'); newDeleteBtn.className = 'delete-row-btn'; newDeleteBtn.textContent = '删除'; newDeleteBtn.onclick = (e) => { e.stopPropagation(); this.deleteRow(header.closest('tr')); }; header.appendChild(newDeleteBtn); const row = header.closest('tr').querySelector('.tier-row'); if (row) { row.setAttribute('data-tier', newName); } this.saveState(); } document.body.removeChild(overlay); document.body.removeChild(popup); }; popup.querySelector('.btn-cancel').onclick = () => { document.body.removeChild(overlay); document.body.removeChild(popup); }; overlay.onclick = () => { document.body.removeChild(overlay); document.body.removeChild(popup); }; nameInput.focus(); nameInput.select(); }, rgbToHex: function(rgb) { if (rgb.startsWith('#')) return rgb; const values = rgb.match(/\d+/g); if (!values || values.length < 3) return '#000000'; const r = parseInt(values[0]).toString(16).padStart(2, '0'); const g = parseInt(values[1]).toString(16).padStart(2, '0'); const b = parseInt(values[2]).toString(16).padStart(2, '0'); return '#' + r + g + b; }, addRow: function() { const table = document.getElementById('tierlist-table'); if (!table) return; const tbody = table.querySelector('tbody'); const tierCount = document.querySelectorAll('.tier-row').length; const tierName = 'T' + (tierCount + 1); const newRow = document.createElement('tr'); newRow.innerHTML = ` <th style="width: 100px; background-color: #9e9e9e; color: white; font-size: 20px; text-align: center" class="tier-header" data-tier="${tierName}">${tierName}</th> <td class="tier-row" data-tier="${tierName}"></td> `; tbody.appendChild(newRow); console.log('添加新行:', tierName); // 重新初始化所有drop区域(包括新行) this.initDropZones(); // 如果在编辑模式下,添加编辑功能 if (this.editMode) { const header = newRow.querySelector('.tier-header'); header.classList.add('editable'); const deleteBtn = document.createElement('button'); deleteBtn.className = 'delete-row-btn'; deleteBtn.textContent = '删除'; deleteBtn.onclick = (e) => { e.stopPropagation(); this.deleteRow(newRow); }; header.appendChild(deleteBtn); header.onclick = () => this.editTierHeader(header); } this.saveState(); }, deleteRow: function(row) { if (!confirm('确定要删除这一行吗?行内的角色将移回角色池。')) { return; } const tierRow = row.querySelector('.tier-row'); const avatars = Array.from(tierRow.querySelectorAll('.avatar-frame')); const pool = document.getElementById('character-pool'); avatars.forEach(avatar => { pool.appendChild(avatar); }); row.remove(); this.cleanupContainers(); this.saveState(); }, saveState: function() { const state = { rows: [], pool: [] }; document.querySelectorAll('#tierlist-table tbody tr').forEach(row => { const header = row.querySelector('.tier-header'); const tierRow = row.querySelector('.tier-row'); if (!header || !tierRow) return; const rowData = { name: header.getAttribute('data-tier'), bgColor: header.style.backgroundColor, characters: [] }; tierRow.querySelectorAll('.avatar-frame').forEach(avatar => { const charId = this.getCharacterId(avatar); if (charId) { rowData.characters.push(charId); } }); state.rows.push(rowData); }); const pool = document.getElementById('character-pool'); if (pool) { pool.querySelectorAll('.avatar-frame').forEach(avatar => { const charId = this.getCharacterId(avatar); if (charId) { state.pool.push(charId); } }); } try { localStorage.setItem('tierlist-state', JSON.stringify(state)); console.log('状态已保存'); } catch (e) { console.warn('无法保存状态:', e); } }, loadState: function() { try { const stateJson = localStorage.getItem('tierlist-state'); if (!stateJson) { console.log('没有保存的状态'); return; } const state = JSON.parse(stateJson); console.log('加载保存的状态:', state); const tbody = document.querySelector('#tierlist-table tbody'); const rows = Array.from(tbody.querySelectorAll('tr')); if (state.rows && state.rows.length > 0) { rows.forEach((row, index) => { if (index >= state.rows.length) { row.remove(); } else { const header = row.querySelector('.tier-header'); const savedRow = state.rows[index]; if (header && savedRow) { header.textContent = savedRow.name; header.setAttribute('data-tier', savedRow.name); header.style.backgroundColor = savedRow.bgColor; const tierRow = row.querySelector('.tier-row'); if (tierRow) { tierRow.setAttribute('data-tier', savedRow.name); tierRow.innerHTML = ''; } } } }); for (let i = rows.length; i < state.rows.length; i++) { const savedRow = state.rows[i]; const newRow = document.createElement('tr'); newRow.innerHTML = ` <th style="width: 100px; background-color: ${savedRow.bgColor}; color: white; font-size: 20px; text-align: center" class="tier-header" data-tier="${savedRow.name}">${savedRow.name}</th> <td class="tier-row" data-tier="${savedRow.name}"></td> `; tbody.appendChild(newRow); } } // 重新初始化所有drop区域 this.initDropZones(); setTimeout(() => { state.rows.forEach((rowData, index) => { const tierRow = document.querySelectorAll('.tier-row')[index]; if (!tierRow) return; rowData.characters.forEach(charId => { const avatar = this.findAvatarById(charId); if (avatar && avatar.parentElement) { tierRow.appendChild(avatar); } }); }); // 重新初始化拖拽 this.initAvatarsDraggable(); this.cleanupContainers(); console.log('状态加载完成'); }, 200); } catch (e) { console.warn('无法加载状态:', e); } }, getCharacterId: function(avatar) { const img = avatar.querySelector('img'); if (img) { const src = img.getAttribute('src'); if (src) { const match = src.match(/\/(\d+)\./); if (match) return match[1]; } } const name = avatar.querySelector('.avatar-name'); if (name) { return name.textContent.trim(); } return avatar.outerHTML; }, findAvatarById: function(charId) { const allAvatars = document.querySelectorAll('.avatar-frame'); for (let avatar of allAvatars) { if (this.getCharacterId(avatar) === charId) { return avatar; } } return null; }, saveTierlist: function() { const table = document.getElementById('tierlist-table'); if (!table) { alert('未找到 Tierlist 表格!'); return; } if (typeof html2canvas === 'undefined') { alert('正在加载图片生成库,请稍后再试...'); return; } const controls = document.querySelector('.tierlist-controls'); const poolContainer = document.querySelector('.character-pool-container'); const originalControlsDisplay = controls ? controls.style.display : ''; const originalPoolDisplay = poolContainer ? poolContainer.style.display : ''; const deleteButtons = document.querySelectorAll('.delete-row-btn'); deleteButtons.forEach(btn => btn.style.display = 'none'); if (controls) controls.style.display = 'none'; if (poolContainer) poolContainer.style.display = 'none'; html2canvas(table, { scale: 2, backgroundColor: '#ffffff', logging: false, useCORS: true, allowTaint: true }).then(canvas => { if (controls) controls.style.display = originalControlsDisplay; if (poolContainer) poolContainer.style.display = originalPoolDisplay; deleteButtons.forEach(btn => btn.style.display = ''); const link = document.createElement('a'); const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5); link.download = 'tierlist_' + timestamp + '.png'; link.href = canvas.toDataURL('image/png'); link.click(); }).catch(err => { console.error('生成图片失败:', err); if (controls) controls.style.display = originalControlsDisplay; if (poolContainer) poolContainer.style.display = originalPoolDisplay; deleteButtons.forEach(btn => btn.style.display = ''); alert('生成图片失败,请查看控制台了解详情'); }); }, resetTierlist: function() { if (!confirm('确定要重置所有排列吗?此操作不可撤销。')) { return; } const pool = document.getElementById('character-pool'); if (!pool) { alert('未找到角色池!'); return; } const allAvatars = Array.from(document.querySelectorAll('.avatar-frame')); document.querySelectorAll('.tier-row').forEach(row => { row.innerHTML = ''; }); pool.innerHTML = ''; allAvatars.forEach(avatar => { pool.appendChild(avatar); avatar.style.opacity = '1'; const img = avatar.querySelector('img'); if (img) { img.style.opacity = '1'; } }); // 重新初始化拖拽功能 this.initAvatarsDraggable(); this.cleanupContainers(); try { localStorage.removeItem('tierlist-state'); console.log('状态已清除'); } catch (e) { console.warn('无法清除状态:', e); } alert('重置完成!'); } }; window.TierlistMakerInitialized = true; window.TierlistMaker = TierlistMaker; TierlistMaker.init(); // 添加手动加载状态的功能 window.loadTierlistState = function() { if (window.TierlistMaker) { window.TierlistMaker.loadState(); } }; })(); </script> </includeonly>
返回
微件:TierListMaker
。