모듈:Radar: 두 판 사이의 차이
Project ZETA Wiki
더 많은 작업
내용 삭제됨 내용 추가됨
편집 요약 없음 |
편집 요약 없음 |
||
| 1번째 줄: | 1번째 줄: | ||
-- 모듈:Radar — 5각형 레이더(공격/방어/지원/이동/제어). CSS clip-path, 다크 시인성 개선판. |
-- 모듈:Radar — 5각형 레이더(공격/방어/지원/이동/제어). CSS clip-path, 다크 시인성 개선판. |
||
-- size 파라미터로 전체 크기 조절 (기본 220 = 박스 폭 px), 모든 요소 비례 스케일. |
|||
local p = {} |
local p = {} |
||
local AXES = { '공격', '방어', '지원', '이동', '제어' } |
local AXES = { '공격', '방어', '지원', '이동', '제어' } |
||
| 18번째 줄: | 19번째 줄: | ||
-- 외곽선 링 = border-color 채움 + 카드색 knockout (얇은 테두리만 남김) |
-- 외곽선 링 = border-color 채움 + 카드색 knockout (얇은 테두리만 남김) |
||
local function ring(cx, cy, R, scale) |
local function ring(cx, cy, R, scale, t) |
||
local ks = scale - |
local ks = scale - t / R |
||
if ks < 0 then ks = 0 end |
|||
return string.format( |
return string.format( |
||
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--border-color-base,#c8ccd1);"></div>' .. |
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--border-color-base,#c8ccd1);"></div>' .. |
||
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--color-surface-1,#fbfcfd);"></div>', |
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--color-surface-1,#fbfcfd);"></div>', |
||
poly(cx, cy, R, scale), poly(cx, cy, R, ks)) |
poly(cx, cy, R, scale), poly(cx, cy, R, ks)) |
||
end |
|||
-- 값 폴리곤 좌표 (각 꼭짓점 반경 개별, inset px만큼 중심 쪽으로 축소) |
|||
local function valPoly(cx, cy, R, vals, maxv, inset) |
|||
local t = {} |
|||
for k = 0, 4 do |
|||
local r = R * (vals[k + 1] / maxv) - inset |
|||
if r < 0 then r = 0 end |
|||
| ⚫ | |||
| ⚫ | |||
end |
|||
| ⚫ | |||
end |
end |
||
| 29번째 줄: | 43번째 줄: | ||
local args = frame.args |
local args = frame.args |
||
local maxv = tonumber(args['max']) or 5 |
local maxv = tonumber(args['max']) or 5 |
||
local |
local size = tonumber(args['size']) or 220 |
||
local s = size / 220 |
|||
local cx, cy, R = 110 * s, 92 * s, 58 * s |
|||
local vals = {} |
local vals = {} |
||
for k = 1, 5 do vals[k] = tonumber(args[AXES[k]]) or 0 end |
for k = 1, 5 do vals[k] = tonumber(args[AXES[k]]) or 0 end |
||
-- 눈금 링: 외곽(1.0) 굵게 + 각 단계 얇게 |
|||
-- 값 폴리곤 |
|||
local |
local grid = { ring(cx, cy, R, 1, 2.2 * s) } |
||
for k = |
for k = 1, maxv - 1 do |
||
grid[#grid + 1] = ring(cx, cy, R, k / maxv, 1.1 * s) |
|||
| ⚫ | |||
end |
end |
||
-- 값 폴리곤: 진한 테두리 + 반투명 내부 |
|||
local border = valPoly(cx, cy, R, vals, maxv, 0) |
|||
local inner = valPoly(cx, cy, R, vals, maxv, 2.4 * s) |
|||
local valueLayers = string.format( |
|||
| ⚫ | |||
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--color-surface-1,#fbfcfd);"></div>' .. |
|||
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--color-progressive,#3a7bd5); opacity:0.45;"></div>', |
|||
border, inner, inner) |
|||
-- 꼭짓점 점 + 라벨 |
-- 꼭짓점 점 + 라벨 |
||
local dot = 8 * s |
|||
local fontPx = 12 * s |
|||
local dots, labels = {}, {} |
local dots, labels = {}, {} |
||
for k = 0, 4 do |
for k = 0, 4 do |
||
| 47번째 줄: | 73번째 줄: | ||
local dx, dy = vert(cx, cy, R * (v / maxv), k) |
local dx, dy = vert(cx, cy, R * (v / maxv), k) |
||
dots[#dots + 1] = string.format( |
dots[#dots + 1] = string.format( |
||
'<div style="position:absolute; left:%.1fpx; top:%.1fpx; width: |
'<div style="position:absolute; left:%.1fpx; top:%.1fpx; width:%.1fpx; height:%.1fpx; margin:%.1fpx; border-radius:50%%; background:var(--color-progressive,#3a7bd5); border:%.1fpx solid var(--color-surface-1,#fbfcfd); box-sizing:content-box;"></div>', |
||
dx, dy, dot, dot, -(dot / 2 + 1.5 * s), 1.5 * s) |
|||
end |
end |
||
local lx, ly = vert(cx, cy, R + |
local lx, ly = vert(cx, cy, R + 19 * s, k) |
||
local tx = '-50%' |
local tx = '-50%' |
||
if lx > cx + 5 then tx = '0' elseif lx < cx - 5 then tx = '-100%' end |
if lx > cx + 5 then tx = '0' elseif lx < cx - 5 then tx = '-100%' end |
||
labels[#labels + 1] = string.format( |
labels[#labels + 1] = string.format( |
||
'<span style="position:absolute; left:%.1fpx; top:%.1fpx; transform:translate(%s,-50%%); white-space:nowrap; font-size: |
'<span style="position:absolute; left:%.1fpx; top:%.1fpx; transform:translate(%s,-50%%); white-space:nowrap; font-size:%.1fpx; font-weight:600; color:var(--color-base,#202122);">%s <span style="color:var(--color-progressive,#3a7bd5)">%d</span></span>', |
||
lx, ly, tx, AXES[k + 1], v) |
lx, ly, tx, fontPx, AXES[k + 1], v) |
||
end |
end |
||
return string.format( |
return string.format( |
||
'<div style="position:relative; display:flow-root; width: |
'<div style="position:relative; display:flow-root; width:%.0fpx; height:%.0fpx; margin:10px auto; background:var(--color-surface-1,#fbfcfd); border:1px solid var(--border-color-base,#c8ccd1); border-radius:8px;">' .. |
||
| ⚫ | |||
'%s%s' .. -- 외곽 링 + 내부 링(0.6) |
|||
size, 184 * s, |
|||
| ⚫ | |||
table.concat(grid, ''), |
|||
| ⚫ | |||
valueLayers, |
|||
| ⚫ | |||
| ⚫ | |||
table.concat(dots, ''), table.concat(labels, '')) |
table.concat(dots, ''), table.concat(labels, '')) |
||
end |
end |
||
2026년 6월 5일 (금) 12:32 판
이 모듈에 대한 설명문서는 모듈:Radar/설명문서에서 만들 수 있습니다
-- 모듈:Radar — 5각형 레이더(공격/방어/지원/이동/제어). CSS clip-path, 다크 시인성 개선판.
-- size 파라미터로 전체 크기 조절 (기본 220 = 박스 폭 px), 모든 요소 비례 스케일.
local p = {}
local AXES = { '공격', '방어', '지원', '이동', '제어' }
local function vert(cx, cy, r, k)
local a = math.rad(-90 + 72 * k)
return cx + r * math.cos(a), cy + r * math.sin(a)
end
local function poly(cx, cy, R, scale)
local t = {}
for k = 0, 4 do
local x, y = vert(cx, cy, R * scale, k)
t[#t + 1] = string.format('%.1fpx %.1fpx', x, y)
end
return table.concat(t, ', ')
end
-- 외곽선 링 = border-color 채움 + 카드색 knockout (얇은 테두리만 남김)
local function ring(cx, cy, R, scale, t)
local ks = scale - t / R
if ks < 0 then ks = 0 end
return string.format(
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--border-color-base,#c8ccd1);"></div>' ..
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--color-surface-1,#fbfcfd);"></div>',
poly(cx, cy, R, scale), poly(cx, cy, R, ks))
end
-- 값 폴리곤 좌표 (각 꼭짓점 반경 개별, inset px만큼 중심 쪽으로 축소)
local function valPoly(cx, cy, R, vals, maxv, inset)
local t = {}
for k = 0, 4 do
local r = R * (vals[k + 1] / maxv) - inset
if r < 0 then r = 0 end
local x, y = vert(cx, cy, r, k)
t[#t + 1] = string.format('%.1fpx %.1fpx', x, y)
end
return table.concat(t, ', ')
end
function p.render(frame)
local args = frame.args
local maxv = tonumber(args['max']) or 5
local size = tonumber(args['size']) or 220
local s = size / 220
local cx, cy, R = 110 * s, 92 * s, 58 * s
local vals = {}
for k = 1, 5 do vals[k] = tonumber(args[AXES[k]]) or 0 end
-- 눈금 링: 외곽(1.0) 굵게 + 각 단계 얇게
local grid = { ring(cx, cy, R, 1, 2.2 * s) }
for k = 1, maxv - 1 do
grid[#grid + 1] = ring(cx, cy, R, k / maxv, 1.1 * s)
end
-- 값 폴리곤: 진한 테두리 + 반투명 내부
local border = valPoly(cx, cy, R, vals, maxv, 0)
local inner = valPoly(cx, cy, R, vals, maxv, 2.4 * s)
local valueLayers = string.format(
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--color-progressive,#3a7bd5);"></div>' ..
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--color-surface-1,#fbfcfd);"></div>' ..
'<div style="position:absolute; inset:0; clip-path:polygon(%s); background:var(--color-progressive,#3a7bd5); opacity:0.45;"></div>',
border, inner, inner)
-- 꼭짓점 점 + 라벨
local dot = 8 * s
local fontPx = 12 * s
local dots, labels = {}, {}
for k = 0, 4 do
local v = vals[k + 1]
if v > 0 then
local dx, dy = vert(cx, cy, R * (v / maxv), k)
dots[#dots + 1] = string.format(
'<div style="position:absolute; left:%.1fpx; top:%.1fpx; width:%.1fpx; height:%.1fpx; margin:%.1fpx; border-radius:50%%; background:var(--color-progressive,#3a7bd5); border:%.1fpx solid var(--color-surface-1,#fbfcfd); box-sizing:content-box;"></div>',
dx, dy, dot, dot, -(dot / 2 + 1.5 * s), 1.5 * s)
end
local lx, ly = vert(cx, cy, R + 19 * s, k)
local tx = '-50%'
if lx > cx + 5 then tx = '0' elseif lx < cx - 5 then tx = '-100%' end
labels[#labels + 1] = string.format(
'<span style="position:absolute; left:%.1fpx; top:%.1fpx; transform:translate(%s,-50%%); white-space:nowrap; font-size:%.1fpx; font-weight:600; color:var(--color-base,#202122);">%s <span style="color:var(--color-progressive,#3a7bd5)">%d</span></span>',
lx, ly, tx, fontPx, AXES[k + 1], v)
end
return string.format(
'<div style="position:relative; display:flow-root; width:%.0fpx; height:%.0fpx; margin:10px auto; background:var(--color-surface-1,#fbfcfd); border:1px solid var(--border-color-base,#c8ccd1); border-radius:8px;">' ..
'%s%s%s%s</div>',
size, 184 * s,
table.concat(grid, ''),
valueLayers,
table.concat(dots, ''), table.concat(labels, ''))
end
return p