{ name: 'day', value: 24 * 60 * 60, children: [ { name: 'work', value: 9 * 60 * 60, children: [ { name: 'coding', value: 6 * 60 * 60, children: [ {name: 'python', value: 4 * 60 * 60}, {name: 'js', value: 2 * 60 * 60} ] }, {name: 'communicate', value: 1.5 * 60 * 60} ] }, {name: 'sleep', value: 7 * 60 * 60}, ... };
function maxDeep(data) { var deeps = []; for (var i = 0, l = (data.children || []).length; i < l; i++) { deeps.push(maxDeep(data.children[i])); } return 1 + Math.max.apply(Math, deeps.length ? deeps : [0]); };
x + x / 1.62 + x / (1.62^2) + ... + x / (1,62^(n-1)) = min(canvas.width, canvas.height)
function rootNodeWidth(n, canvasWidth, canvasHeight) { var canvasSize = Math.min(canvasWidth, canvasHeight), div = 1; for (var i = 1; i < n; i++) { div += 1 / Math.pow(1.62, i); } return canvasSize / 2 / div; // 2 , . };
function calcMetaData(dataRootNode, rootNodeWidth) { var startWidth = rootNodeWidth, meta = { root: { data: dataRootNode, color: pickColor(), angles: {begin: 0, end: 2 * Math.PI, abs: 2 * Math.PI}, // - width: startWidth, offset: 0, children: [], scale: 1 } }, sibling; function calcChildMetaData(childDatum, parentMeta, sibling, scale) { var meta = { data: childDatum, color: pickColor(), parent: parentMeta, width: parentMeta.width / scale, offset: parentMeta.offset + parentMeta.width, children: [], scale: parentMeta.scale / scale }, childSibling; meta.angles = {abs: parentMeta.angles.abs * childDatum.value / parentMeta.data.value}; meta.angles.begin = sibling ? sibling.angles.end : parentMeta.angles.begin; meta.angles.end = meta.angles.begin + meta.angles.abs; for (var i = 0, l = (childDatum.children || []).length; i < l; i++) { childSibling = calcChildMetaData(childDatum.children[i], meta, childSibling, scale); meta.children.push(childSibling); } return meta; } for (var i = 0, l = (dataRootNode.children || []).length; i < l; i++) { if (dataRootNode.children[i].value > dataRootNode.value) { console.error('Child value greater than parent value.', dataRootNode.children[i], dataRootNode); continue; } sibling = calcChildMetaData(dataRootNode.children[i], meta.root, sibling, 1.62); meta.root.children.push(sibling); } return meta; };
var nodeMeta = {width: 20px, color: 'green', angles: {begin: 0, end: 2 * Math.PI}}; // var origin = {x: 250, y: 250}; // var ctx = canvas.getContext('2d'); function drawRootNodeBody(nodeMeta, origin, ctx) { ctx.beginPath(); ctx.arc(origin.x, origin.y, nodeMeta.width, nodeMeta.angles.begin, nodeMeta.angles.end); // ctx.fillStyle = nodeMeta.color; // - ctx.fill(); ctx.strokeStyle = 'white'; // - ctx.stroke(); }
function drawChildNodeBody(nodeMeta, origin, ctx) { ctx.beginPath(); ctx.arc(origin.x, origin.y, nodeMeta.offset, nodeMeta.angles.begin, nodeMeta.angles.end); // // ctx.save(); ctx.translate(origin.x, origin.y); // ctx.rotate(nodeMeta.angles.end); // , // ctx.lineTo(nodeMeta.offset + nodeMeta.width, 0); ctx.restore(); // // ctx.arc(origin.x, origin.y, nodeMeta.offset + nodeMeta.width, nodeMeta.angles.end, nodeMeta.angles.begin, true); // - . ctx.closePath(); ctx.fillStyle = nodeMeta.hover ? 'red' : nodeMeta.color; ctx.fill(); ctx.strokeStyle = 'white'; ctx.stroke(); }
function cartesianCoordsToPolarCoords(point, origin) { var difX = point.x - origin.x, difY = point.y - origin.y, distance = Math.sqrt(difX * difX + difY * difY), angle = Math.acos(difX / distance); if (difY < 0) { angle = 2 * Math.PI - angle; } return {dist: distance, angle: angle}; };
function getNodeByPolarCoords(point, origin, metaData) { function _findNode(point, nodeMeta) { // if (nodeMeta.offset >= point.dist) { // , distance, // , . return null; } if (nodeMeta.offset < point.dist && point.dist <= nodeMeta.offset + nodeMeta.width) { // , . if (nodeMeta.angles.begin < point.angle && point.angle <= nodeMeta.angles.end) { return nodeMeta; } } else { // We need to go deeper. . var node; for (var i = 0, l = (nodeMeta.children || []).length; i < l; i++) { if (node = _findNode(point, nodeMeta.children[i])) { return node; } } } return null; } return _findNode(point, metaData.root); };
Source: https://habr.com/ru/post/246909/
All Articles