mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-10-22 15:19:59 +08:00
fixed # 补全梦三怪物、卡牌
fixed # 修复天书乱斗中,过关技能不会重置次数的问题
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
// 只覆盖命名空间内的 CSS 变量,不移动或复制真实卡牌。
|
||||
export function fanSlots(count, width, cardWidth = 112, cardHeight = 156) {
|
||||
if (!Number.isSafeInteger(count) || count < 0 || !Number.isFinite(width) || width <= 0) return [];
|
||||
const step = count > 1 ? Math.min(cardWidth * 0.68,
|
||||
Math.max(0, width - cardWidth - 32) / (count - 1)) : 0;
|
||||
const half = (count - 1) / 2;
|
||||
const angleStep = count > 1 ? Math.min(4, 13 / half) : 0;
|
||||
return Array.from({ length: count }, (_, index) => {
|
||||
const offset = index - half;
|
||||
return { x: width / 2 + offset * step - cardWidth / 2,
|
||||
y: -cardHeight + 28 + (half ? Math.pow(offset / half, 2) * 20 : 0),
|
||||
angle: offset * angleStep, z: index + 1 };
|
||||
});
|
||||
}
|
||||
|
||||
export function createHandFan(adapter, env) {
|
||||
const { window } = env;
|
||||
const owned = new Map();
|
||||
let enabled = false, hover = null, dragging = null;
|
||||
function variable(card, key, value) {
|
||||
let record = owned.get(card);
|
||||
if (!record) { record = new Map(); owned.set(card, record); }
|
||||
if (!record.has(key)) record.set(key, {
|
||||
before: card.style.getPropertyValue(key), priority: card.style.getPropertyPriority(key), last: null,
|
||||
});
|
||||
const entry = record.get(key);
|
||||
entry.last = value;
|
||||
if (card.style.getPropertyValue(key) !== value) card.style.setProperty(key, value);
|
||||
}
|
||||
function release(card) {
|
||||
for (const name of ["mengsan-hand-hover-shuying", "mengsan-hand-drag-shuying", "mengsan-hand-free-drag-shuying"]) card.classList.remove(name);
|
||||
for (const [key, record] of owned.get(card) || []) {
|
||||
if (card.style.getPropertyValue(key) !== record.last) continue;
|
||||
if (record.before) card.style.setProperty(key, record.before, record.priority);
|
||||
else card.style.removeProperty(key);
|
||||
}
|
||||
owned.delete(card);
|
||||
}
|
||||
function setHover(card) {
|
||||
if (hover === card) return;
|
||||
hover?.classList.remove("mengsan-hand-hover-shuying");
|
||||
hover = enabled && !dragging ? card : null;
|
||||
hover?.classList.add("mengsan-hand-hover-shuying");
|
||||
}
|
||||
function sync(active) {
|
||||
enabled = active;
|
||||
const cards = adapter.cards().filter(card => !card.classList.contains("display-none"));
|
||||
const current = new Set(cards);
|
||||
for (const card of owned.keys()) if (!active || !current.has(card)) release(card);
|
||||
if (!active) { setHover(null); return; }
|
||||
const small = window.innerWidth <= 640 || window.innerHeight <= 500;
|
||||
const width = adapter.containers[0]?.clientWidth || adapter.root.clientWidth;
|
||||
const slots = fanSlots(cards.length, width, small ? 82 : 112, small ? 114 : 156);
|
||||
cards.forEach((card, index) => {
|
||||
const slot = slots[index];
|
||||
if (!slot) return;
|
||||
variable(card, "--mengsan-fan-x", `${slot.x}px`);
|
||||
variable(card, "--mengsan-fan-y", `${slot.y}px`);
|
||||
variable(card, "--mengsan-fan-angle", `${slot.angle}deg`);
|
||||
variable(card, "--mengsan-fan-z", `${slot.z}`);
|
||||
});
|
||||
if (hover && !current.has(hover)) setHover(null);
|
||||
}
|
||||
function drag(card, point, targeted) {
|
||||
if (dragging && dragging !== card) stopDrag();
|
||||
setHover(null);
|
||||
dragging = card;
|
||||
card.classList.add("mengsan-hand-drag-shuying");
|
||||
card.classList.toggle("mengsan-hand-free-drag-shuying", !targeted);
|
||||
const zone = card.parentNode;
|
||||
const rect = zone.getBoundingClientRect();
|
||||
// CSS 像素相对于真实父容器:兼容 documentZoom/缩放,不能直接拿屏幕坐标当布局坐标。
|
||||
const scaleX = rect.width / zone.offsetWidth || 1;
|
||||
const scaleY = rect.height / zone.offsetHeight || scaleX;
|
||||
const rootRect = adapter.root.getBoundingClientRect();
|
||||
const small = window.innerWidth <= 640 || window.innerHeight <= 500;
|
||||
const width = small ? 82 : 112, height = small ? 114 : 156;
|
||||
const x = targeted ? rootRect.left + rootRect.width / 2 : point.x;
|
||||
const y = targeted ? rootRect.bottom - height * scaleY / 2 - 6 : point.y;
|
||||
variable(card, "--mengsan-drag-x", `${(x - rect.left) / scaleX - width / 2}px`);
|
||||
variable(card, "--mengsan-drag-y", `${(y - rect.top) / scaleY - height / 2}px`);
|
||||
}
|
||||
function stopDrag() {
|
||||
dragging?.classList.remove("mengsan-hand-drag-shuying", "mengsan-hand-free-drag-shuying");
|
||||
dragging = null;
|
||||
}
|
||||
return { sync, setHover, drag, stopDrag,
|
||||
dispose() { stopDrag(); setHover(null); for (const card of owned.keys()) release(card); } };
|
||||
}
|
||||
Reference in New Issue
Block a user