Skip to content

Instantly share code, notes, and snippets.

@N0taN3rd
Last active March 16, 2016 01:40
Show Gist options
  • Save N0taN3rd/f1ba6bef2fc906b87dbf to your computer and use it in GitHub Desktop.
Save N0taN3rd/f1ba6bef2fc906b87dbf to your computer and use it in GitHub Desktop.
Visualization Implementation (VI7)

John Berlin CS725 Information Visualization

Visualization Implementation (VI7)

View on blocks

Matrix View

In constructing the matrix view I borrowed heavily from the Les Miserables example seen here.

The default ordering is set to be by name and will change its self periodically to be ordered by frequency and then back again.

The by name ordering of the matrix provides information if you are like myself and do not remember information about the states off hand.

When ordered by frequency it gets more interesting. Tennessee pops straight to the top along with Montana and Kentucky. Through this you can infer that states that are long either the east or west cost ie coastal states do not have many neighboring states as those that are land locked.

Node Link

The node link diagram is rather boring as it is a simple representation of the Contiguous States. What is more interesting about it is that the states can be reduced to a small graph showing how relatively small the USA is to other countries. Also in this graph you can see the states that are coastal as they are on the outermost edges of the graph. But besides that there is little to be gained from this.

As you mouse over each node the name of the state is displayed for you.

Data

To generate the json file used in for this vis I used the following snippet of python code. What is not included is the shortest path lengths as it proved to produce a very large file wich blocks did not like. So I simply removed that part and ran the script normally.

import json
from collections import defaultdict
import networkx as nx


def stripper(s):
    s = s.rstrip("\n")
    split = s.split(" ")
    return split[0], split[1]


class Node:
    def __init__(self, name, numedges):
        self.name = name
        self.numedges = numedges

    def to_jdic(self):
        out = {'name': self.name, 'nedges': self.numedges, 'group': 0}
        return out

    def __str__(self):
        return self.name


class Edge:
    def __init__(self, source, target):
        self.source = source
        self.target = target

    def to_jdic(self):
        out = {'source': self.source, 'target': self.target, 'value': 1}
        return out


class shortPlen:
    def __init__(self, to, length):
        self.to = to
        self.length = length

    def to_jdic(self):
        out = {'to': self.to, 'length': self.length}
        return out

    def __str__(self):
        return "%s of length %d" % (self.to, self.length)


if __name__ == "__main__":

    print("hi")
    edgeList = defaultdict(list)

    nlist = []
    nnlist = []
    edgel = []

    with open('contiguous-usa.dat', "r") as o:
        for pairs in map(lambda x: stripper(x), o):
            edgeList[pairs[0]].append(pairs[1])

    graph = nx.Graph()
    graph.edges()
    for node in edgeList.keys():
        nnlist.append(node)
        graph.add_node(node)

    for node, edges in edgeList.items():
        for edge in edges:
            graph.add_edge(node, edge)
            if edge not in nnlist:
                nnlist.append(edge)

    alppathslen = nx.all_pairs_shortest_path_length(graph)

    for n in graph.nodes():
        spl = alppathslen[n]  # type: dict
        spl.pop(n)
        spl = list(map(lambda x: shortPlen(x[0], x[1]), spl.items()))

        nn = Node(n, len(graph.edges(n)))
        nlist.append(nn)

    nlist = sorted(nlist, key=lambda x: x.name)
    nnlist = sorted(nnlist)
    for n, e in graph.edges():
        edgel.append(Edge(nnlist.index(n), nnlist.index(e)))

    g = {}

    g['nodes'] = nlist
    g['links'] = edgel
    with open("contiguous-usa.json", "w+") as out:
        out.write(json.dumps(g, default=lambda c: c.to_jdic(), sort_keys=True, indent=1))
{
"links": [
{
"source": 22,
"target": 27,
"value": 1
},
{
"source": 22,
"target": 15,
"value": 1
},
{
"source": 22,
"target": 10,
"value": 1
},
{
"source": 22,
"target": 40,
"value": 1
},
{
"source": 22,
"target": 12,
"value": 1
},
{
"source": 22,
"target": 1,
"value": 1
},
{
"source": 22,
"target": 34,
"value": 1
},
{
"source": 22,
"target": 14,
"value": 1
},
{
"source": 8,
"target": 9,
"value": 1
},
{
"source": 8,
"target": 0,
"value": 1
},
{
"source": 26,
"target": 24,
"value": 1
},
{
"source": 26,
"target": 39,
"value": 1
},
{
"source": 26,
"target": 21,
"value": 1
},
{
"source": 9,
"target": 38,
"value": 1
},
{
"source": 9,
"target": 0,
"value": 1
},
{
"source": 9,
"target": 25,
"value": 1
},
{
"source": 9,
"target": 40,
"value": 1
},
{
"source": 44,
"target": 17,
"value": 1
},
{
"source": 44,
"target": 32,
"value": 1
},
{
"source": 44,
"target": 28,
"value": 1
},
{
"source": 48,
"target": 24,
"value": 1
},
{
"source": 48,
"target": 27,
"value": 1
},
{
"source": 48,
"target": 39,
"value": 1
},
{
"source": 48,
"target": 11,
"value": 1
},
{
"source": 48,
"target": 4,
"value": 1
},
{
"source": 48,
"target": 42,
"value": 1
},
{
"source": 34,
"target": 4,
"value": 1
},
{
"source": 34,
"target": 41,
"value": 1
},
{
"source": 34,
"target": 1,
"value": 1
},
{
"source": 34,
"target": 30,
"value": 1
},
{
"source": 34,
"target": 14,
"value": 1
},
{
"source": 5,
"target": 37,
"value": 1
},
{
"source": 5,
"target": 17,
"value": 1
},
{
"source": 5,
"target": 32,
"value": 1
},
{
"source": 47,
"target": 33,
"value": 1
},
{
"source": 47,
"target": 15,
"value": 1
},
{
"source": 47,
"target": 43,
"value": 1
},
{
"source": 47,
"target": 36,
"value": 1
},
{
"source": 47,
"target": 18,
"value": 1
},
{
"source": 28,
"target": 19,
"value": 1
},
{
"source": 28,
"target": 17,
"value": 1
},
{
"source": 46,
"target": 21,
"value": 1
},
{
"source": 46,
"target": 20,
"value": 1
},
{
"source": 46,
"target": 10,
"value": 1
},
{
"source": 46,
"target": 12,
"value": 1
},
{
"source": 35,
"target": 3,
"value": 1
},
{
"source": 35,
"target": 31,
"value": 1
},
{
"source": 35,
"target": 11,
"value": 1
},
{
"source": 35,
"target": 45,
"value": 1
},
{
"source": 45,
"target": 11,
"value": 1
},
{
"source": 10,
"target": 27,
"value": 1
},
{
"source": 10,
"target": 39,
"value": 1
},
{
"source": 10,
"target": 12,
"value": 1
},
{
"source": 10,
"target": 21,
"value": 1
},
{
"source": 27,
"target": 4,
"value": 1
},
{
"source": 27,
"target": 39,
"value": 1
},
{
"source": 27,
"target": 14,
"value": 1
},
{
"source": 32,
"target": 29,
"value": 1
},
{
"source": 32,
"target": 17,
"value": 1
},
{
"source": 32,
"target": 36,
"value": 1
},
{
"source": 3,
"target": 31,
"value": 1
},
{
"source": 3,
"target": 2,
"value": 1
},
{
"source": 17,
"target": 37,
"value": 1
},
{
"source": 43,
"target": 18,
"value": 1
},
{
"source": 43,
"target": 15,
"value": 1
},
{
"source": 43,
"target": 25,
"value": 1
},
{
"source": 43,
"target": 40,
"value": 1
},
{
"source": 43,
"target": 6,
"value": 1
},
{
"source": 24,
"target": 11,
"value": 1
},
{
"source": 24,
"target": 39,
"value": 1
},
{
"source": 13,
"target": 33,
"value": 1
},
{
"source": 13,
"target": 15,
"value": 1
},
{
"source": 13,
"target": 20,
"value": 1
},
{
"source": 13,
"target": 12,
"value": 1
},
{
"source": 39,
"target": 21,
"value": 1
},
{
"source": 11,
"target": 42,
"value": 1
},
{
"source": 11,
"target": 31,
"value": 1
},
{
"source": 25,
"target": 40,
"value": 1
},
{
"source": 25,
"target": 38,
"value": 1
},
{
"source": 40,
"target": 0,
"value": 1
},
{
"source": 40,
"target": 15,
"value": 1
},
{
"source": 40,
"target": 1,
"value": 1
},
{
"source": 40,
"target": 23,
"value": 1
},
{
"source": 1,
"target": 41,
"value": 1
},
{
"source": 1,
"target": 23,
"value": 1
},
{
"source": 1,
"target": 16,
"value": 1
},
{
"source": 16,
"target": 23,
"value": 1
},
{
"source": 16,
"target": 41,
"value": 1
},
{
"source": 33,
"target": 15,
"value": 1
},
{
"source": 33,
"target": 36,
"value": 1
},
{
"source": 33,
"target": 20,
"value": 1
},
{
"source": 15,
"target": 12,
"value": 1
},
{
"source": 36,
"target": 7,
"value": 1
},
{
"source": 36,
"target": 29,
"value": 1
},
{
"source": 36,
"target": 18,
"value": 1
},
{
"source": 2,
"target": 30,
"value": 1
},
{
"source": 2,
"target": 31,
"value": 1
},
{
"source": 2,
"target": 42,
"value": 1
},
{
"source": 0,
"target": 23,
"value": 1
},
{
"source": 41,
"target": 30,
"value": 1
},
{
"source": 31,
"target": 42,
"value": 1
},
{
"source": 29,
"target": 7,
"value": 1
},
{
"source": 42,
"target": 4,
"value": 1
},
{
"source": 30,
"target": 4,
"value": 1
},
{
"source": 14,
"target": 4,
"value": 1
},
{
"source": 7,
"target": 18,
"value": 1
},
{
"source": 18,
"target": 6,
"value": 1
}
],
"nodes": [
{
"group": 0,
"name": "AL",
"nedges": 4
},
{
"group": 0,
"name": "AR",
"nedges": 6
},
{
"group": 0,
"name": "AZ",
"nedges": 4
},
{
"group": 0,
"name": "CA",
"nedges": 3
},
{
"group": 0,
"name": "CO",
"nedges": 6
},
{
"group": 0,
"name": "CT",
"nedges": 3
},
{
"group": 0,
"name": "DC",
"nedges": 2
},
{
"group": 0,
"name": "DE",
"nedges": 3
},
{
"group": 0,
"name": "FL",
"nedges": 2
},
{
"group": 0,
"name": "GA",
"nedges": 5
},
{
"group": 0,
"name": "IA",
"nedges": 6
},
{
"group": 0,
"name": "ID",
"nedges": 6
},
{
"group": 0,
"name": "IL",
"nedges": 5
},
{
"group": 0,
"name": "IN",
"nedges": 4
},
{
"group": 0,
"name": "KS",
"nedges": 4
},
{
"group": 0,
"name": "KY",
"nedges": 7
},
{
"group": 0,
"name": "LA",
"nedges": 3
},
{
"group": 0,
"name": "MA",
"nedges": 5
},
{
"group": 0,
"name": "MD",
"nedges": 5
},
{
"group": 0,
"name": "ME",
"nedges": 1
},
{
"group": 0,
"name": "MI",
"nedges": 3
},
{
"group": 0,
"name": "MN",
"nedges": 4
},
{
"group": 0,
"name": "MO",
"nedges": 8
},
{
"group": 0,
"name": "MS",
"nedges": 4
},
{
"group": 0,
"name": "MT",
"nedges": 4
},
{
"group": 0,
"name": "NC",
"nedges": 4
},
{
"group": 0,
"name": "ND",
"nedges": 3
},
{
"group": 0,
"name": "NE",
"nedges": 6
},
{
"group": 0,
"name": "NH",
"nedges": 3
},
{
"group": 0,
"name": "NJ",
"nedges": 3
},
{
"group": 0,
"name": "NM",
"nedges": 4
},
{
"group": 0,
"name": "NV",
"nedges": 5
},
{
"group": 0,
"name": "NY",
"nedges": 5
},
{
"group": 0,
"name": "OH",
"nedges": 5
},
{
"group": 0,
"name": "OK",
"nedges": 6
},
{
"group": 0,
"name": "OR",
"nedges": 4
},
{
"group": 0,
"name": "PA",
"nedges": 6
},
{
"group": 0,
"name": "RI",
"nedges": 2
},
{
"group": 0,
"name": "SC",
"nedges": 2
},
{
"group": 0,
"name": "SD",
"nedges": 6
},
{
"group": 0,
"name": "TN",
"nedges": 8
},
{
"group": 0,
"name": "TX",
"nedges": 4
},
{
"group": 0,
"name": "UT",
"nedges": 5
},
{
"group": 0,
"name": "VA",
"nedges": 6
},
{
"group": 0,
"name": "VT",
"nedges": 3
},
{
"group": 0,
"name": "WA",
"nedges": 2
},
{
"group": 0,
"name": "WI",
"nedges": 4
},
{
"group": 0,
"name": "WV",
"nedges": 5
},
{
"group": 0,
"name": "WY",
"nedges": 6
}
]
}
// d3.tip
// Copyright (c) 2013 Justin Palmer
//
// Tooltips for d3.js SVG visualizations
// Public - contructs a new tooltip
//
// Returns a tip
d3.tip = function() {
var direction = d3_tip_direction,
offset = d3_tip_offset,
html = d3_tip_html,
node = initNode(),
svg = null,
point = null,
target = null
function tip(vis) {
svg = getSVGNode(vis)
point = svg.createSVGPoint()
document.body.appendChild(node)
}
// Public - show the tooltip on the screen
//
// Returns a tip
tip.show = function() {
var args = Array.prototype.slice.call(arguments)
if(args[args.length - 1] instanceof SVGElement) target = args.pop()
var content = html.apply(this, args),
poffset = offset.apply(this, args),
dir = direction.apply(this, args),
nodel = d3.select(node), i = 0,
coords
nodel.html(content)
.style({ opacity: 1, 'pointer-events': 'all' })
while(i--) nodel.classed(directions[i], false)
coords = direction_callbacks.get(dir).apply(this)
nodel.classed(dir, true).style({
top: (coords.top + poffset[0]) + 'px',
left: (coords.left + poffset[1]) + 'px'
})
return tip
}
// Public - hide the tooltip
//
// Returns a tip
tip.hide = function() {
nodel = d3.select(node)
nodel.style({ opacity: 0, 'pointer-events': 'none' })
return tip
}
// Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
//
// n - name of the attribute
// v - value of the attribute
//
// Returns tip or attribute value
tip.attr = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).attr(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.attr.apply(d3.select(node), args)
}
return tip
}
// Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
//
// n - name of the property
// v - value of the property
//
// Returns tip or style property value
tip.style = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).style(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.style.apply(d3.select(node), args)
}
return tip
}
// Public: Set or get the direction of the tooltip
//
// v - One of n(north), s(south), e(east), or w(west), nw(northwest),
// sw(southwest), ne(northeast) or se(southeast)
//
// Returns tip or direction
tip.direction = function(v) {
if (!arguments.length) return direction
direction = v == null ? v : d3.functor(v)
return tip
}
// Public: Sets or gets the offset of the tip
//
// v - Array of [x, y] offset
//
// Returns offset or
tip.offset = function(v) {
if (!arguments.length) return offset
offset = v == null ? v : d3.functor(v)
return tip
}
// Public: sets or gets the html value of the tooltip
//
// v - String value of the tip
//
// Returns html value or tip
tip.html = function(v) {
if (!arguments.length) return html
html = v == null ? v : d3.functor(v)
return tip
}
function d3_tip_direction() { return 'n' }
function d3_tip_offset() { return [0, 0] }
function d3_tip_html() { return ' ' }
var direction_callbacks = d3.map({
n: direction_n,
s: direction_s,
e: direction_e,
w: direction_w,
nw: direction_nw,
ne: direction_ne,
sw: direction_sw,
se: direction_se
}),
directions = direction_callbacks.keys()
function direction_n() {
var bbox = getScreenBBox()
return {
top: bbox.n.y - node.offsetHeight,
left: bbox.n.x - node.offsetWidth / 2
}
}
function direction_s() {
var bbox = getScreenBBox()
return {
top: bbox.s.y,
left: bbox.s.x - node.offsetWidth / 2
}
}
function direction_e() {
var bbox = getScreenBBox()
return {
top: bbox.e.y - node.offsetHeight / 2,
left: bbox.e.x
}
}
function direction_w() {
var bbox = getScreenBBox()
return {
top: bbox.w.y - node.offsetHeight / 2,
left: bbox.w.x - node.offsetWidth
}
}
function direction_nw() {
var bbox = getScreenBBox()
return {
top: bbox.nw.y - node.offsetHeight,
left: bbox.nw.x - node.offsetWidth
}
}
function direction_ne() {
var bbox = getScreenBBox()
return {
top: bbox.ne.y - node.offsetHeight,
left: bbox.ne.x
}
}
function direction_sw() {
var bbox = getScreenBBox()
return {
top: bbox.sw.y,
left: bbox.sw.x - node.offsetWidth
}
}
function direction_se() {
var bbox = getScreenBBox()
return {
top: bbox.se.y,
left: bbox.e.x
}
}
function initNode() {
var node = d3.select(document.createElement('div'))
node.style({
position: 'absolute',
opacity: 0,
pointerEvents: 'none',
boxSizing: 'border-box'
})
return node.node()
}
function getSVGNode(el) {
el = el.node()
if(el.tagName.toLowerCase() == 'svg')
return el
return el.ownerSVGElement
}
// Private - gets the screen coordinates of a shape
//
// Given a shape on the screen, will return an SVGPoint for the directions
// n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
// sw(southwest).
//
// +-+-+
// | |
// + +
// | |
// +-+-+
//
// Returns an Object {n, s, e, w, nw, sw, ne, se}
function getScreenBBox() {
var targetel = target || d3.event.target,
bbox = {},
matrix = targetel.getScreenCTM(),
tbbox = targetel.getBBox(),
width = tbbox.width,
height = tbbox.height,
x = tbbox.x,
y = tbbox.y,
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
point.x = x + scrollLeft
point.y = y + scrollTop
bbox.nw = point.matrixTransform(matrix)
point.x += width
bbox.ne = point.matrixTransform(matrix)
point.y += height
bbox.se = point.matrixTransform(matrix)
point.x -= width
bbox.sw = point.matrixTransform(matrix)
point.y -= height / 2
bbox.w = point.matrixTransform(matrix)
point.x += width
bbox.e = point.matrixTransform(matrix)
point.x -= width / 2
point.y -= height / 2
bbox.n = point.matrixTransform(matrix)
point.y += height
bbox.s = point.matrixTransform(matrix)
return bbox
}
return tip
};
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://gist.github.com/N0taN3rd/f1ba6bef2fc906b87dbf#file-d3tip-js"></script>
<style>
svg {
font: 10px sans-serif;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.background {
fill: #eee;
}
line {
stroke: #fff;
}
text.active {
fill: red;
}
body {
display: block;
margin: 66px;
}
line.link {
stroke: #999;
stroke-opacity: .6;
}
.background {
fill: #eee;
}
line {
stroke: #fff;
}
text.active {
fill: red;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
</style>
</head>
<body>
<div id="vis1">
<p>Order: <select id="order">
<option value="name">by Name</option>
<option value="count">by Frequency</option>
</select>
</div>
<div id="vis2">
</div>
<script>
d3.tip = function() {
var direction = d3_tip_direction,
offset = d3_tip_offset,
html = d3_tip_html,
node = initNode(),
svg = null,
point = null,
target = null
function tip(vis) {
svg = getSVGNode(vis)
point = svg.createSVGPoint()
document.body.appendChild(node)
}
// Public - show the tooltip on the screen
//
// Returns a tip
tip.show = function() {
var args = Array.prototype.slice.call(arguments)
if(args[args.length - 1] instanceof SVGElement) target = args.pop()
var content = html.apply(this, args),
poffset = offset.apply(this, args),
dir = direction.apply(this, args),
nodel = d3.select(node), i = 0,
coords
nodel.html(content)
.style({ opacity: 1, 'pointer-events': 'all' })
while(i--) nodel.classed(directions[i], false)
coords = direction_callbacks.get(dir).apply(this)
nodel.classed(dir, true).style({
top: (coords.top + poffset[0]) + 'px',
left: (coords.left + poffset[1]) + 'px'
})
return tip
}
// Public - hide the tooltip
//
// Returns a tip
tip.hide = function() {
nodel = d3.select(node)
nodel.style({ opacity: 0, 'pointer-events': 'none' })
return tip
}
// Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
//
// n - name of the attribute
// v - value of the attribute
//
// Returns tip or attribute value
tip.attr = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).attr(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.attr.apply(d3.select(node), args)
}
return tip
}
// Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
//
// n - name of the property
// v - value of the property
//
// Returns tip or style property value
tip.style = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).style(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.style.apply(d3.select(node), args)
}
return tip
}
// Public: Set or get the direction of the tooltip
//
// v - One of n(north), s(south), e(east), or w(west), nw(northwest),
// sw(southwest), ne(northeast) or se(southeast)
//
// Returns tip or direction
tip.direction = function(v) {
if (!arguments.length) return direction
direction = v == null ? v : d3.functor(v)
return tip
}
// Public: Sets or gets the offset of the tip
//
// v - Array of [x, y] offset
//
// Returns offset or
tip.offset = function(v) {
if (!arguments.length) return offset
offset = v == null ? v : d3.functor(v)
return tip
}
// Public: sets or gets the html value of the tooltip
//
// v - String value of the tip
//
// Returns html value or tip
tip.html = function(v) {
if (!arguments.length) return html
html = v == null ? v : d3.functor(v)
return tip
}
function d3_tip_direction() { return 'n' }
function d3_tip_offset() { return [0, 0] }
function d3_tip_html() { return ' ' }
var direction_callbacks = d3.map({
n: direction_n,
s: direction_s,
e: direction_e,
w: direction_w,
nw: direction_nw,
ne: direction_ne,
sw: direction_sw,
se: direction_se
}),
directions = direction_callbacks.keys()
function direction_n() {
var bbox = getScreenBBox()
return {
top: bbox.n.y - node.offsetHeight,
left: bbox.n.x - node.offsetWidth / 2
}
}
function direction_s() {
var bbox = getScreenBBox()
return {
top: bbox.s.y,
left: bbox.s.x - node.offsetWidth / 2
}
}
function direction_e() {
var bbox = getScreenBBox()
return {
top: bbox.e.y - node.offsetHeight / 2,
left: bbox.e.x
}
}
function direction_w() {
var bbox = getScreenBBox()
return {
top: bbox.w.y - node.offsetHeight / 2,
left: bbox.w.x - node.offsetWidth
}
}
function direction_nw() {
var bbox = getScreenBBox()
return {
top: bbox.nw.y - node.offsetHeight,
left: bbox.nw.x - node.offsetWidth
}
}
function direction_ne() {
var bbox = getScreenBBox()
return {
top: bbox.ne.y - node.offsetHeight,
left: bbox.ne.x
}
}
function direction_sw() {
var bbox = getScreenBBox()
return {
top: bbox.sw.y,
left: bbox.sw.x - node.offsetWidth
}
}
function direction_se() {
var bbox = getScreenBBox()
return {
top: bbox.se.y,
left: bbox.e.x
}
}
function initNode() {
var node = d3.select(document.createElement('div'))
node.style({
position: 'absolute',
opacity: 0,
pointerEvents: 'none',
boxSizing: 'border-box'
})
return node.node()
}
function getSVGNode(el) {
el = el.node()
if(el.tagName.toLowerCase() == 'svg')
return el
return el.ownerSVGElement
}
// Private - gets the screen coordinates of a shape
//
// Given a shape on the screen, will return an SVGPoint for the directions
// n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
// sw(southwest).
//
// +-+-+
// | |
// + +
// | |
// +-+-+
//
// Returns an Object {n, s, e, w, nw, sw, ne, se}
function getScreenBBox() {
var targetel = target || d3.event.target,
bbox = {},
matrix = targetel.getScreenCTM(),
tbbox = targetel.getBBox(),
width = tbbox.width,
height = tbbox.height,
x = tbbox.x,
y = tbbox.y,
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
point.x = x + scrollLeft
point.y = y + scrollTop
bbox.nw = point.matrixTransform(matrix)
point.x += width
bbox.ne = point.matrixTransform(matrix)
point.y += height
bbox.se = point.matrixTransform(matrix)
point.x -= width
bbox.sw = point.matrixTransform(matrix)
point.y -= height / 2
bbox.w = point.matrixTransform(matrix)
point.x += width
bbox.e = point.matrixTransform(matrix)
point.x -= width / 2
point.y -= height / 2
bbox.n = point.matrixTransform(matrix)
point.y += height
bbox.s = point.matrixTransform(matrix)
return bbox
}
return tip
};
var margin = {top: 80, right: 0, bottom: 10, left: 80},
width = 720,
height = 720;
var x = d3.scale.ordinal().rangeBands([0, width]),
z = d3.scale.linear().domain([0, 4]).clamp(true),
c = d3.scale.category10().domain(d3.range(10));
var svg = d3.select("#vis1").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.style("margin-left", -margin.left + "px")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("contiguous-usa.json", function(data) {
var matrix = [],
nodes = data.nodes,
n = nodes.length;
// Compute index per node.
nodes.forEach(function(node, i) {
node.index = i;
node.count = 0;
matrix[i] = d3.range(n).map(function(j) { return {x: j, y: i, z: 0}; });
});
// Convert links to matrix; count character occurrences.
data.links.forEach(function(link) {
matrix[link.source][link.target].z += link.value;
matrix[link.target][link.source].z += link.value;
matrix[link.source][link.source].z += link.value;
matrix[link.target][link.target].z += link.value;
nodes[link.source].count += link.value;
nodes[link.target].count += link.value;
});
// Precompute the orders.
var orders = {
name: d3.range(n).sort(function(a, b) { return d3.ascending(nodes[a].name, nodes[b].name); }),
count: d3.range(n).sort(function(a, b) { return nodes[b].count - nodes[a].count; })
};
// The default sort order.
x.domain(orders.name);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height);
function order(value) {
x.domain(orders[value]);
var t = svg.transition().duration(2500);
t.selectAll(".row")
.delay(function(d, i) { return x(i) * 4; })
.attr("transform", function(d, i) { return "translate(0," + x(i) + ")"; })
.selectAll(".cell")
.delay(function(d) { return x(d.x) * 4; })
.attr("x", function(d) { return x(d.x); });
t.selectAll(".column")
.delay(function(d, i) { return x(i) * 4; })
.attr("transform", function(d, i) { return "translate(" + x(i) + ")rotate(-90)"; });
}
var row = svg.selectAll(".row")
.data(matrix)
.enter().append("g")
.attr("class", "row")
.attr("transform", function(d, i) { return "translate(0," + x(i) + ")"; })
.each(rr);
row.append("line")
.attr("x2", width);
row.append("text")
.attr("x", -6)
.attr("y", x.rangeBand() / 2)
.attr("dy", ".32em")
.attr("text-anchor", "end")
.text(function(d, i) {
console.log(nodes[i].name);
return nodes[i].name; });
var column = svg.selectAll(".column")
.data(matrix)
.enter().append("g")
.attr("class", "column")
.attr("transform", function(d, i) { return "translate(" + x(i) + ")rotate(-90)"; });
column.append("line")
.attr("x1", -width);
column.append("text")
.attr("x", 6)
.attr("y", x.rangeBand() / 2)
.attr("dy", ".32em")
.attr("text-anchor", "start")
.text(function(d, i) { return nodes[i].name; });
function mouseover(p) {
d3.selectAll(".row text").classed("active", function(d, i) { return i == p.y; });
d3.selectAll(".column text").classed("active", function(d, i) { return i == p.x; });
}
function mouseout() {
d3.selectAll("text").classed("active", false);
}
d3.select("#order").on("change", function() {
clearTimeout(timeout);
order(this.value);
});
function rr(row) {
var cell = d3.select(this).selectAll(".cell")
.data(row.filter(function(d) { return d.z; }))
.enter().append("rect")
.attr("class", "cell")
.attr("x", function(d) { return x(d.x); })
.attr("width", x.rangeBand())
.attr("height", x.rangeBand())
.style("fill-opacity", function(d) { return z(d.z); })
.style("fill", function(d) { return nodes[d.x].group == nodes[d.y].group ? c(nodes[d.x].group) : null;})
.on("mouseover", mouseover)
.on("mouseout", mouseout);
}
var timeout = setTimeout(function() {
order("name");
d3.select("#order").property("selectedIndex", 0).node().focus();
}, 5000);
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
.text("Matrix");
});
d3.json("contiguous-usa.json", function(data) {
var width = 960, height = 600;
var svg = d3.select("#vis2").append("svg").attr("width", width).attr("height", height);
var cc = d3.scale.category10().domain(d3.range(10));
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
//console.log(color(d.nedges));
//''color:'+color(d.nedges)+''''color:red
console.log(cc(d.nedges));
var c = "'color:" + cc(d.nedges) + ";'";
return "<strong>State:</strong> <span style=c>" + d.name + "</span>";
});
svg.call(tip);
var force = d3.layout.force()
.charge(-200)
.linkDistance(20)
.size([width, height]);
force
.nodes(data.nodes)
.links(data.links)
.start();
var link = svg.selectAll(".link")
.data(data.links).enter().append("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(data.nodes)
.enter()
.append("circle")
.attr("class", "node")
.attr("r", 5)
.style("fill", function (d) {
return d3.rgb("#0000FF");
})
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.call(force.drag());
force.on("tick", function () {
link.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
node.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
});
});
svg.append("text")
.attr("x", (width / 2))
.attr("y",25)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
.text("Node Link");
});
d3.select(self.frameElement).style("height", "1500px").style("width","1200px");
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment