mirror of
https://github.com/chanind/hanzi-writer-data.git
synced 2025-07-19 15:28:54 +08:00
130 lines
3.7 KiB
JavaScript
130 lines
3.7 KiB
JavaScript
var VERSION = "2.0";
|
|
var getCharDataUrl = char =>
|
|
`https://cdn.jsdelivr.net/npm/hanzi-writer-data@${VERSION}/${char}.json`;
|
|
|
|
function loadData(char, onLoad, onError) {
|
|
var xhr = new XMLHttpRequest();
|
|
if (xhr.overrideMimeType) {
|
|
xhr.overrideMimeType("application/json");
|
|
}
|
|
xhr.open("GET", getCharDataUrl(char), true);
|
|
xhr.onreadystatechange = () => {
|
|
if (xhr.readyState !== 4) return;
|
|
if (xhr.status === 200) {
|
|
onLoad(JSON.parse(xhr.responseText));
|
|
} else if (onError) {
|
|
onError(xhr);
|
|
}
|
|
};
|
|
xhr.send(null);
|
|
}
|
|
|
|
function attr(elm, name, value) {
|
|
elm.setAttributeNS(null, name, value);
|
|
}
|
|
|
|
function createElm(elmType) {
|
|
return document.createElementNS("http://www.w3.org/2000/svg", elmType);
|
|
}
|
|
|
|
function getPathString(points) {
|
|
const start = points[0];
|
|
const remainingPoints = points.slice(1);
|
|
let pathString = `M ${start[0]} ${start[1]}`;
|
|
remainingPoints.forEach(point => {
|
|
pathString += ` L ${point[0]} ${point[1]}`;
|
|
});
|
|
return pathString;
|
|
}
|
|
|
|
function renderCharacter(charData) {
|
|
var target = document.querySelector("#target");
|
|
document.body.classList.toggle("has-radical-data", !!charData.radStrokes);
|
|
target.innerHTML = "";
|
|
var svg = createElm("svg");
|
|
attr(svg, "width", "100%");
|
|
attr(svg, "height", "100%");
|
|
target.appendChild(svg);
|
|
var group = createElm("g");
|
|
attr(
|
|
group,
|
|
"transform",
|
|
"translate(0, 263.671875) scale(0.29296875, -0.29296875)"
|
|
);
|
|
svg.appendChild(group);
|
|
charData.strokes.forEach((stroke, i) => {
|
|
var isRadical = (charData.radStrokes || []).indexOf(i) > -1;
|
|
var path = createElm("path");
|
|
attr(path, "d", stroke);
|
|
path.classList.toggle("radical-stroke", isRadical);
|
|
group.appendChild(path);
|
|
});
|
|
charData.medians.forEach(median => {
|
|
var path = createElm("path");
|
|
attr(path, "d", getPathString(median));
|
|
path.classList.add("median-stroke");
|
|
group.appendChild(path);
|
|
});
|
|
}
|
|
|
|
function updateClasses() {
|
|
var target = document.querySelector("#target");
|
|
var transparent = document.querySelector("#transparent").checked;
|
|
var radical = document.querySelector("#radical").checked;
|
|
var medians = document.querySelector("#medians").checked;
|
|
target.classList.toggle("transparent-strokes", transparent);
|
|
target.classList.toggle("color-radical", radical);
|
|
target.classList.toggle("show-medians", medians);
|
|
}
|
|
|
|
document.querySelectorAll("input[type=checkbox]").forEach(function(node) {
|
|
node.addEventListener("change", updateClasses);
|
|
});
|
|
|
|
function renderLoadPath(char) {
|
|
var cdnTarget = document.querySelector("#cdn-path");
|
|
var url = getCharDataUrl(char);
|
|
cdnTarget.innerHTML = `<a href="${url}" target="blank">${url}</a>`;
|
|
|
|
var npmTarget = document.querySelector("#npm-path");
|
|
npmTarget.innerHTML = `var charData = require('hanzi-writer-data/${char}.json');`;
|
|
}
|
|
|
|
function loadAndRender() {
|
|
var char = document.querySelector("#char-input").value;
|
|
loadData(
|
|
char,
|
|
function(charData) {
|
|
renderCharacter(charData);
|
|
renderLoadPath(char);
|
|
window.location.hash = char.codePointAt(0);
|
|
},
|
|
function(err) {
|
|
console.error(err);
|
|
alert(`Unable to load data for ${char}`);
|
|
}
|
|
);
|
|
}
|
|
|
|
function setCharFromHash(defaultChar) {
|
|
var hashChar = defaultChar;
|
|
if (window.location.hash) {
|
|
var codePoint = parseInt(window.location.hash.slice(1));
|
|
if (!isNaN(codePoint)) {
|
|
hashChar = String.fromCodePoint(codePoint);
|
|
}
|
|
}
|
|
if (hashChar) {
|
|
document.querySelector("#char-input").value = hashChar;
|
|
}
|
|
}
|
|
|
|
setCharFromHash("我");
|
|
window.addEventListener("hashchange", function() {
|
|
setCharFromHash(null);
|
|
loadAndRender();
|
|
});
|
|
document.querySelector("#update-char").addEventListener("click", loadAndRender);
|
|
updateClasses();
|
|
loadAndRender();
|