网络日志搬迁中
文章集
工具集
|
对抗暗水印 之前做了个工具为作64*64的像素画。是将一张64*64的位图文件转矢量图,先把图片的每一个像素读出来,排列好,再把排列好的十六进制码写进svg,rect标签,用脚本。 最后得到图像,除了64行标签什么也没有。好方便Base64编码内联到css中去。svg的图片代码干净,可以读懂,可以和位图一样堆像素,就是这样做比较大。若不是64*64,4k图片转为<rect x="0" y="0" width="1" height="1" style="fill:#040033;" />,这样子在txt中打开,到1,829,330,944 字节了。 把原来的做头像的工具改一下,一个是不要长宽的限制,第二个是原来的代码有一个多余的操作是hex color = f"#{r:02x}{g:02x}{b:02x}"将RGB值格式化为十六进制字符串,连同以下的f.write(hex_color + "\n")替换成输出 RGB 数值的语句f.write(f"{r},{g},{b}\n")。 然后逐行读生成的txt,每一条的R值、B值、G值上下随机调动1~3位。 再把动过的txt文件还原成位图文件,png_file = "Ship of Theseus.png"。不要还原成svg,太大了会大不开。其实txt文件已经打不开了,需要用编译器打开,而且复制不了,因为全选也做不到。 |
|
网页的开发原因 网页开发的时间很短,从4月1日开始编辑至4月4日完工。本来是想编辑视觉效果更复杂的网页,借宿在这的朋友问了句“这么多矢量图一定会画到春天过去了,那时候你已经是找实习的时候了吧?”给我破防了,便突击了一个在样式上简单易制作的网页。 |
|
JavaScript筛选功能data标签指向文章 最开始的做法是一个链接一个html文件,在学校里也是这么做的嘛,但携标签的侧边栏内容都要在每个html中使用的话就很混乱了。 很大的问题就是代码冗杂,把侧边栏的html结构、css、js渲染逻辑、折叠动画、筛选函数全部复制到每一个文章页面,往后只要侧边栏结构增删、修改标签名称、调整折叠动画速度都必须打开每一个独立 html 文件修改,文件数量越多维护成本指数上升,复制粘贴都会烦,就不想遗漏的故事了。最终整个网站结构彻底狂乱无法维护。 Web 标准中给了data标签,hmtl里每篇文章 data是数据属性,把标签直接写在文章元素自身上,不要额外的其他什么,标记上的标签自带数据,JS 可以读取,也不需要依赖外部数据,筛选时不需要遍历复杂数据结构。正好合适我这个不明白数据库的,给了我一个通常侧边栏以外的解决方案。不占用额外网络资源,不跳转到新html,页面都不用重新刷新了。重要的是避免大量重复代码,不然一个一个去专门的标签html和文章html覆盖增删的标签也太灾难了。 |
|
ttf中文字体文件内联css的办法 生产中不会把完整的过大的中文字体包内联到 css 里。有fontspider这个方案,不做输入的话,可以把使用了的文字打包成一个小字体包,其他没用的字不要,就是字体子集化,从几十 MB 的大包里,只切出网页里实际用到的几十个汉字,生成一个几十 KB 的全新小字体包。文字包内联到css里,体积还不会太大。不过每次更新网站都要把新字加上去就是了。 不过我现下的情况在开发像素网页时像素字体是必须的,也不能因为网络问题失效了外部资源引用导致视觉效果差错,视觉上有接受不能,资源所以尽量内联,多做同步阻塞,减少异步加载。用 css 加载字体包,要用到 Web Fonts,还是异步加载。 图片没办法,只能用三方库,直接监听图片加载,加载结束才浏览网页。 我想编辑出美观的网页,无论网络环境好坏的人们,能看到同样的画面,点进网页的人将承受首屏加载的代价,对不起喵。 字体转换网站Font Squirrel可以将tff、otf、wpff和woff2等字体包格式,转换成 @font-face 格式,随意地插入随便哪个标签。不过因为国外网站网速慢,中文字体的转换会很久,我想网站是为了转换英文字体包而设计的,不考虑过大的中文字体包。 为了方便,就在本地浏览器编码tff好了,写一个html工具在浏览器中打开
.html
<input type="file" id="fontFile" onchange="encodeFont()">
<script>
function encodeFont() {
const file = document.getElementById('fontFile').files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
console.log(e.target.result);
showToast("已输出Base64,打开控制台");
};
reader.readAsDataURL(file);
}
</script>
点击按钮,上传ttf字体文件。开浏览器控制台把复制下来的Base64 编码复制在data:font/truetype;charset=utf-8;base64,的后面,替换...的部分。
.css
@font-face {
font-family: 'cnttf';
src: url(data:font/truetype;charset=utf-8;base64, ... ) format('truetype');
}
任意标签 {
font-family: 'cnttf', sans-serif;
}
|
|
生成随机字符
.html
<!DOCTYPE html>
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>随机字符生成</title>
</head>
<body>
<div style="display: flex; justify-content: center; align-items: center; flex-direction: column;">
<div class="container">
<h1>随机字符生成</h1>
<div>
<label for="passwordOutput" style="font-family: monospace; font-weight: bold;">生成字符:</label><br>
<input type="text" id="passwordOutput" class="password-field" readonly="" size="40" value="点击生成" style="background-color: rgb(248, 248, 248); border: 1px solid rgb(170, 170, 170); padding: 6px;">
</div>
<div style="margin-top: 15px;">
<button id="generateBtn" style="font-family: monospace; padding: 5px 12px; cursor: pointer;">生成新字符</button>
<button id="copyBtn" style="font-family: monospace; padding: 5px 12px; cursor: pointer; margin-left: 12px;">复制到剪贴板</button>
</div>
<hr>
<div style="margin-bottom: 15px;">
<label for="lengthSlider" style="font-family: monospace; font-weight: bold;">字符长度:</label>
<input type="range" id="lengthSlider" min="3" max="32" value="12" step="1" style="width: 220px; vertical-align: middle;">
<input type="number" id="lengthNumber" min="3" max="32" value="12" step="1" style="width: 55px; font-family: monospace; text-align: center; margin-left: 8px;">
<span style="font-family: monospace; margin-left: 8px;">字符</span>
</div>
<fieldset style="border: 1px solid #aaa; padding: 10px 15px; display: inline-block; margin-top: 8px;">
<legend style="font-family: monospace; font-weight: bold;">字符池</legend>
<div style="display: flex; flex-wrap: wrap; gap: 18px; justify-content: center;">
<label style="font-family: monospace;">
<input type="checkbox" id="useUpper" checked=""> 大写字母 (A-Z)
</label>
<label style="font-family: monospace;">
<input type="checkbox" id="useLower" checked=""> 小写字母 (a-z)
</label>
<label style="font-family: monospace;">
<input type="checkbox" id="useDigits" checked=""> 数字 (0-9)
</label>
<label style="font-family: monospace;">
<input type="checkbox" id="useSpecial"> 特殊符号 (!@#$%^&*...)
</label>
</div>
</fieldset>
<div id="statusMsg" style="font-family: monospace; margin-top: 15px; font-size: 0.85rem; color: rgb(44, 62, 44); min-height: 2.2em;"></div>
</div>
</div>
<script>
(function() {
const passwordOutput = document.getElementById('passwordOutput');
const generateBtn = document.getElementById('generateBtn');
const copyBtn = document.getElementById('copyBtn');
const lengthSlider = document.getElementById('lengthSlider');
const lengthNumber = document.getElementById('lengthNumber');
const useUpperChk = document.getElementById('useUpper');
const useLowerChk = document.getElementById('useLower');
const useDigitsChk = document.getElementById('useDigits');
const useSpecialChk = document.getElementById('useSpecial');
const statusSpan = document.getElementById('statusMsg');
const UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const LOWER = 'abcdefghijklmnopqrstuvwxyz';
const DIGITS = '0123456789';
const SPECIAL = '!@#$%^&*()_+-=[]{}|;:,.<>?';
function showMessage(msg, isError = false) {
statusSpan.textContent = msg;
statusSpan.style.color = isError ? '#aa2e2e' : '#2c6e2c';
setTimeout(() => {
if (statusSpan.textContent === msg) {
statusSpan.textContent = '';
statusSpan.style.color = '#2c3e2c';
}
}, 2800);
}
function secureRandomInt(min, max) {
const range = max - min + 1;
if (range <= 0) return min;
const maxValid = Math.floor(0xFFFFFFFF / range) * range;
let randomVal;
const randomArray = new Uint32Array(1);
do {
crypto.getRandomValues(randomArray);
randomVal = randomArray[0];
} while (randomVal >= maxValid);
return min + (randomVal % range);
}
function randomCharFromSet(charSet) {
if (!charSet || charSet.length === 0) return '';
const idx = secureRandomInt(0, charSet.length - 1);
return charSet[idx];
}
function shuffleArray(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = secureRandomInt(0, i);
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
function generatePassword(length, useUpper, useLower, useDigits, useSpecial) {
const activeSets = [];
if (useUpper) activeSets.push(UPPER);
if (useLower) activeSets.push(LOWER);
if (useDigits) activeSets.push(DIGITS);
if (useSpecial) activeSets.push(SPECIAL);
if (activeSets.length === 0) {
activeSets.push(LOWER);
useLowerChk.checked = true;
showMessage("未选择任何字符集,已自动启用小写字母", false);
}
const minRequired = activeSets.length;
let finalLength = length;
if (finalLength < minRequired) {
finalLength = minRequired;
lengthSlider.value = finalLength;
lengthNumber.value = finalLength;
showMessage(`长度不足以保证每个类别至少一个字符,已自动调整为 ${finalLength}`, false);
}
let fullCharPool = '';
for (let set of activeSets) {
fullCharPool += set;
}
if (fullCharPool.length === 0) {
return "error";
}
const passwordChars = [];
for (let set of activeSets) {
const guaranteedChar = randomCharFromSet(set);
passwordChars.push(guaranteedChar);
}
const remaining = finalLength - activeSets.length;
if (remaining > 0) {
for (let i = 0; i < remaining; i++) {
const randChar = randomCharFromSet(fullCharPool);
passwordChars.push(randChar);
}
}
const shuffled = shuffleArray([...passwordChars]);
return shuffled.join('');
}
function updateLengthConstraints() {
let activeCount = 0;
if (useUpperChk.checked) activeCount++;
if (useLowerChk.checked) activeCount++;
if (useDigitsChk.checked) activeCount++;
if (useSpecialChk.checked) activeCount++;
if (activeCount === 0) activeCount = 1;
const minLen = activeCount;
const currentLen = parseInt(lengthSlider.value, 10);
lengthSlider.min = minLen;
lengthNumber.min = minLen;
if (currentLen < minLen) {
lengthSlider.value = minLen;
lengthNumber.value = minLen;
showMessage(`字符集最少需要 ${minLen} 位长度,已自动调整`, false);
}
}
function enforceAtLeastOneCheckbox() {
const anyChecked = useUpperChk.checked || useLowerChk.checked || useDigitsChk.checked || useSpecialChk.checked;
if (!anyChecked) {
useLowerChk.checked = true;
showMessage("至少需要一种字符类型,已重新启用小写字母", false);
updateLengthConstraints();
}
}
function syncLengthInputs() {
const sliderVal = parseInt(lengthSlider.value, 10);
const numVal = parseInt(lengthNumber.value, 10);
if (sliderVal !== numVal) {
lengthNumber.value = sliderVal;
}
let current = parseInt(lengthNumber.value, 10);
const minVal = parseInt(lengthSlider.min, 10);
const maxVal = parseInt(lengthSlider.max, 10);
if (isNaN(current)) current = minVal;
if (current < minVal) current = minVal;
if (current > maxVal) current = maxVal;
if (current !== parseInt(lengthNumber.value, 10)) {
lengthNumber.value = current;
lengthSlider.value = current;
}
}
function refreshPassword() {
enforceAtLeastOneCheckbox();
updateLengthConstraints();
syncLengthInputs();
let lengthVal = parseInt(lengthSlider.value, 10);
const minPossible = parseInt(lengthSlider.min, 10);
if (lengthVal < minPossible) lengthVal = minPossible;
const useUpper = useUpperChk.checked;
const useLower = useLowerChk.checked;
const useDigits = useDigitsChk.checked;
const useSpecial = useSpecialChk.checked;
if (!useUpper && !useLower && !useDigits && !useSpecial) {
useLowerChk.checked = true;
showMessage("字符集缺失,启用小写字母作为后备", false);
return refreshPassword();
}
try {
const newPassword = generatePassword(lengthVal, useUpper, useLower, useDigits, useSpecial);
if (newPassword && newPassword.length === lengthVal) {
passwordOutput.value = newPassword;
showMessage("新字符已生成 | 长度: " + newPassword.length, false);
} else {
console.warn("生成字符长度不一致,重新尝试");
const fallbackPwd = generatePassword(lengthVal, useUpper, useLower, useDigits, useSpecial);
passwordOutput.value = fallbackPwd;
showMessage("字符已生成 (安全随机)", false);
}
} catch (err) {
console.error(err);
passwordOutput.value = "生成失败,请重试";
showMessage("生成错误,请检查配置", true);
}
}
async function copyPasswordToClipboard() {
const pwd = passwordOutput.value;
if (!pwd || pwd === "点击生成" || pwd === "生成失败,请重试") {
showMessage("没有有效字符可复制,请先生成", true);
return;
}
try {
await navigator.clipboard.writeText(pwd);
showMessage("字符已复制到剪贴板", false);
passwordOutput.style.backgroundColor = "#e6f0e6";
setTimeout(() => {
passwordOutput.style.backgroundColor = "#f8f8f8";
}, 300);
} catch (err) {
passwordOutput.select();
const success = document.execCommand('copy');
if (success) {
showMessage("字符已复制 (传统方式)", false);
} else {
showMessage("复制失败了,手动选取", true);
}
passwordOutput.setSelectionRange(0, 0);
}
}
generateBtn.addEventListener('click', () => {
refreshPassword();
});
copyBtn.addEventListener('click', () => {
copyPasswordToClipboard();
});
lengthSlider.addEventListener('input', function() {
let val = parseInt(this.value, 10);
const minLimit = parseInt(this.min, 10);
if (val < minLimit) val = minLimit;
if (val > 32) val = 32;
lengthSlider.value = val;
lengthNumber.value = val;
let activeCount = 0;
if (useUpperChk.checked) activeCount++;
if (useLowerChk.checked) activeCount++;
if (useDigitsChk.checked) activeCount++;
if (useSpecialChk.checked) activeCount++;
if (activeCount === 0) activeCount = 1;
if (val < activeCount) {
showMessage(`注意:当前长度小于所选字符类别数(${activeCount}),点击生成将自动调整`, false);
} else {
if (statusSpan.textContent.includes("小于所选字符类别数")) statusSpan.textContent = "";
}
});
lengthNumber.addEventListener('input', function() {
let val = parseInt(this.value, 10);
if (isNaN(val)) val = lengthSlider.min;
const minLimit = parseInt(lengthSlider.min, 10);
const maxLimit = 32;
if (val < minLimit) val = minLimit;
if (val > maxLimit) val = maxLimit;
lengthNumber.value = val;
lengthSlider.value = val;
let activeCount = 0;
if (useUpperChk.checked) activeCount++;
if (useLowerChk.checked) activeCount++;
if (useDigitsChk.checked) activeCount++;
if (useSpecialChk.checked) activeCount++;
if (activeCount === 0) activeCount = 1;
if (val < activeCount) {
showMessage(`长度小于字符类别数(${activeCount}),生成时自动修正`, false);
}
});
function onCheckboxChange() {
enforceAtLeastOneCheckbox();
updateLengthConstraints();
syncLengthInputs();
showMessage("字符集已更新,点击「生成新字符」生效", false);
}
useUpperChk.addEventListener('change', onCheckboxChange);
useLowerChk.addEventListener('change', onCheckboxChange);
useDigitsChk.addEventListener('change', onCheckboxChange);
useSpecialChk.addEventListener('change', onCheckboxChange);
function init() {
if (!useUpperChk.checked) useUpperChk.checked = true;
if (!useLowerChk.checked) useLowerChk.checked = true;
if (!useDigitsChk.checked) useDigitsChk.checked = true;
updateLengthConstraints();
syncLengthInputs();
refreshPassword();
}
init();
window.addEventListener('load', function() {
if (!passwordOutput.value || passwordOutput.value === "点击生成") {
refreshPassword();
}
});
setInterval(function() {
const currentLen = parseInt(lengthSlider.value, 10);
let activeCount = 0;
if (useUpperChk.checked) activeCount++;
if (useLowerChk.checked) activeCount++;
if (useDigitsChk.checked) activeCount++;
if (useSpecialChk.checked) activeCount++;
if (activeCount === 0) activeCount = 1;
if (currentLen < activeCount) {
updateLengthConstraints();
syncLengthInputs();
}
}, 10000);
})();
</script>
</body></html>
|
|
ttf转Base64url编码
.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>字体转Base64工具</title>
</head>
<body>
<h2>ttf转Base64url编码</h2>
<p>选择.ttf、.otf字体文件,转换后的完整DataURL会表示在下方文本区,点击按钮复制</p>
<input type="file" id="fontFile" accept=".ttf,.otf">
<div id="fileInfo"></div>
<table border="1" cellpadding="8" cellspacing="0">
<tr>
<td valign="top">
<button id="copyBtn">复制Base64结果</button>
<div>点击按钮复制完整字符串</div>
</td>
<td width="95%">
<textarea id="resultArea" readonly rows="12" cols="100" wrap="soft" placeholder="请选择字体文件(.ttf / .otf),转换后会表示Base64编码结果...结果将完整展示在此区域,点击按钮即可复制"></textarea>
<div id="resultMeta"></div>
</td>
</tr>
</table>
<div id="statusMessage"></div>
<script>
(function() {
const fileInput = document.getElementById('fontFile');
const resultArea = document.getElementById('resultArea');
const copyBtn = document.getElementById('copyBtn');
const fileInfoDiv = document.getElementById('fileInfo');
const resultMetaDiv = document.getElementById('resultMeta');
const statusMsgDiv = document.getElementById('statusMessage');
let pendingFile = null;
function updateFileInfo(file) {
if (!file) {
fileInfoDiv.innerHTML = '';
return;
}
const sizeKB = (file.size / 1024).toFixed(2);
const sizeMB = (file.size / (1024 * 1024)).toFixed(2);
let sizeStr = sizeKB + ' KB';
if (file.size > 1024 * 1024) {
sizeStr = sizeMB + ' MB (' + sizeKB + ' KB)';
}
fileInfoDiv.innerHTML = '已选择: ' + file.name + ' | 大小: ' + sizeStr;
}
function clearResult(placeholderMsg) {
if (placeholderMsg) {
resultArea.value = placeholderMsg;
} else {
resultArea.value = '';
}
resultMetaDiv.innerHTML = '';
}
function displayResult(dataURL, file) {
if (!dataURL) {
resultArea.value = '转换失败:未获取到有效数据';
resultMetaDiv.innerHTML = '';
return;
}
resultArea.value = dataURL;
const totalLength = dataURL.length;
const base64Part = dataURL.split(',')[1] || '';
const rawBase64Len = base64Part.length;
resultMetaDiv.innerHTML = '转换终了 | 完整字符串长度: ' + totalLength + ' 字符 | Base64数据长度: ' + rawBase64Len + ' 字符 | 文件: ' + file.name;
statusMsgDiv.innerHTML = '转换终了结果已表示在下方文本区,点击左侧“复制Base64结果”按钮即可复制完整字符串。';
console.log('[字体转Base64] 转换终了,DataURL长度:', totalLength);
}
function showError(errorMsg, file) {
resultArea.value = '转换出错: ' + errorMsg + '\n请检查字体文件是否有效或重试。';
resultMetaDiv.innerHTML = '错误: ' + errorMsg;
statusMsgDiv.innerHTML = '处理失败: ' + errorMsg;
console.error('[字体转Base64] 错误:', errorMsg, file ? file.name : '');
}
function convertFontToBase64(file) {
if (!file) {
showError('未选择有效文件', null);
return;
}
updateFileInfo(file);
const fileName = file.name.toLowerCase();
if (!fileName.endsWith('.ttf') && !fileName.endsWith('.otf')) {
statusMsgDiv.innerHTML = '注意: 文件 "' + file.name + '" 扩展名不是 .ttf 或 .otf,转换仍继续,但确保是有效字体文件。';
} else {
statusMsgDiv.innerHTML = '正在转换字体文件 "' + file.name + '",请稍候...';
}
resultArea.value = '正在读取并编码字体文件,请稍候...\n(大文件可能需要几秒钟)';
resultMetaDiv.innerHTML = '';
const currentFileToken = file;
pendingFile = currentFileToken;
const reader = new FileReader();
reader.onload = function(ev) {
if (pendingFile !== currentFileToken) {
console.log('[忽略] 文件 "' + currentFileToken.name + '" 转换终了,但已被新文件覆盖,不更新界面。');
return;
}
const dataURL = ev.target.result;
if (dataURL && typeof dataURL === 'string' && dataURL.startsWith('data:')) {
displayResult(dataURL, currentFileToken);
} else {
showError('读取结果无效,未能生成有效的DataURL', currentFileToken);
}
pendingFile = null;
};
reader.onerror = function(err) {
if (pendingFile !== currentFileToken) {
console.log('[忽略错误] 文件 "' + currentFileToken.name + '" 读取失败但已被覆盖。');
return;
}
showError('文件读取失败: ' + (reader.error ? reader.error.message : '未知错误'), currentFileToken);
pendingFile = null;
};
reader.onabort = function() {
if (pendingFile === currentFileToken) {
showError('读取操作已取消', currentFileToken);
pendingFile = null;
}
};
reader.readAsDataURL(file);
}
fileInput.addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) {
fileInfoDiv.innerHTML = '';
resultArea.value = '未选择任何字体文件,请选择 .ttf 或 .otf 文件。';
resultMetaDiv.innerHTML = '';
statusMsgDiv.innerHTML = '';
pendingFile = null;
return;
}
convertFontToBase64(file);
});
copyBtn.addEventListener('click', async function() {
const contentToCopy = resultArea.value;
if (!contentToCopy ||
contentToCopy === '未选择任何字体文件,请选择 .ttf 或 .otf 文件。' ||
contentToCopy.startsWith('正在读取并编码字体文件') ||
contentToCopy.startsWith('转换出错') ||
contentToCopy.startsWith('转换失败') ||
contentToCopy.includes('请选择字体文件')) {
alert('没有可复制的内容,请先选择一个字体文件并等待转换完成。');
return;
}
if (!contentToCopy.includes('data:') || !contentToCopy.includes('base64')) {
alert('当前文本不是有效的Base64字体数据,请重新转换字体文件。');
return;
}
try {
await navigator.clipboard.writeText(contentToCopy);
alert('复制成功\nBase64字符串已存入剪贴板,可直接在CSS或代码中使用。\n(字符串总长度: ' + contentToCopy.length + ' 字符)');
statusMsgDiv.innerHTML = '复制成功,已复制 ' + contentToCopy.length + ' 个字符到剪贴板。';
setTimeout(function() {
if (statusMsgDiv.innerHTML.indexOf('复制成功') !== -1) {
if (resultArea.value && resultArea.value.startsWith('data:')) {
statusMsgDiv.innerHTML = '转换结果已就绪,可继续复制或选择新字体。';
} else {
statusMsgDiv.innerHTML = '';
}
}
}, 2500);
} catch (err) {
console.error('复制失败:', err);
try {
resultArea.select();
resultArea.setSelectionRange(0, resultArea.value.length);
var success = document.execCommand('copy');
if (success) {
alert('复制成功(兼容模式)Base64字符串已存入剪贴板。');
statusMsgDiv.innerHTML = '复制成功已复制 ' + contentToCopy.length + ' 个字符。';
} else {
alert('复制失败,请手动选中文本域内容后按Ctrl+C复制。');
}
} catch (fallbackErr) {
alert('复制失败,请手动选中文本域中的内容后复制。\n错误详情: ' + fallbackErr.message);
}
}
});
resultArea.value = '等待选择字体文件...\n点击上方“选择文件”按钮,选取 .ttf 或 .otf 字体,转换后将在此处表示完整的Base64 DataURL。\n左侧【复制Base64结果】按钮可一键复制。';
resultMetaDiv.innerHTML = '';
fileInfoDiv.innerHTML = '';
statusMsgDiv.innerHTML = '选择字体文件后自动转换,结果会表示在下方文本区。';
})();
</script>
</body>
</html>
|
華奢
Email: kyasha@qq.com
网页使用HBuilderX编辑
很优秀的IDE
只有一个 .html文件