Skip to content

Instantly share code, notes, and snippets.

@icodesido
Created December 20, 2018 13:46
Show Gist options
  • Save icodesido/b6e53ebf6da57a1946a970046d4753a2 to your computer and use it in GitHub Desktop.
Save icodesido/b6e53ebf6da57a1946a970046d4753a2 to your computer and use it in GitHub Desktop.
Dynamic Infographic

Dynamic Infographic

This example shows how a dynamic infographic can be realized with archer.

A Pen by Archer on CodePen.

License.

<html>
<head>
<title>Dynamic Infographic</title>
<link rel="stylesheet" href="app.css">
<link rel="stylesheet" href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/691867/control-panel.css">
</head>
<body>
<div id="container"></div>
<div id="error">
<h1>The graphic files could not be loaded</h1>
</div>
<!-- Include the runtime library -->
<!-- NOTE: The Archer Runtime library is free for personal, non-commercial use and testing environments. -->
<!-- For using the Archer Runtime library in production environments please visit https://archer.graphics to learn more about commercial licensing options. -->
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/691867/archer.min.js'></script>
<script language='javascript' type='text/javascript'>
/*
* NOTE: This example may only work when it is loaded through a web server. The example code needs to load the archer
* graphic file as well as the archer configuration file, which for security reasons is not allowed when loading the
* HTML file from the file system.
*/
/**
* Root location where your interactive graphic is stored.
* Leave empty to resolve paths relative from this HTML.
* Can also contain an absolute URL to the server where your graphic is stored, for example:
* http://my-domain.com/graphics/my-graphic/
*/
var rootUrl = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/691867/';
/**
* Location of the assets folder, by default resolved relative from root URL
*/
var assetUrl = rootUrl;
/**
* Location of the SVG file, by default resolved relative from root URL
*/
var graphicUrl = rootUrl + 'ring-chart.archer.graphic.svg';
/**
* Location of the graphic configuration file, by default resolved relative from root URL
*/
var configUrl = rootUrl + 'ring-chart.archer.config.json';
/**
* The container HTML element in which to display the graphic
*/
var container = document.getElementById('container');
// Create a graphic instance over the container
var graphic = archer.create(container);
// Tell the graphic where assets (e.g. images) are located
graphic.document.setAssetRoot(assetUrl);
// Load graphic and configuration
graphic.loadUrl(graphicUrl, configUrl);
// Wait until files are loaded
graphic.on('ready', function () {
// Make graphic fit into container bounds
graphic.view.zoomToFit();
// Enable zoom / pan with mouse
graphic.view.enableMouse(true, true);
// Set variable values
App.init();
// Add event listeners
});
// Files could not be loaded, maybe due to security restrictions
// Display error message
graphic.on('error', function () {
document.getElementById('error').style['display'] = 'block';
})
</script>
<div id="control-panel">
<section>
<h1>Category 1</h1>
<div class="row">
<div>
<label for="label-0">Text</label>
<input id="label-0" type="text" value="Well running projects"/>
</div>
<div>
<label for="color-0">Color</label>
<input id="color-0" type="text" value="#ff0000"/>
</div>
</div>
<div>
<label for="value-0">Value</label>
<input id="value-0" type="range" min="0" max="100"/>
</div>
</section>
<section>
<h1>Category 2</h1>
<div class="row">
<div>
<label for="label-1">Text</label>
<input id="label-1" type="text" value="Normal projects"/>
</div>
<div>
<label for="color-1">Color</label>
<input id="color-1" type="text" value="#ff0000"/>
</div>
</div>
<div>
<label for="value-1">Value</label>
<input id="value-1" type="range" min="0" max="100"/>
</div>
</section>
<section>
<h1>Category 3</h1>
<div class="row">
<div>
<label for="label-2">Text</label>
<input id="label-2" type="text" value="Critical projects"/>
</div>
<div>
<label for="color-2">Color</label>
<input id="color-2" type="text" value="#ff0000"/>
</div>
</div>
<div>
<label for="value-2">Value</label>
<input id="value-2" type="range" min="0" max="100"/>
</div>
</section>
<section>
<h1></h1>
<div class="row">
<input id="keep-positions" type="checkbox" value="false"/>
<label for="keep-positions">Keep positions</label>
</div>
</section>
</div>
<a href="https://archer.graphics" target="_" title="Powered by Archer" style="display: block; position: absolute; right: 0px; bottom: 0px; width: 60px; height: 60px; background-image: url(&quot;data:image/svg+xml;charset=utf8,%3C?xml version='1.0' encoding='utf-8'?%3E %3C!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E %3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='120px' height='120px' viewBox='0 0 120 120' style='enable-background:new 0 0 120 120;' xml:space='preserve'%3E %3Cstyle type='text/css'%3E .st0%7Bfill:%231AC1E3;%7D .st1%7Bclip-path:url(%23SVGID_2_);%7D .st2%7Bfill:%231AC1E3;stroke:%231AC1E3;stroke-miterlimit:10;%7D %3C/style%3E %3Cdefs%3E %3Cfilter id='black-glow'%3E %3CfeColorMatrix type='matrix' values= '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0'/%3E %3CfeGaussianBlur stdDeviation='5' result='coloredBlur'/%3E %3CfeMerge%3E %3CfeMergeNode in='coloredBlur'/%3E %3CfeMergeNode in='SourceGraphic'/%3E %3C/feMerge%3E %3C/filter%3E %3C/defs%3E %3Cg%3E %3Cg%3E %3Ccircle cx='60' cy='60' r='40' filter='url(%23black-glow)' /%3E %3C/g%3E %3C/g%3E %3Cg%3E %3Cpath class='st0' d='M65.7,63.4L65.7,63.4c-0.6,0.7-1.1,1-1.9,1c-1.1,0-1.8-0.6-1.8-1.7c0-2,2.2-2.1,3.6-2.1h0.6 c0.1-0.2,0.1-0.3,0.1-0.5c0-0.6-0.6-0.7-1.1-0.7c-0.7,0-1.4,0.2-2,0.5l0.2-1.2c0.7-0.2,1.3-0.3,2.1-0.3c1.1,0,2.3,0.4,2.3,1.8 c0,0.8-0.6,3.1-0.7,4.2h-1.3L65.7,63.4z M64.2,63.3c1.1,0,1.5-0.8,1.8-1.8h-0.6c-0.7,0-2,0.2-2,1.1C63.4,63,63.8,63.3,64.2,63.3z' /%3E %3Cpath class='st0' d='M69.4,59.2c0.1-0.2,0.1-0.6,0.2-0.8H71l-0.2,1.1l0,0c0.2-0.6,1-1.2,1.8-1.2c0.2,0,0.4,0,0.6,0.1l-0.4,1.4 c-0.2-0.1-0.4-0.1-0.6-0.1c-1.1,0-1.6,1-1.8,1.9l-0.6,2.6h-1.6L69.4,59.2z'/%3E %3Cpath class='st0' d='M77.7,59.7c-0.2-0.2-0.7-0.2-1.1-0.2c-1.2,0-1.9,1.1-1.9,2.2c0,0.7,0.2,1.6,1.3,1.6c0.4,0,0.8-0.2,1.2-0.2 L77,64.2c-0.5,0.2-1,0.2-1.5,0.2c-1.5,0-2.5-1-2.5-2.6c0-2.1,1.4-3.7,3.4-3.7c0.6,0,1.1,0.2,1.6,0.2L77.7,59.7z'/%3E %3Cpath class='st0' d='M79.7,55.6h1.6l-0.7,3.3l0,0c0.4-0.4,1-0.7,1.7-0.7c1.1,0,1.9,0.7,1.9,1.9c0,0.5-0.2,1-0.2,1.3l-0.6,2.9h-1.6 l0.6-2.8c0.1-0.4,0.2-0.8,0.2-1.2c0-0.5-0.3-0.8-0.8-0.8c-1.1,0-1.4,1-1.6,1.9l-0.6,3H78L79.7,55.6z'/%3E %3Cpath class='st0' d='M86.5,61.8c0,1.1,0.6,1.5,1.6,1.5c0.6,0,1.2-0.2,1.8-0.4l-0.2,1.2c-0.6,0.2-1.2,0.3-1.9,0.3 c-1.7,0-2.9-0.8-2.9-2.6s1.4-3.6,3.4-3.6c1.4,0,2.5,0.7,2.5,2.2c0,0.5-0.1,0.9-0.2,1.3C90.6,61.8,86.5,61.8,86.5,61.8z M89.3,60.7 c0-0.2,0.1-0.2,0.1-0.4c0-0.6-0.3-1-1-1c-1,0-1.4,0.6-1.6,1.4H89.3L89.3,60.7z'/%3E %3Cpath class='st0' d='M92.3,59.2c0.1-0.2,0.1-0.6,0.2-0.8H94l-0.2,1.1l0,0c0.2-0.6,1-1.2,1.8-1.2c0.2,0,0.4,0,0.6,0.1l-0.3,1.5 c-0.2-0.1-0.4-0.1-0.6-0.1c-1.1,0-1.6,1-1.8,1.9l-0.6,2.6h-1.6L92.3,59.2z'/%3E %3C/g%3E %3Cg%3E %3Cg%3E %3Cg%3E %3Cdefs%3E %3Ccircle id='SVGID_1_' cx='60' cy='60' r='40'/%3E %3C/defs%3E %3CclipPath id='SVGID_2_'%3E %3Cuse xlink:href='%23SVGID_1_' style='overflow:visible;'/%3E %3C/clipPath%3E %3Cg class='st1'%3E %3Cpath class='st2' d='M53,48.6'/%3E %3Cg%3E %3Cpath class='st2' d='M59,75.4L59,75.4L59,75.4z'/%3E %3Cpath class='st2' d='M117.4,34l-2.2-5.4c0,0-36.4,9.9-59.9,17.5l0,0c-1.4-8-3.2-13.9-5.1-14.3c-6.4-1-12.6,11.4-16.9,22.2 c-2.1,1-3.4,1.7-4.1,2.3c-1,1.1-0.5,3.3,1,6c-1.4,4.2-2.2,7-2.2,7s2.6-7.2,6-15l0,0c4.2-1.7,11.1-3.7,19-5.8 c2.3,8,4.7,18.6,6,26.9c-0.7-8.3-1.9-18.8-3.4-27.4C79.2,41.8,117.4,34,117.4,34z M30.2,62.3c-1.2-2.5-1.5-4.5-0.6-5.5 c0.5-0.5,1.6-1.2,3.2-1.8C31.8,57.6,31,60.1,30.2,62.3L30.2,62.3z M34.6,53.4c4.5-9.9,10.2-20.3,13.6-17 c1.2,1.1,2.8,5.1,4.4,10.6C45.2,49.4,38.8,51.6,34.6,53.4z'/%3E %3C/g%3E %3Cpath class='st2' d='M30.6,62.9c5,9.5,20.9,25.5,26.6,25.5l0,0C50.9,85.5,35.8,71.6,30.6,62.9L30.6,62.9z'/%3E %3Cpath class='st2' d='M59,75.4c0.8,5.4,1.4,9.6,1.5,12.3c0.1,1.4-1.6,1.4-3.4,0.6l0,0c1.1,0,2.5-0.6,2.6-2.2 C59.9,83.7,59.2,80,59,75.4'/%3E %3C/g%3E %3C/g%3E %3C/g%3E %3C/g%3E %3C/svg%3E&quot;); background-size: contain;"></a>
</body>
</html>
var App = {
barNames: ['front', 'right', 'left'],
keepPositions: false,
bars: [{
color: '#ff5353',
text: 'Dead horse projects',
value: 23
}, {
color: '#ffde00',
text: 'Difficult projects',
value: 32
}, {
color: '#53de53',
text: 'Well-running projects',
value: 45
}],
init: function () {
this.keepPositionsEl = document.getElementById('keep-positions');
this.keepPositionsEl.onchange = function (evt) {
this.keepPositions = !this.keepPositions;
valueChanged();
}.bind(this);
var labelChanged = function (inputIndex) {
this.bars[inputIndex].text = this.bars[inputIndex].labelEl.value;
graphic.setValue(this.barNames[inputIndex] + '-label-details', this.bars[inputIndex].text);
valueChanged();
}.bind(this);
var colorChanged = function (inputIndex) {
this.bars[inputIndex].color = this.bars[inputIndex].colorEl.value;
graphic.setValue(this.barNames[inputIndex] + '-color', this.bars[inputIndex].color);
valueChanged();
}.bind(this);
var valueChanged = function () {
var total = 0;
var highest = 0;
for (var barIndex = 0; barIndex < this.bars.length; barIndex++) {
var barValue = parseFloat(this.bars[barIndex].valueEl.value);
total += barValue;
if (barValue > highest) highest = barValue;
}
var highestRatio = highest / total;
for (var barIndex = 0; barIndex < this.bars.length; barIndex++) {
var bar = this.bars[barIndex];
bar.ratio = parseFloat(bar.valueEl.value) / total;
bar.height = 100 * bar.ratio / highestRatio;
}
var sortArray = this.bars.slice();
if (!this.keepPositions) {
sortArray.sort(function (a, b) {
return a.height - b.height;
});
}
for (var barIndex = 0; barIndex < sortArray.length; barIndex++) {
var bar = sortArray[barIndex];
graphic.setValue(this.barNames[barIndex] + '-value', bar.height);
graphic.setValue(this.barNames[barIndex] + '-color', bar.color);
graphic.setValue(this.barNames[barIndex] + '-label', Math.round(bar.ratio * 1000) / 10 + '%');
graphic.setValue(this.barNames[barIndex] + '-label-details', bar.text);
}
}.bind(this);
for (var i = 0; i < this.bars.length; i++) {
var bar = this.bars[i];
bar.valueEl = document.getElementById('value-' + i);
bar.labelEl = document.getElementById('label-' + i);
bar.colorEl = document.getElementById('color-' + i);
bar.valueEl.value = bar.value;
bar.colorEl.value = bar.color;
bar.labelEl.value = bar.text;
bar.labelEl.onkeyup = function (evt) {
var id = evt.currentTarget.id;
labelChanged(parseInt(id.substring(id.indexOf('-') + 1, id.length)));
};
bar.valueEl.oninput = function (evt) {
var id = evt.currentTarget.id;
valueChanged();
};
bar.colorEl.oninput = function (evt) {
var id = evt.currentTarget.id;
colorChanged(id.substring(id.indexOf('-') + 1, id.length));
};
}
valueChanged();
}
};
body {
font-family: arial;
font-size: 9pt;
background-color: #0071bc;
}
#container {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
}
#error {
display: none;
}
#color-0, #color-1, #color-2 {
width: 50pt;
}
#label-0, #label-1, #label-2 {
width: 100pt;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment