之前一直以为Javascript很容易入门,都不需要专门学的嘛。加上现在各种人工智能大语言模型在自动生成代码方面的能力都很强,很容易就得到了好用的html交换的用户界面,用于字符输入、获取、动态演示等。
我甚至以为把关键js的函数放自己电脑上,就算完全实现了本地化。没想到断网之后还是出错了!
Javascript的安全性和跨平台,牺牲了对本地文件读写的便捷性,关键是连读都很难!之前以为本地可以实现了,实际是不了解情况的幻觉。引用了一个不到1M的javascript函数文件,但从它居然能够调用60MB大小的字体和笔顺文件信息,压缩比高得不可思议,代码还都是明文可读的txt格式,这让人不相信。果然断网就不能用了。发现还是隐藏使用了储存在网络的字体和笔画相关的文件!于是把相关文件放在本地,这才意识到javascript不能读!目前用的最偷懒的方法是安装node.js(很大)、安装http-server,启动http-server把保存字体和笔顺信息的文件夹变成一个虚拟的网络服务器上的文件,然后修改引用这些文件的js代码,这才在断网的情况下真正实现了本地化,但相关程序和文件打包仍然不可实现。
对比下来,顶级的大语言模型在我心目中已经有了大致的优劣特征的座次,目前来说,各有千秋,不能偏废,个个都学都用才好。
调试真的很烦
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>汉字输入获取</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
min-height: 100vh;
text-align: center;
position: relative;
background-color: #1a1a1a;
color: #fff;
font-family: sans-serif;
padding: 20px;
box-sizing: border-box;
}
#hanziInput {
width: 200px;
height: 50px;
font-size: 24px;
text-align: center;
margin-top: 20px;
background-color: #333;
color: #fff;
border: none;
border-radius: 5px;
box-shadow: inset 2px 2px 5px rgba(0, 0, 0, 0.5);
}
#button-container {
display: flex;
justify-content: center;
/* 居中按钮 */
align-items: center;
margin-bottom: 10px;
}
.ellipsoid-button {
position: relative;
font-family: sans-serif;
color: #fff;
border: none;
border-radius: 50px;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.5),
-5px -5px 10px rgba(255, 255, 255, 0.2),
inset 2px 2px 5px rgba(255, 255, 255, 0.3),
inset -2px -2px 5px rgba(0, 0, 0, 0.4);
cursor: pointer;
transition: all 0.3s ease;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
padding: 10px 20px;
font-size: 18px;
margin: 0 10px 10px 10px;
/* 按钮间距 */
}
.ellipsoid-button:hover {
transform: translateY(-3px);
box-shadow: 8px 8px 15px rgba(0, 0, 0, 0.6),
-8px -8px 15px rgba(255, 255, 255, 0.25);
}
.ellipsoid-button:active {
transform: translateY(2px);
box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.4),
-3px -3px 6px rgba(255, 255, 255, 0.15),
inset 3px 3px 6px rgba(0, 0, 0, 0.5);
}
#get-character-button {
background: radial-gradient(circle at 30% 30%, #54a0ff, #2e86de);
}
#animate-button00 {
background: radial-gradient(circle at 30% 30%, #88d8b0, #55c57a);
}
#clear-button {
background: radial-gradient(circle at 30% 30%, #e66771, #b53441);
}
#animate-button00:disabled {
background: radial-gradient(circle at 30% 30%, #777, #555);
cursor: not-allowed;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.5),
-5px -5px 10px rgba(255, 255, 255, 0.2),
inset 2px 2px 5px rgba(255, 255, 255, 0.1),
inset -2px -2px 5px rgba(0, 0, 0, 0.2);
}
#character-target-div {
width: 350px;
height: 350px;
margin: 20px 0;
}
#controls {
display: flex;
justify-content: center;
/* 居中控件 */
align-items: center;
margin-bottom: 20px;
}
#radicalCheckbox {
margin: 10px;
}
#output {
font-size: 14px;
/* 缩小字体 */
color: #aaa;
/* 降低亮度 */
position: absolute;
/* 绝对定位到底部 */
bottom: 10px;
/* 距离底部10px */
width: 100%;
/* 占据整个宽度 */
text-align: center;
/* 居中显示 */
}
/* 字体和控件缩放 */
body {
font-size: calc(16px + (24 - 16) * (100vw - 400px) / (1200 - 400));
}
@media (max-width: 400px) {
body {
font-size: 16px;
}
}
@media (min-width: 1200px) {
body {
font-size: 24px;
}
}
.ellipsoid-button {
font-size: calc(12px + (18 - 12) * (100vw - 400px) / (1200 - 400));
padding: calc(5px + (10 - 5) * (100vw - 400px) / (1200 - 400)) calc(10px + (20 - 10) * (100vw - 400px) / (1200 - 400));
}
@media (max-width: 400px) {
.ellipsoid-button {
font-size: 12px;
padding: 5px 10px;
}
}
@media (min-width: 1200px) {
.ellipsoid-button {
font-size: 18px;
padding: 10px 20px;
}
}
</style>
</head>
<body>
<label for="hanziInput">请输入一个汉字:</label>
<input type="text" id="hanziInput">
<div id="button-container">
<button class="ellipsoid-button" id="get-character-button" onclick="getCharacter()">获取汉字</button>
<button class="ellipsoid-button" id="clear-button" onclick="clearInput()">清除</button>
</div>
<div id="character-target-div"></div>
<div id="controls">
<button class="ellipsoid-button" id="animate-button00" onclick="animateCharacter()" disabled>动态演示笔顺</button>
<label>
<input type="checkbox" id="radicalCheckbox" checked onchange="toggleRadical()"> 显示偏旁
</label>
</div>
<p id="output">您输入的汉字是:</p>
<script src="./hanzi-writer.js"></script>
<script>
let writer;
let currentCharacter = '';
function getCharacter() {
const input = document.getElementById("hanziInput").value.trim();
const output = document.getElementById("output");
const button = document.getElementById("animate-button00");
const firstChar = input.length > 0 ? input.charAt(0) : '';
if (firstChar.length === 1) {
const charCode = firstChar.charCodeAt(0);
if (charCode >= 0x4E00 && charCode <= 0x9FA5) {
output.innerText = "您输入的汉字是:" + firstChar;
button.disabled = false;
currentCharacter = firstChar;
if (!writer) {
writer = HanziWriter.create('character-target-div', firstChar, {
width: 320,
height: 320,
padding: 5,
strokeAnimationSpeed: 1.75,
showOutline: true,
radicalColor: '#99EE99'
});
} else {
writer.setCharacter(firstChar);
}
toggleRadical();
} else {
output.innerText = "您输入的字符不是有效的汉字字符";
button.disabled = true;
currentCharacter = '';
}
} else {
output.innerText = "您输入的字符不是有效的汉字字符";
button.disabled = true;
currentCharacter = '';
}
}
function clearInput() {
document.getElementById("hanziInput").value = "";
document.getElementById("output").innerText = "您输入的汉字是:";
document.getElementById("animate-button00").disabled = true;
document.getElementById("hanziInput").focus();
currentCharacter = '';
}
function animateCharacter() {
if (writer) {
writer.animateCharacter();
} else {
alert("请先输入一个汉字!");
}
}
function toggleRadical() {
if (writer) {
const showRadical = document.getElementById("radicalCheckbox").checked;
writer.updateOptions({
showRadical: showRadical,
radicalColor: showRadical ? '#99EE99' : '#000'
});
writer.setCharacter(currentCharacter);
}
}
</script>
</body>
</html>
以及下面:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>汉字输入获取</title>
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
min-height: 100vh;
text-align: center;
position: relative;
background-color: #f0f0f0; /* 浅色背景 */
color: #333; /* 深色文字,与浅色背景形成对比 */
font-family: sans-serif;
padding: 20px;
box-sizing: border-box;
}
#hanziInput {
width: 200px;
height: 50px;
font-size: 24px;
text-align: center;
margin-top: 20px;
background-color: #fff; /* 白色输入框 */
color: #333;
border: 1px solid #ccc; /* 浅灰色边框 */
border-radius: 5px;
box-shadow: inset 2px 2px 5px rgba(0, 0, 0, 0.1); /* 浅阴影 */
}
#button-container {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 10px;
}
.ellipsoid-button {
position: relative;
font-family: sans-serif;
color: #fff;
border: none;
border-radius: 50px;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2),
-5px -5px 10px rgba(255, 255, 255, 0.5),
inset 2px 2px 5px rgba(255, 255, 255, 0.4),
inset -2px -2px 5px rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.3s ease;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
padding: 10px 20px;
font-size: 18px;
margin: 0 10px 10px 10px;
}
.ellipsoid-button:hover {
transform: translateY(-3px);
box-shadow: 8px 8px 15px rgba(0, 0, 0, 0.3),
-8px -8px 15px rgba(255, 255, 255, 0.6);
}
.ellipsoid-button:active {
transform: translateY(2px);
box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.1),
-3px -3px 6px rgba(255, 255, 255, 0.3),
inset 3px 3px 6px rgba(0, 0, 0, 0.2);
}
#get-character-button {
background: radial-gradient(circle at 30% 30%, #54a0ff, #2e86de);
}
#animate-button00 {
background: radial-gradient(circle at 30% 30%, #88d8b0, #55c57a);
}
#clear-button {
background: radial-gradient(circle at 30% 30%, #e66771, #b53441);
}
#animate-button00:disabled {
background: radial-gradient(circle at 30% 30%, #ddd, #bbb);
cursor: not-allowed;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.1),
-5px -5px 10px rgba(255, 255, 255, 0.3),
inset 2px 2px 5px rgba(255, 255, 255, 0.2),
inset -2px -2px 5px rgba(0, 0, 0, 0.1);
}
#character-target-div {
width: 350px;
height: 350px;
margin: 20px 0;
}
#controls {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
}
#radicalCheckbox {
margin: 10px;
}
#output {
font-size: 14px;
color: #777;
position: absolute;
bottom: 10px;
width: 100%;
text-align: center;
}
/* 字体和控件缩放 */
body {
font-size: calc(16px + (24 - 16) * (100vw - 400px) / (1200 - 400));
}
@media (max-width: 400px) {
body {
font-size: 16px;
}
}
@media (min-width: 1200px) {
body {
font-size: 24px;
}
}
.ellipsoid-button {
font-size: calc(12px + (18 - 12) * (100vw - 400px) / (1200 - 400));
padding: calc(5px + (10 - 5) * (100vw - 400px) / (1200 - 400)) calc(10px + (20 - 10) * (100vw - 400px) / (1200 - 400));
}
@media (max-width: 400px) {
.ellipsoid-button {
font-size: 12px;
padding: 5px 10px;
}
}
@media (min-width: 1200px) {
.ellipsoid-button {
font-size: 18px;
padding: 10px 20px;
}
}
</style>
</head>
<body>
<label for="hanziInput">请输入一个汉字:</label>
<input type="text" id="hanziInput">
<div id="button-container">
<button class="ellipsoid-button" id="get-character-button" onclick="getCharacter()">获取汉字</button>
<button class="ellipsoid-button" id="clear-button" onclick="clearInput()">清除</button>
</div>
<div id="character-target-div"></div>
<div id="controls">
<button class="ellipsoid-button" id="animate-button00" onclick="animateCharacter()" disabled>动态演示笔顺</button>
<label>
<input type="checkbox" id="radicalCheckbox" checked onchange="toggleRadical()"> 显示偏旁
</label>
</div>
<p id="output">您输入的汉字是:</p>
<script src="./hanzi-writer-local.js"></script>
<script>
let writer;
let currentCharacter = '';
function getCharacter() {
const input = document.getElementById("hanziInput").value.trim();
const output = document.getElementById("output");
const button = document.getElementById("animate-button00");
const firstChar = input.length > 0 ? input.charAt(0) : '';
if (firstChar.length === 1) {
const charCode = firstChar.charCodeAt(0);
if (charCode >= 0x4E00 && charCode <= 0x9FA5) {
output.innerText = "您输入的汉字是:" + firstChar;
button.disabled = false;
currentCharacter = firstChar;
if (!writer) {
writer = HanziWriter.create('character-target-div', firstChar, {
width: 310,
height: 310,
padding: 5,
strokeAnimationSpeed: 1.5,
showOutline: true,
radicalColor: '#99EE99'
});
} else {
writer.setCharacter(firstChar);
}
toggleRadical();
} else {
output.innerText = "您输入的字符不是有效的汉字字符";
button.disabled = true;
currentCharacter = '';
}
} else {
output.innerText = "您输入的字符不是有效的汉字字符";
button.disabled = true;
currentCharacter = '';
}
}
function clearInput() {
document.getElementById("hanziInput").value = "";
document.getElementById("output").innerText = "您输入的汉字是:";
document.getElementById("animate-button00").disabled = true;
document.getElementById("hanziInput").focus();
currentCharacter = '';
}
function animateCharacter() {
if (writer) {
writer.animateCharacter();
} else {
alert("请先输入一个汉字!");
}
}
function toggleRadical() {
if (writer) {
const showRadical = document.getElementById("radicalCheckbox").checked;
writer.updateOptions({
showRadical: showRadical,
radicalColor: showRadical ? '#99EE99' : '#000'
});
writer.setCharacter(currentCharacter);
}
}
</script>
</body>
</html>