实现了下面功能:
1、根据输入汉字,自动调整米字格和四线格的行数;
2、给汉字自动加上拼音和声调(暂时不考虑多音字);
3、汉字在米字格,拼音在四线格,
4、第一列用黑色,2-5列四列浅灰以描摹,第6列默写;
5、暂时调整这么多。
我的一个发现:用大语言模型写代码,局限性还是太多。要想完成复杂的项目,不但功能、界面设计方面要深度介入,由于当前大模型的局限太多,如何选择模型、如何使用提示词、按照何种次序和起始点来使用大模型和提示词,都是需要练习和反复练习的。
所以,完全否定通过AI生成的作品的“著作权”是不合适的。大模型就是计算机的智能键盘、是画家的智能画布和笔刷。好作品仍然需要付出很多创造性劳动和非创造性劳动。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>四线格与米字格生成器(带拼音)</title>
<style>
@font-face {
font-family: 'TeXGyreAdventor';
src:
local('TeX Gyre Adventor'),
url('fonts/texgyreadventor-regular.woff2') format('woff2'),
url('fonts/texgyreadventor-regular.otf') format('opentype');
font-display: swap;
}
body {
font-family: 'TeXGyreAdventor', 'KaiTi', serif;
text-align: center;
padding: 20px;
}
#input-container {
margin-bottom: 20px;
}
#hanzi-input {
font-size: 28px;
padding: 10px;
width: 300px;
}
#generate-btn, #print-btn, #clear-btn {
font-size: 18px;
padding: 10px 20px;
margin: 0 10px;
}
#grid-container {
display: flex;
flex-direction: column;
align-items: center;
}
.row {
display: flex;
position: relative;
width: 600px; /* 6列总宽度 */
}
/* 四线格样式 */
.pinyin-row {
height: 48px; /* 3个16px间距 */
}
.pinyin-cell {
width: 100px;
height: 48px;
display: flex;
justify-content: center;
align-items: center;
}
.pinyin-row.first::before, .pinyin-row .line1, .pinyin-row .line2, .pinyin-row::after {
content: '';
position: absolute;
width: 600px; /* 与米字格等宽 */
height: 0;
left: 0;
border: 1px solid red; /* 红色实线 */
z-index: 0; /* 底层 */
}
.pinyin-row.first::before {
top: 0; /* 第一行四线格第1条 */
}
.pinyin-row .line1 {
top: 16px; /* 第2条 */
}
.pinyin-row .line2 {
top: 32px; /* 第3条 */
}
.pinyin-row::after {
bottom: 0; /* 底部边框,与下方米字格共用 */
}
.pinyin-cell span {
font-family: 'TeXGyreAdventor', 'KaiTi', serif;
font-size: 28px; /* 调整为28号字体 */
position: relative;
z-index: 1; /* 文字在上层 */
}
.black span {
color: black;
opacity: 1;
}
.gray span {
color: black;
opacity: 0.25;
}
/* 米字格样式 */
.char-row {
margin-top: -1px; /* 与上方共用边框 */
}
.cell {
width: 100px;
height: 100px;
border-bottom: 1px solid red; /* 底部边框 */
border-right: 1px solid red; /* 右侧边框 */
border-left: 1px solid red; /* 左侧边框,首列使用 */
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-size: 72px;
font-family: '海棠未雨', serif;
}
.cell:not(:first-child) {
border-left: none; /* 水平共用边框 */
}
.char-row .cell {
border-top: 1px solid red; /* 所有米字格保留顶部边框,与上方四线格共用 */
}
.cell::before, .cell::after {
content: '';
position: absolute;
border: 1px dashed red; /* 红色虚线 */
z-index: 0; /* 底层 */
}
.cell::before {
width: 100%;
height: 0;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.cell::after {
width: 0;
height: 100%;
left: 50%;
top: 0;
transform: translateX(-50%);
}
.diagonal1, .diagonal2 {
position: absolute;
width: 141px;
height: 0;
border: 1px dashed red; /* 红色虚线 */
z-index: 0; /* 底层 */
}
.diagonal1 {
top: 0;
left: 0;
transform: rotate(45deg);
transform-origin: 0 0;
}
.diagonal2 {
bottom: 0;
left: 0;
transform: rotate(-45deg);
transform-origin: 0 100%;
}
.cell span {
position: relative;
z-index: 1; /* 文字在上层 */
}
.black span {
color: black;
opacity: 1;
}
.gray span {
color: black;
opacity: 0.25;
}
@media print {
#input-container, #generate-btn, #print-btn, #clear-btn {
display: none;
}
#grid-container {
display: block;
}
}
</style>
</head>
<body>
<div id="input-container">
<input type="text" id="hanzi-input" value="寳寶氷麤鳯龘">
<button id="clear-btn">清除</button>
<button id="generate-btn">生成</button>
<button id="print-btn">打印</button>
</div>
<div id="grid-container"></div>
<!-- 引入拼音库文件 -->
<script type="text/javascript" src="./pinyin_dict_withtone.js"></script>
<script type="text/javascript" src="./pinyinUtil.js"></script>
<!-- 引入 html2canvas 和 jsPDF 库 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script>
window.onload = function() {
generateGrid();
};
function generateGrid() {
const input = document.getElementById('hanzi-input').value;
const gridContainer = document.getElementById('grid-container');
gridContainer.innerHTML = ''; // 清空现有内容
// 获取拼音(带声调)
const pinyinArray = pinyinUtil.getPinyin(input, ' ', true, false).split(' ');
for (let i = 0; i < input.length; i++) {
// 生成四线格行(填充拼音)
const pinyinRow = document.createElement('div');
pinyinRow.className = 'row pinyin-row';
if (i === 0) {
pinyinRow.classList.add('first'); // 第一行四线格有3条独立线
} else {
pinyinRow.style.marginTop = '-1px'; // 与上方米字格共用底部边框
}
const line1 = document.createElement('div');
line1.className = 'line1';
const line2 = document.createElement('div');
line2.className = 'line2';
pinyinRow.appendChild(line1);
pinyinRow.appendChild(line2);
for (let j = 0; j < 6; j++) {
const pinyinCell = document.createElement('div');
pinyinCell.className = 'pinyin-cell';
const span = document.createElement('span');
if (j === 0) {
span.textContent = pinyinArray[i] || ''; // 第一列填充拼音
span.classList.add('black');
} else if (j < 5) {
// span.textContent = pinyinArray[i] || ''; // 第二到第五列灰色拼音
// span.classList.add('gray');
}
pinyinCell.appendChild(span);
pinyinRow.appendChild(pinyinCell);
}
gridContainer.appendChild(pinyinRow);
// 生成米字格行(填充汉字)
const charRow = document.createElement('div');
charRow.className = 'row char-row';
for (let j = 0; j < 6; j++) {
const cell = document.createElement('div');
cell.className = 'cell';
const diag1 = document.createElement('div');
diag1.className = 'diagonal1';
const diag2 = document.createElement('div');
diag2.className = 'diagonal2';
cell.appendChild(diag1);
cell.appendChild(diag2);
const span = document.createElement('span');
if (j === 0) {
span.textContent = input[i]; // 每个汉字填充到米字格第一列
cell.classList.add('black');
} else if (j < 5) {
span.textContent = input[i]; // 第二到第五列灰色
cell.classList.add('gray');
}
cell.appendChild(span);
charRow.appendChild(cell);
}
gridContainer.appendChild(charRow);
}
}
document.getElementById('generate-btn').addEventListener('click', function() {
generateGrid();
});
document.getElementById('print-btn').addEventListener('click', function() {
const gridContainer = document.getElementById('grid-container');
// 使用 html2canvas 将 grid-container 渲染为图像
html2canvas(gridContainer, {
scale: 2, // 提高分辨率,确保清晰度
useCORS: true, // 处理可能的跨域问题
backgroundColor: '#ffffff', // 设置背景为白色,避免透明
logging: true // 启用日志以便调试
}).then(canvas => {
const imgData = canvas.toDataURL('image/png'); // 将 Canvas 转换为 PNG 图像数据
const { jsPDF } = window.jspdf; // 从全局对象中获取 jsPDF
const doc = new jsPDF({
orientation: 'portrait',
unit: 'mm',
format: 'a4'
});
// 计算图像在 PDF 中的尺寸
const pageWidth = 210; // A4 宽度 (mm)
const pageHeight = 297; // A4 高度 (mm)
const margin = 10; // 边距
const imgWidth = pageWidth - 2 * margin; // PDF 中图像宽度
const imgHeight = (canvas.height * imgWidth) / canvas.width; // 按比例计算高度
let heightLeft = imgHeight;
let position = margin; // 从顶部边距开始
// 添加第一页图像
doc.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight);
heightLeft -= (pageHeight - 2 * margin);
// 处理分页
while (heightLeft > 0) {
doc.addPage();
position = -heightLeft + margin; // 调整位置以显示剩余部分
doc.addImage(imgData, 'PNG', margin, position, imgWidth, imgHeight);
heightLeft -= (pageHeight - 2 * margin);
}
// 保存 PDF 文件
doc.save('字帖.pdf');
}).catch(error => {
console.error('html2canvas 渲染失败:', error);
alert('生成 PDF 失败,请检查控制台错误信息。');
});
});
document.getElementById('clear-btn').addEventListener('click', function() {
const input = document.getElementById('hanzi-input');
const gridContainer = document.getElementById('grid-container');
input.value = '';
gridContainer.innerHTML = '';
input.focus();
});
</script>
</body>
</html>