tomgp
2/20/2016 - 9:08 PM

icon array scale interactive example

icon array scale interactive example

Icon array scale example

A simple example of using the layout and scale functions of my d3 icon array plugin.

This gist is to illustrate the gapInterval and gapSize properties.

<!DOCTYPE html>
<html>
<head>
	<title>Icon array scaletest</title>
	<script src="//d3js.org/d3.v4.0.0-alpha.18.min.js" charset="utf-8"></script>
	<script type="text/javascript" src="d3-iconarray.js"></script>
	<style type="text/css">
	*{
		font-family: sans-serif;
		font-weight: bold;
		letter-spacing: 1px;
	}

	input[type='range']{
		width:600px;
	}

	p{
		font-weight: normal;
	}
	.arg{
		color: #B00;
		font-weight: bold;
	}

	</style>
</head>
<body>

<p>gapInterval(<span class="arg" id="interval-value">4</span>):</p> <input value="4" id="interval-input" type="range" min="0" max="12" step="1"></input>

<p>gapSize(<span class="arg" id="size-value">1</span>):</p><input value="1" id="size-input" type="range" min="0" max="3" step="0.1"></input>


<div id="simple-example">
	
</div>
</body>
<script type="text/javascript">
	
var layout = d3_iconarray.layout();

var data = d3.range(1, 145, 1);

var grid = layout(data);
var dotRadius = 10;
var width = 600, 
	height = 600, 
	margin = {top:20, bottom:20, left:20, right:20 };

var arrayScale = d3_iconarray.scale()
	.domain([ 0, layout.maxDimension(data.length) ])
	.range([0, width-(margin.left+margin.right)])
	.gapSize(1)
	.gapInterval(4);

var svg = d3.select('#simple-example')
		.append('svg')
			.attr('width',width)
			.attr('height',height)
		.append('g')
			.attr('transform','translate('+margin.left+','+margin.top+')');

svg.selectAll('g')
	.data(grid)
		.enter()
	.append('g').attr('transform', function(d){ 
		return 'translate('+arrayScale(d.position.x)+','+arrayScale(d.position.y)+')' 
	})
	.call(function(parent){
		parent.append('text')
			.text(function(d){ return d.data; })
			.attr('stroke','#000')
			.attr('stroke-width',8)
			.attr('stroke-linejoin','round')
			.attr('text-anchor','middle')
			.attr('x',dotRadius)
			.attr('y',dotRadius*6/4)

		parent.append('text')
			.text(function(d){ return d.data; })
			.attr('fill','#FFF')
			.attr('text-anchor','middle')		
			.attr('y',dotRadius*6/4)
			.attr('x',dotRadius)	
	});

d3.selectAll('input#interval-input, input#size-input').on('change',function(){
	console.log('hiya');

	var interval = document.getElementById('interval-input').value;
	var size = document.getElementById('size-input').value;

	d3.select('#interval-value').text(interval);
	d3.select('#size-value').text(size);

	arrayScale.gapSize(size)
		.gapInterval(interval);

	svg.selectAll('g')
		.transition()
		.attr('transform', function(d){ 
			return 'translate('+arrayScale(d.position.x)+','+arrayScale(d.position.y)+')' 
		})
})

d3.select(self.frameElement).style("height", (height + 200)+"px");

</script>
</html>
(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-scale')) :
	typeof define === 'function' && define.amd ? define(['exports', 'd3-scale'], factory) :
	(factory((global.d3_iconarray = global.d3_iconarray || {}),global.d3));
}(this, function (exports,d3) { 'use strict';

	function iconArrayLayout() {
		var width = undefined;
		var height = undefined;
		var widthFirst = true;
		var maxDimension = undefined;

		function layout(data){
			//work our missing height, width stuff

			setDimensions(data.length);

			return data.map(function(d,i){
				return {
					data:d,
					position:position(i)
				};
			});
		}

		function position(i){
			if(isNaN(width) || isNaN(height)){ 
				console.log('Warning: width/height undefined') 
				return 0;
			}
			if(widthFirst){
				return {
					x: i % width,
					y: Math.floor( i/width )
				};
			}else{
				return {
					x: Math.floor( i/height ),
					y: i % height
				};
			}
		}

		function setDimensions(l){
			//neither width or height is defined
			if(isNaN(width) && isNaN(height)){
				console.log('no width or height');
				if(widthFirst){ 
					width = Math.ceil( Math.sqrt(l) );
					height = Math.ceil( l / width );
				}else{
					height = Math.ceil( Math.sqrt(l) );
					width = Math.ceil( l / height );
				}
			}else if(isNaN(width)){	//width undefined
				width = Math.ceil( l / height );
			}else if(isNaN(height)){ //height undefined
				height = Math.ceil( l / width );
			}
		}

		layout.maxDimension = function(x){
			var itemPosition = position(x); 
			if(widthFirst){
				var x = Math.max(itemPosition.x, width);
				return Math.max(x, itemPosition.y);
			}
			var y = Math.max(itemPosition.y, height);
			return Math.max(y, itemPosition.x);

		}

		layout.position = function(x){
			return position(x);
		}

		layout.width = function(x){
			if(x === undefined) return width;
			width = x;
			return layout;
		};

		layout.height = function(x){
			if(x === undefined) return height;
			height = x;
			return layout;
		};

		layout.widthFirst = function(b){
			if(b === undefined) return widthFirst;
			widthFirst = b;
			return layout;
		};

		return layout;
	};

	function iconArrayScale(){

		var domain = [0,100];
		var range = [0,100];
		var gapInterval = 10;
		var gapSize = 0; //default no change
		var notionalScale = d3.scaleLinear()
								.domain(domain)
								.range(range);

		function scale(domainValue){
			var rangeValue = 20;
			var adjustedDomainValue = domainValue + Math.floor(domainValue/gapInterval)*gapSize;
			//console.log(notionalScale.domain());
			return rangeValue = notionalScale(adjustedDomainValue);		
		}

		function rescale(){
			//calculate an adjusted domain
			var domainLength = (domain[1] - domain[0]) * gapSize;
			var gaps = Math.ceil( domainLength/ gapInterval );
			var adjustedDomain = [ domain[0], domain[1] + gaps ];

			//calculate an adjusted range

			notionalScale.domain(adjustedDomain)
					.range(range);
		}

		scale.gapInterval = function(x){
			if(!x) return gapInterval;
			gapInterval = x;
			rescale();
			return scale;
		};

		scale.gapSize = function(x){
			if(isNaN(x)) return gapSize;
			gapSize = x;
			rescale();
			return scale;
		}

		scale.domain = function(array){
			if(!array) return domain;
			domain = array;
			rescale();
			return scale;
		};

		scale.range = function(array){
			if(!array) return range;
			range = array;
			rescale();
			return scale;
		};

		rescale();
		return scale; 
	}

	var version = "0.0.1";

	exports.version = version;
	exports.layout = iconArrayLayout;
	exports.scale = iconArrayScale;

}));