<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>八维能力雷达图生成器 | 自定义维度</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<style>
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
body { background-color: #f7f9fc; font-family: system-ui, -apple-system, "Microsoft YaHei", sans-serif; }
.card-shadow { box-shadow: 0 2px 12px rgba(0,0,0,0.08); }
.level-input { width: 85px; text-align: center; }
#radarBox { min-height: 400px; height: 62vh; }
.dim-name, .dim-level { min-height: 38px; }
button { min-height: 42px; }
</style>
</head>
<body class="p-3 md:p-6">
<div class="max-w-7xl mx-auto">
<h1 class="text-[clamp(1.3rem,5vw,2.2rem)] font-bold text-gray-800 mb-5 text-center leading-tight">八维能力雷达图生成器(自定义维度)</h1>
<div class="flex flex-col lg:flex-row gap-5 md:gap-6">
<div class="lg:w-[420px] w-full bg-white rounded-xl p-4 md:p-5 card-shadow">
<div class="flex flex-wrap gap-2.5 mb-5">
<button id="fillDefault" class="flex-1 min-w-[140px] px-3 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 active:bg-blue-800 transition">一键导入默认八维</button>
<button id="resetAll" class="flex-1 min-w-[140px] px-3 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 active:bg-red-700 transition">重置全部数据</button>
</div>
<div class="mb-5 border-b pb-4">
<h3 class="font-semibold text-gray-700 mb-3">图表基础设置</h3>
<div class="flex flex-col gap-3">
<div class="flex items-center gap-2 flex-wrap">
<label class="w-[76px] shrink-0 text-sm text-gray-600">图表标题:</label>
<input type="text" id="chartTitle" value="个人综合能力八维雷达图" class="flex-1 min-w-[160px] border rounded px-3 py-2 text-sm">
</div>
<div class="flex items-center gap-2 flex-wrap">
<label class="w-[76px] shrink-0 text-sm text-gray-600">画布背景:</label>
<input type="color" id="bgColor" value="#ffffff" class="w-9 h-9 border rounded shrink-0">
<span class="text-xs text-gray-400 shrink-0">#ffffff</span>
</div>
<div class="flex items-center gap-2 flex-wrap">
<label class="w-[76px] shrink-0 text-sm text-gray-600">填充颜色:</label>
<input type="color" id="fillColor" value="#409EFF" class="w-9 h-9 border rounded shrink-0">
<span class="text-xs text-gray-400 shrink-0">#409EFF</span>
</div>
<div class="flex items-center gap-2 flex-wrap">
<label class="w-[76px] shrink-0 text-sm text-gray-600">线条颜色:</label>
<input type="color" id="lineColor" value="#2563eb" class="w-9 h-9 border rounded shrink-0">
<span class="text-xs text-gray-400 shrink-0">#2563eb</span>
</div>
</div>
</div>
<h3 class="font-semibold text-gray-700 mb-3">八大维度设置(等级:E~SSS)</h3>
<div id="dimList" class="flex flex-col gap-2.5">
</div>
<button id="copyImg" class="w-full mt-5 px-4 py-2.5 bg-emerald-500 text-white rounded-lg hover:bg-emerald-600 active:bg-emerald-700 transition font-medium text-base">复制雷达图图片到剪贴板</button>
<p class="text-xs text-gray-400 mt-2 text-center leading-normal">E不可减号|SSS不可加号|输入回车自动修正格式</p>
</div>
<div class="flex-1 w-full bg-white rounded-xl p-3 md:p-5 card-shadow">
<div id="radarBox" class="w-full"></div>
</div>
</div>
</div>
<script>
const radarDom = document.getElementById('radarBox');
const myChart = echarts.init(radarDom);
const defaultDimNames = [
'学习迭代', '洞察力', '长线运营', '分析思考',
'策略精度', '心理素质', '设局能力', '信息处理'
];
const validLevels = ['E','E+','D-','D','D+','C-','C','C+','B-','B','B+','A-','A','A+','S-','S','S+','SS-','SS','SS+','SSS'];
const levelScoreMap = {
'E':10, 'E+':18,
'D-':26, 'D':34, 'D+':42,
'C-':50, 'C':58, 'C+':66,
'B-':70, 'B':75, 'B+':80,
'A-':84, 'A':88, 'A+':92,
'S-':94, 'S':96, 'S+':97,
'SS-':98, 'SS':99, 'SS+':99.5,
'SSS':100
};
let dimData = [];
function initDimItems() {
const wrap = document.getElementById('dimList');
wrap.innerHTML = '';
dimData = [];
for(let i=0;i<8;i++){
dimData.push({name:'维度'+(i+1), level:'C'});
const item = document.createElement('div');
item.className = 'flex items-center gap-2 bg-gray-50 rounded px-2.5 py-2';
item.innerHTML = `
<input type="text" class="dim-name flex-1 border rounded px-2 py-1.5 text-sm outline-none focus:border-blue-400" placeholder="维度名称">
<input type="text" class="dim-level level-input border rounded px-1 py-1.5 text-sm uppercase outline-none focus:border-blue-400" value="C" maxlength="4">
`;
wrap.appendChild(item);
}
bindInputEvent();
renderChart();
}
document.getElementById('fillDefault').addEventListener('click',()=>{
const nameInputs = document.querySelectorAll('.dim-name');
defaultDimNames.forEach((name,idx)=>{
nameInputs[idx].value = name;
dimData[idx].name = name;
})
renderChart();
});
function formatLevel(raw) {
let str = raw.trim().toUpperCase();
if(str.startsWith('E') && str.includes('-')) return 'E';
if(str === 'SSS+') return 'SSS';
if(validLevels.includes(str)) return str;
return 'C';
}
function bindInputEvent() {
const nameInputs = document.querySelectorAll('.dim-name');
const levelInputs = document.querySelectorAll('.dim-level');
nameInputs.forEach((inp,idx)=>{
inp.addEventListener('input',()=>{
dimData[idx].name = inp.value.trim() || '维度'+(idx+1);
renderChart();
})
});
levelInputs.forEach((inp,idx)=>{
inp.addEventListener('blur',()=>{
const fix = formatLevel(inp.value);
inp.value = fix;
dimData[idx].level = fix;
renderChart();
});
inp.addEventListener('keyup',(e)=>{
if(e.key==='Enter') inp.blur();
});
});
['chartTitle','bgColor','fillColor','lineColor'].forEach(id=>{
document.getElementById(id).addEventListener('input',renderChart);
});
}
function renderChart() {
const title = document.getElementById('chartTitle').value;
const bg = document.getElementById('bgColor').value;
const fill = document.getElementById('fillColor').value;
const line = document.getElementById('lineColor').value;
const isMobile = window.innerWidth < 768;
const radarRadius = isMobile ? '82%' : '76%';
const axisFontSize = isMobile ? 11 : 13;
const titleFontSize = isMobile ? 16 : 18;
const indicator = dimData.map(item=>({
name: `${item.name}\n【${item.level}】`,
max:100
}));
const data = dimData.map(item=>levelScoreMap[item.level]);
const option = {
backgroundColor: bg,
title:{
text: title,
left:'center',
textStyle:{fontSize:titleFontSize,fontWeight:500}
},
tooltip:{
trigger:'item',
formatter:(params)=>{
const idx = params.dataIndex;
return `${dimData[idx].name}<br>等级:${dimData[idx].level}<br>分值:${params.value}`
}
},
radar:{
radius: radarRadius,
splitNumber:5,
axisName:{
fontSize: axisFontSize,
color:'#333',
align:'center',
lineHeight:1.45
},
splitLine:{lineStyle:{color:'#e5e7eb'}},
splitArea:{show:false},
axisLine:{lineStyle:{color:'#d1d5db'}},
symbol:'none',
},
indicator: indicator,
series:[{
type:'radar',
data: data,
areaStyle:{color: fill, opacity:0.25},
lineStyle:{color: line, width:2},
itemStyle:{color:line}
}]
};
myChart.setOption(option);
}
function resizeChart() {
setTimeout(()=>myChart.resize(), 120);
}
window.addEventListener('resize', resizeChart);
window.addEventListener('orientationchange', resizeChart);
window.addEventListener('blur', resizeChart);
document.getElementById('resetAll').addEventListener('click',()=>{
const confirm1 = confirm('⚠️第一次确认:确定重置所有维度与等级数据?');
if(!confirm1) return;
const confirm2 = confirm('⚠️第二次确认:数据清空无法恢复,确认全部重置?');
if(confirm2){
document.getElementById('chartTitle').value = '个人综合能力八维雷达图';
document.getElementById('bgColor').value = '#ffffff';
document.getElementById('fillColor').value = '#409EFF';
document.getElementById('lineColor').value = '#2563eb';
initDimItems();
alert('已完成全部重置');
}
});
document.getElementById('copyImg').addEventListener('click',async()=>{
try{
const canvas = await html2canvas(radarDom,{
backgroundColor: document.getElementById('bgColor').value,
scale: window.innerWidth > 768 ? 2 : 1.8,
useCORS:true,
logging:false
});
canvas.toBlob(async blob=>{
try {
const item = new ClipboardItem({ 'image/png': blob });
await navigator.clipboard.write([item]);
alert('✅图片已复制剪贴板,直接粘贴即可');
} catch (err) {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = '八维能力雷达图.png';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
alert('⚠️浏览器剪贴板受限,已自动下载图片到相册');
}
})
}catch(err){
alert('❌复制失败:请用系统浏览器打开,不要微信内置浏览器');
console.error(err);
}
});
initDimItems();
</script>
</body>
</html>
Error code
ERRW:SS1.0
Were you logged in?
Yes
Your username (if logged in)
No response
Your HTML
Your JavaScript
-Your CSS
-