| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8"> | |
| <title>Circular Grid Chart - jsFiddle demo by ramnathv</title> | |
| <script type="text/javascript" src="//coffeescript.org/extras/coffee-script.js"></script> | |
| <script type='text/javascript' src="//d3js.org/d3.v3.min.js"></script> | |
| <script type='text/javascript' src="//rawgit.com/gka/d3-jetpack/master/d3-jetpack.js"></script> | |
| <script type='text/javascript' src="//rawgit.com/kristw/75b61f9beeab9b530612/raw/389e984e4041117a9185cf6edad9f6b85a38097a/d3kit.min.js"></script> | |
| <script type='text/javascript' src="//rawgit.com/ramnathv/a5a3199538f86817ec1b/raw/f6627fc544e65d8e6186ba87556f743caa3f2730/visutils.js"></script> | |
| <link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> | |
| <script type='text/javascript' src="//gka.github.io/chroma.js/vendor/chroma-js/chroma.min.js"></script> | |
| <script type='text/javascript' src="//rawgit.com/Caged/d3-tip/master/index.js"></script> | |
| <link rel="stylesheet" type="text/css" href="//rawgit.com/Caged/d3-tip/master/examples/example-styles.css"> | |
| <style type='text/css'> | |
| #main{ | |
| margin-top: 20px; | |
| } | |
| .x-axis-layer path, | |
| .x-axis-layer line{ | |
| fill: none; | |
| } | |
| .y-axis-layer path, | |
| .y-axis-layer line{ | |
| fill: none; | |
| } | |
| svg text{ | |
| font-size: 10px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container-fluid" id="main"> | |
| <div class="row"> | |
| <div class="col-xs-12 col-md-4"> | |
| <div id="chart"></div> | |
| </div> | |
| <div class="col-xs-12 col-md-4"> | |
| <div class="col-xs-6 col-md-4"> | |
| <div class="thumbnail"> | |
| <img id='avatar1' src="https://randomuser.me/api/portraits/thumb/men/1.jpg" class="img-circle"> | |
| </div> | |
| </div> | |
| <div class="col-xs-6 col-md-4"> | |
| <div class="thumbnail"> | |
| <img id='avatar2' src="https://randomuser.me/api/portraits/thumb/men/2.jpg" class="img-circle"> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script type="text/coffeescript"> | |
| y = d3.range(20) | |
| x = y | |
| expand_grid = (x, y) -> | |
| d3.merge(x.map (x_) -> y.map (y_) -> {x: x_, y: y_}) | |
| data = expand_grid(x, y) | |
| data.forEach (d) -> | |
| d.c = Math.random() | |
| switch_avatar = (d) -> | |
| #d3.json "//randomuser.me/api/", (error, data) -> | |
| url = (x) -> | |
| "https://randomuser.me/api/portraits/thumb/men/#{x}.jpg" | |
| d3.select('#avatar1').attr('src', url(d.x)) | |
| d3.select('#avatar2').attr('src', url(d.y)) | |
| circularGridConstructor = (skeleton) -> | |
| layers = skeleton.getLayerOrganizer() | |
| S = | |
| x: d3.scale.ordinal() | |
| y: d3.scale.ordinal() | |
| c: d3.scale.linear().range(["lightyellow", "orange"]) | |
| .domain([0, 1]) | |
| .interpolate(d3.interpolateHcl) | |
| A = | |
| x: (d) -> d.x | |
| y: (d) -> d.y | |
| c: (d) -> d.c | |
| layers.create(["hrect", "vrect", 'x-axis', 'y-axis', 'circles']) | |
| hrect = layers.get('hrect').append('rect.hrect') | |
| vrect = layers.get('vrect').append('rect.vrect') | |
| visualize = -> | |
| data = skeleton.data() | |
| opts = skeleton.options() | |
| H = skeleton.getInnerHeight() | |
| W = skeleton.getInnerWidth() | |
| W = d3.min([W, H]) | |
| H = d3.min([W, H]) | |
| S.x.rangeRoundBands([0, W]).domain(data.map(A.x), 0, 0.01) | |
| S.y.rangeRoundBands([0, H]).domain(data.map(A.y), 0, 0.01) | |
| circles = layers.get('circles').selectAll('circle').data(data) | |
| circles.enter().append('circle') | |
| circles.attr | |
| cx: (d) -> S.x(A.x(d)) - S.x.rangeBand()/2 | |
| cy: (d) -> S.y(A.y(d)) - S.y.rangeBand()/2 | |
| r: (d) -> S.x.rangeBand()/2 | |
| fill: (d, i) -> S.c A.c(d) | |
| #circles.call attachTooltip, {html: (d) -> "(#{d.x}, #{d.y})"} | |
| highlight = (d) -> | |
| d3.select('.hrect').attr | |
| x: - S.x.rangeBand()/2 | |
| y: S.y(A.y(d)) - S.y.rangeBand() | |
| height: S.y.rangeBand() | |
| width: S.x(A.x(d)) | |
| fill: '#aaa' | |
| opacity: 0.9 | |
| d3.select('.vrect').attr | |
| x: S.x(A.x(d)) - S.x.rangeBand() | |
| y: S.y(A.y(d)) - S.y.rangeBand()/2 | |
| height: H - S.y(A.y(d)) - S.y.rangeBand() | |
| width: S.x.rangeBand() | |
| fill: '#ccc' | |
| opacity: 0.9 | |
| tip = d3.tip().attr('class', 'd3-tip') | |
| .html (d) -> "(#{d.x}, #{d.y})" | |
| #circles.call(tip) | |
| circles.on "mouseover", (d, i) -> | |
| #tip.show(d) | |
| switch_avatar(d) | |
| highlight(d) | |
| d3.select(@).attr | |
| stroke: "black" | |
| "stroke-width": 2 | |
| circles.on "mouseout", (d, i) -> | |
| #tip.hide(d) | |
| circles.each -> d3.select(@).attr("stroke", "none") | |
| #d3.select('.hrect').attr('width', 0) | |
| #d3.select('.vrect').attr('width', 0) | |
| layers.get('circles').on "mouseout", -> | |
| d3.select('.hrect').attr('width', 0) | |
| d3.select('.vrect').attr('width', 0) | |
| xAxis = d3.svg.axis() | |
| .scale(S.x) | |
| .orient('bottom') | |
| H2 = H - S.y.rangeBand() | |
| layers.get('x-axis') | |
| .translate([-S.x.rangeBand(), H2]) | |
| .call(xAxis) | |
| yAxis = d3.svg.axis() | |
| .scale(S.y) | |
| .orient('left') | |
| layers.get('y-axis') | |
| .translate([-S.x.rangeBand(), -S.y.rangeBand()]) | |
| .call(yAxis) | |
| skeleton | |
| .resizeToFitContainer() | |
| .on("data", visualize) | |
| .on("resize", visualize) | |
| .autoResize(true) | |
| renderCircularGrid= (el, x, width, height) -> | |
| circleGridChart = d3Kit.factory.createChart( | |
| x.defaults, [], circularGridConstructor | |
| ) | |
| mychart = new circleGridChart('#' + el.id).data(x.data) | |
| defaults = | |
| margin: {left: 50, right: 10, top: 30, bottom: 30} | |
| initialHeight: 400 | |
| initialWidth: "auto" | |
| fontSize: 10 | |
| el = document.getElementById('chart') | |
| x = {defaults: defaults, data: data} | |
| renderCircularGrid(el, x) | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment