Holiday Tree
- Enter your full name in the text box and press Render Tree.
- Based on your name, a unique, force-directed graph will be generated. While the structure will always be the same, the position of the nodes may (slightly) differ every time.
- After render, you may make adjustments by dragging nodes around.
- Right-click on the tree and choose View as PNG.
- Right-click again and save your holiday tree.
Enjoy! Happy Holidays from ZingChart!
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ZingChart Demo: Xmas Tree</title> <script src="https://cdn.zingchart.com/zingchart.min.js"></script> <style> .zc-body { margin: 10px; padding: 10px; background: #fbfbfb; } .zc-info { margin-bottom: 10px; border-bottom: 1px solid #ccc; } .zc-info ol { margin: 0 0 22px; padding: 0 0 0 1rem; font-size: 14px; } .zc-info p { color: #dc1257; } .zc-controls { padding: 5px 0; } .zc-controls input { height: 40px; border: 1px solid #ebebeb; border-radius: 4px; box-sizing: border-box; font-size: 1rem; padding: 0 10px; } .zc-controls input:focus { font-size: 1rem; } .zc-controls button { color: #fff; background: #073c4e; border: 1px solid #ebebeb; border-radius: 4px; cursor: pointer; font-size: .8125rem; padding: 0 10px; height: 40px; } .zc-controls button[disabled] { cursor: not-allowed; } </style> </head> <body class="zc-body"> <div class="zc-info"> <ol> <li>Enter your full name in the text box and press <strong>Render Tree</strong>.</li> <li>Based on your name, a unique, force-directed graph will be generated. While the structure will always be the same, the position of the nodes may (slightly) differ every time.</li> <li>After render, you may make adjustments by dragging nodes around.</li> <li>Right-click on the tree and choose <strong>View as PNG</strong>.</li> <li>Right-click again and save your holiday tree.</li> </ol> <p>Enjoy! Happy Holidays from ZingChart!</p> </div> <div class="zc-controls"> <input type="text" id="renderInput" placeholder="Your full name here" value="world"> <button id="renderBtn">Render Tree</button> </div> <div id="myChart"></div> <script> ZC.LICENSE = ["569d52cefae586f634c54f86dc99e6a9", "b55b025e438fa8a98e32482b5f768ff5"]; // INIT // ----------------------------- // Define Module Location zingchart.MODULESDIR = "https://cdn.zingchart.com/modules/"; ZC.LICENSE = ["bab21d016b2dadc18447d2a055f061e3"]; // DEFINE CHART // ----------------------------- // Main chart render location var chartId = 'myChart'; // DOM ELEMENTS // ----------------------------- var renderBtn = document.querySelector('#renderBtn'); var renderInput = document.querySelector('#renderInput'); // RENDER BUTTON EVENTS // ----------------------------- renderBtn.addEventListener('click', renderChart); // HELPER FNS // ----------------------------- // Render Chart function renderChart() { // Disable render button renderBtn.setAttribute('disabled', 'disabled') // Define constants var W = '100%'; var H = 560; var COLORS = [ '#99ccff #336699', '#6CB359 #0F4800', '#9A5E9A #430443', '#FFA153 #AC4E00', '#FF653D #A62300', '#57B8C6 #095B67', '#FFE66D #AF930B', '#EF668F #9D0A36' ]; var SEQ = 0; var COLORSEQ = 0; var NAME = renderInput.value.trim() || 'Santa Claus'; var TICK = null; // Define data var CDATA = { type: 'tree', title: { color: '#333333', padding: 25, text: 'Hello ' + NAME + ', here\'s your holiday tree', fontSize: 17 }, images: [{ src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas0.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas1.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas2.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas3.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas4.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas5.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas6.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas7.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas8.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas9.png', visible: false } ], shapes: [], source: { fontSize: 12, margin: 'auto 25 25 25', text: 'Happy Holidays from ZingChart!' }, plotarea: { margin: '60 40 40 60' }, options: { aspect: 'graph', textAttr: 'id', minSize: 16, maxSize: 16, minLinkWidth: 1, maxLinkWidth: 1, springLength: 35, attractionConstant: 0.1, repulsionConstant: 400, repulsionDistanceFactor: 5, weightedNodes: 1, weightedLinks: 1, node: { backgroundRepeat: 'no-repeat', backgroundColor: 'none', backgroundPosition: '45% 45%', borderWidth: 0, fillType: 'radial', fillOffsetX: -5, fillOffsetY: -5, label: { visible: false }, tooltip: { visible: false } }, link: { lineColor: '#000000' } }, series: [] }; // Build layout var rows = Math.round(H / 20); var cols = Math.round(W / 20); var iCharCode; for (var row = 0; row < rows; row++) { iCharCode = NAME.charCodeAt(row % NAME.length); CDATA.shapes.push({ type: 'star5', flat: true, backgroundColor: COLORS[iCharCode % COLORS.length], size: 4 + iCharCode % 4, x: 10, y: 10 + row * 20 }, { type: 'star5', flat: true, backgroundColor: COLORS[iCharCode % COLORS.length], size: 4 + iCharCode % 4, x: W - 10, y: 10 + row * 20 }); } for (var col = 1; col < cols - 1; col++) { iCharCode = NAME.charCodeAt(col % NAME.length); CDATA.shapes.push({ type: 'star5', flat: true, backgroundColor: COLORS[iCharCode % COLORS.length], size: 4 + iCharCode % 4, x: 10 + col * 20, y: 10 }, { type: 'star5', flat: true, backgroundColor: COLORS[iCharCode % COLORS.length], size: 4 + iCharCode % 4, x: 10 + col * 20, y: H - 10 }); } // Render the chart zingchart.render({ id: chartId, width: W, height: H, output: 'canvas', data: CDATA, events: { load: function() { TICK = window.setInterval(fnStep, 150); } } }); function fnStep() { var i, sSource, sTarget, aPairs, oLink; var iCharCode = NAME.charCodeAt((SEQ + COLORSEQ) % NAME.length); var iColorCharCode = NAME.charCodeAt(COLORSEQ % NAME.length); // get data from graph var aData = zingchart.exec(chartId, 'tree.getdata') || []; // count links for each node var oNodesLinks = {}, aNodesIds = [], aLinksIds = []; for (i = 0; i < aData.length; i++) { if (aData[i].type === 'link') { oNodesLinks[aData[i].source] = ++oNodesLinks[aData[i].source] || 1; oNodesLinks[aData[i].target] = ++oNodesLinks[aData[i].target] || 1; aLinksIds.push(aData[i].source + '-' + aData[i].target); aLinksIds.push(aData[i].target + '-' + aData[i].source); } else if (aData[i].type === 'node') { aNodesIds.push(aData[i].id); } } // remove all nodes with no links if (aNodesIds.length > 2) { for (i = 0; i < aNodesIds.length; i++) { if (!oNodesLinks[aNodesIds[i]]) { zingchart.exec(chartId, 'tree.removenode', { id: aNodesIds[i] }); } } } // from time to time remove oldest leaves if (SEQ % 5 === 0 && aNodesIds.length > 5) { for (i = 0; i < aNodesIds.length; i++) { if (oNodesLinks[aNodesIds[i]] === 1) { zingchart.exec(chartId, 'tree.removenode', { id: aNodesIds[i] }); SEQ++; return; } } } // from time to time remove nodes with too many links if (SEQ % 13 === 0 && aNodesIds.length > 5) { for (i = 0; i < aNodesIds.length; i++) { if (oNodesLinks[aNodesIds[i]] > 3) { zingchart.exec(chartId, 'tree.removenode', { id: aNodesIds[i] }); SEQ++; return; } } } // from time to time just create a link between existing nodes if (SEQ % 7 === 0 && aNodesIds.length > 3) { aPairs = []; for (i = 0; i < aNodesIds.length; i++) { if (oNodesLinks[aNodesIds[i]] === 1) { aPairs.push(aNodesIds[i]); if (aPairs.length === 2) { oLink = { source: aPairs[0], target: aPairs[1], value: 1 + iCharCode % 2 }; zingchart.exec(chartId, 'tree.addlink', { data: oLink, update: true }); SEQ++; return; } } } } // otherwise, create a new node sTarget = 'n' + SEQ; oNode = { id: sTarget, text: sTarget, value: 1, style: { backgroundImage: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas' + (SEQ % 10) + '.png', backgroundColor: COLORS[iColorCharCode % COLORS.length] } }; COLORSEQ++; zingchart.exec(chartId, 'tree.addnode', { data: oNode, update: (aNodesIds.length === 0) }); if (aNodesIds.length > 0) { sSource = aNodesIds[iCharCode % aNodesIds.length]; oLink = { source: sSource, target: sTarget, value: 1 + iCharCode % 2 }; zingchart.exec(chartId, 'tree.addlink', { data: oLink, update: (aNodesIds.length > 0) }); } SEQ++; if (SEQ > 99) { window.clearInterval(TICK); renderBtn.removeAttribute('disabled'); } }; } window.addEventListener('load', function() { renderChart(); }); </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ZingChart Demo: Xmas Tree</title> <script src="https://cdn.zingchart.com/zingchart.min.js"></script> </head> <body class="zc-body"> <div class="zc-info"> <ol> <li>Enter your full name in the text box and press <strong>Render Tree</strong>.</li> <li>Based on your name, a unique, force-directed graph will be generated. While the structure will always be the same, the position of the nodes may (slightly) differ every time.</li> <li>After render, you may make adjustments by dragging nodes around.</li> <li>Right-click on the tree and choose <strong>View as PNG</strong>.</li> <li>Right-click again and save your holiday tree.</li> </ol> <p>Enjoy! Happy Holidays from ZingChart!</p> </div> <div class="zc-controls"> <input type="text" id="renderInput" placeholder="Your full name here" value="world"> <button id="renderBtn">Render Tree</button> </div> <div id="myChart"></div> </body> </html>
// INIT // ----------------------------- // Define Module Location zingchart.MODULESDIR = "https://cdn.zingchart.com/modules/"; ZC.LICENSE = ["bab21d016b2dadc18447d2a055f061e3"]; // DEFINE CHART // ----------------------------- // Main chart render location var chartId = 'myChart'; // DOM ELEMENTS // ----------------------------- var renderBtn = document.querySelector('#renderBtn'); var renderInput = document.querySelector('#renderInput'); // RENDER BUTTON EVENTS // ----------------------------- renderBtn.addEventListener('click', renderChart); // HELPER FNS // ----------------------------- // Render Chart function renderChart() { // Disable render button renderBtn.setAttribute('disabled', 'disabled') // Define constants var W = '100%'; var H = 560; var COLORS = [ '#99ccff #336699', '#6CB359 #0F4800', '#9A5E9A #430443', '#FFA153 #AC4E00', '#FF653D #A62300', '#57B8C6 #095B67', '#FFE66D #AF930B', '#EF668F #9D0A36' ]; var SEQ = 0; var COLORSEQ = 0; var NAME = renderInput.value.trim() || 'Santa Claus'; var TICK = null; // Define data var CDATA = { type: 'tree', title: { color: '#333333', padding: 25, text: 'Hello ' + NAME + ', here\'s your holiday tree', fontSize: 17 }, images: [ { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas0.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas1.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas2.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas3.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas4.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas5.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas6.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas7.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas8.png', visible: false }, { src: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas9.png', visible: false } ], shapes: [], source: { fontSize: 12, margin: 'auto 25 25 25', text: 'Happy Holidays from ZingChart!' }, plotarea: { margin: '60 40 40 60' }, options: { aspect: 'graph', textAttr: 'id', minSize: 16, maxSize: 16, minLinkWidth: 1, maxLinkWidth: 1, springLength: 35, attractionConstant: 0.1, repulsionConstant: 400, repulsionDistanceFactor: 5, weightedNodes: 1, weightedLinks: 1, node: { backgroundRepeat: 'no-repeat', backgroundColor: 'none', backgroundPosition: '45% 45%', borderWidth: 0, fillType: 'radial', fillOffsetX: -5, fillOffsetY: -5, label: { visible: false }, tooltip: { visible: false } }, link: { lineColor: '#000000' } }, series: [] }; // Build layout var rows = Math.round(H / 20); var cols = Math.round(W / 20); var iCharCode; for (var row=0;row<rows;row++) { iCharCode = NAME.charCodeAt(row%NAME.length); CDATA.shapes.push({ type: 'star5', flat: true, backgroundColor: COLORS[iCharCode%COLORS.length], size: 4 + iCharCode%4, x: 10, y: 10 + row * 20 }, { type: 'star5', flat: true, backgroundColor: COLORS[iCharCode%COLORS.length], size: 4 + iCharCode%4, x: W - 10, y: 10 + row * 20 }); } for (var col=1;col<cols-1;col++) { iCharCode = NAME.charCodeAt(col%NAME.length); CDATA.shapes.push({ type: 'star5', flat: true, backgroundColor: COLORS[iCharCode%COLORS.length], size: 4 + iCharCode%4, x: 10 + col * 20, y: 10 }, { type: 'star5', flat: true, backgroundColor: COLORS[iCharCode%COLORS.length], size: 4 + iCharCode%4, x: 10 + col * 20, y: H - 10 }); } // Render the chart zingchart.render({ id: chartId, width: W, height: H, output: 'canvas', data: CDATA, events: { load: function() { TICK = window.setInterval(fnStep, 150); } } }); function fnStep() { var i, sSource, sTarget, aPairs, oLink; var iCharCode = NAME.charCodeAt((SEQ+COLORSEQ)%NAME.length); var iColorCharCode = NAME.charCodeAt(COLORSEQ%NAME.length); // get data from graph var aData = zingchart.exec(chartId, 'tree.getdata') || []; // count links for each node var oNodesLinks = {}, aNodesIds = [], aLinksIds = []; for (i=0;i<aData.length;i++) { if (aData[i].type === 'link') { oNodesLinks[aData[i].source] = ++oNodesLinks[aData[i].source] || 1; oNodesLinks[aData[i].target] = ++oNodesLinks[aData[i].target] || 1; aLinksIds.push(aData[i].source + '-' + aData[i].target); aLinksIds.push(aData[i].target + '-' + aData[i].source); } else if (aData[i].type === 'node') { aNodesIds.push(aData[i].id); } } // remove all nodes with no links if (aNodesIds.length > 2) { for (i=0;i<aNodesIds.length;i++) { if (!oNodesLinks[aNodesIds[i]]) { zingchart.exec(chartId, 'tree.removenode', { id: aNodesIds[i] }); } } } // from time to time remove oldest leaves if (SEQ%5 === 0 && aNodesIds.length > 5) { for (i=0;i<aNodesIds.length;i++) { if (oNodesLinks[aNodesIds[i]] === 1) { zingchart.exec(chartId, 'tree.removenode', { id: aNodesIds[i] }); SEQ++; return; } } } // from time to time remove nodes with too many links if (SEQ%13 === 0 && aNodesIds.length > 5) { for (i=0;i<aNodesIds.length;i++) { if (oNodesLinks[aNodesIds[i]] > 3) { zingchart.exec(chartId, 'tree.removenode', { id: aNodesIds[i] }); SEQ++; return; } } } // from time to time just create a link between existing nodes if (SEQ%7 === 0 && aNodesIds.length > 3) { aPairs = []; for (i=0;i<aNodesIds.length;i++) { if (oNodesLinks[aNodesIds[i]] === 1) { aPairs.push(aNodesIds[i]); if (aPairs.length === 2) { oLink = { source: aPairs[0], target: aPairs[1], value: 1 + iCharCode%2 }; zingchart.exec(chartId, 'tree.addlink', { data: oLink, update: true }); SEQ++; return; } } } } // otherwise, create a new node sTarget = 'n' + SEQ; oNode = { id: sTarget, text: sTarget, value: 1, style: { backgroundImage: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/xmas' + (SEQ%10) + '.png', backgroundColor: COLORS[iColorCharCode%COLORS.length] } }; COLORSEQ++; zingchart.exec(chartId, 'tree.addnode', { data: oNode, update: (aNodesIds.length === 0) }); if (aNodesIds.length > 0) { sSource = aNodesIds[iCharCode%aNodesIds.length]; oLink = { source: sSource, target: sTarget, value: 1 + iCharCode%2 }; zingchart.exec(chartId, 'tree.addlink', { data: oLink, update: (aNodesIds.length > 0) }); } SEQ++; if (SEQ > 99) { window.clearInterval(TICK); renderBtn.removeAttribute('disabled'); } }; } window.addEventListener('load', function() { renderChart(); });
.zc-body { margin:10px; padding:10px; background: #fbfbfb; } .zc-info { margin-bottom: 10px; border-bottom: 1px solid #ccc; } .zc-info ol { margin: 0 0 22px; padding: 0 0 0 1rem; font-size: 14px; } .zc-info p { color: #dc1257; } .zc-controls { padding: 5px 0; } .zc-controls input { height: 40px; border: 1px solid #ebebeb; border-radius: 4px; box-sizing: border-box; font-size: 1rem; padding:0 10px; } .zc-controls input:focus { font-size: 1rem; } .zc-controls button { color: #fff; background: #073c4e; border: 1px solid #ebebeb; border-radius: 4px; cursor: pointer; font-size: .8125rem; padding:0 10px; height: 40px; } .zc-controls button[disabled] { cursor: not-allowed; }