html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单词统计 Key→Value 动态可视化</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
text-align: center;
}
#inputArea {
margin-bottom: 20px;
}
#kvContainer {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 20px;
max-width: 400px;
margin-left: auto;
margin-right: auto;
}
.kvPair {
display: flex;
align-items: center;
gap: 10px;
padding: 5px 10px;
border: 1px solid #888;
border-radius: 5px;
transition: background-color 0.3s, color 0.3s;
}
.kvPair.active {
background-color: orange;
color: white;
}
.key, .value {
min-width: 60px;
text-align: center;
font-weight: bold;
}
.arrow {
font-size: 16px;
}
#controls {
margin-top: 20px;
}
input[type="text"] {
width: 300px;
padding: 5px;
font-size: 16px;
}
button {
padding: 5px 15px;
font-size: 16px;
margin-left: 10px;
cursor: pointer;
}
</style>
</head>
<body>
<h2>句子单词统计 Key→Value 动态可视化</h2>
<div id="inputArea">
<input type="text" id="sentenceInput" value="I love coding and I love teaching">
<button id="startBtn">开始</button>
</div>
<div id="kvContainer">
<!-- KeyValuePair 会动态生成 -->
</div>
<div id="controls">
<button id="prevBtn">上一步</button>
<button id="nextBtn">下一步</button>
</div>
<script>
const sentenceInput = document.getElementById('sentenceInput');
const startBtn = document.getElementById('startBtn');
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
const kvContainer = document.getElementById('kvContainer');
let steps = []; // 保存每一步 Map 状态
let currentStep = -1;
let words = [];
let wordMap = new Map();
// 重置可视化
function resetVisualization() {
kvContainer.innerHTML = '';
steps = [];
currentStep = -1;
wordMap.clear();
}
// 生成每步状态
function recordSteps(sentence) {
words = sentence.trim().split(/\s+/);
wordMap.clear();
steps = [];
for (let i = 0; i < words.length; i++) {
const word = words[i].toLowerCase();
wordMap.set(word, (wordMap.get(word) || 0) + 1);
const snapshot = new Map(wordMap); // 保存 Map 副本
steps.push({
current: word,
map: snapshot
});
}
}
// 渲染指定步骤
function renderStep(stepIndex) {
if (stepIndex < 0 || stepIndex >= steps.length) return;
const step = steps[stepIndex];
const currentWord = step.current;
const map = step.map;
kvContainer.innerHTML = ''; // 清空容器
map.forEach((value, key) => {
const kvDiv = document.createElement('div');
kvDiv.classList.add('kvPair');
if (key === currentWord) kvDiv.classList.add('active');
const keyDiv = document.createElement('div');
keyDiv.classList.add('key');
keyDiv.innerText = key;
const arrowDiv = document.createElement('div');
arrowDiv.classList.add('arrow');
arrowDiv.innerText = '→';
const valueDiv = document.createElement('div');
valueDiv.classList.add('value');
valueDiv.innerText = value;
kvDiv.appendChild(keyDiv);
kvDiv.appendChild(arrowDiv);
kvDiv.appendChild(valueDiv);
kvContainer.appendChild(kvDiv);
});
currentStep = stepIndex;
}
// 按钮事件
startBtn.addEventListener('click', () => {
const sentence = sentenceInput.value.trim();
if (!sentence) {
alert('请输入句子!');
return;
}
resetVisualization();
recordSteps(sentence);
renderStep(0);
});
nextBtn.addEventListener('click', () => {
if (currentStep < steps.length - 1) {
renderStep(currentStep + 1);
}
});
prevBtn.addEventListener('click', () => {
if (currentStep > 0) {
renderStep(currentStep - 1);
}
});
</script>
</body>
</html>