JSFiddle - React, Tailwind, and code Playground
by rwhal06
HTML
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="//d3js.org/d3.v4.min.js"></script>
<div class="d3Chart" id="mChart" data-parameter="cm" data-value="30" data-type="bigDollars" data-xAxisLabel="x" data-xAxisFormat="$.2f" data-yAxisLabel="y" data-yAxisFormat="$.2f" data-restrict="Math.max(3e4, Math.min(3e6, d3.round(v < 1000 ? v * 1000 : v, -3)))"
data-scale="d3.scale.log().domain([3e4, 3e6])" data-scale-format="$s" data-height="240">
</div>
<h3>
My chart above is on its way to looking and behaving like Bostock's (below) but needs these additional features:
</h3>
<ol>
<li>handle should move when dragged</li>
<li>After dragging, input box val should be adjusted and formatted to make sense</li>
<li>On change of input box value, attr data-value and charts should update</li>
<li>There should be a y-value tooltip that is dynamically updated</li>
</ol>
<a href="https://www.nytimes.com/interactive/2014/upshot/buy-rent-calculator.html" target="_blank">(link to Bostock's)</a>
<a href="https://www.nytimes.com/interactive/2014/upshot/buy-rent-calculator.html" target="_blank"><img src="http://i.imgur.com/XOCLWJE.png" /></a>
SCSS
.chartTitle{
font-weight: bold;
font-size: 14px;
position: relative;
top: 100px;
}
.bar {
fill: steelblue;
&:hover {
fill: brown;
}
}
.axisLabel{
font-size: 18px;
font-weight: bold;
}
.ticks {
font: 10px sans-serif;
}
.track,
.track-inset,
.track-overlay {
stroke-linecap: round;
}
$trackStroke: 8px;
.track {
stroke: #000;
stroke-opacity: 0.3;
stroke-width: $trackStroke;
}
.track-inset {
stroke: #ddd;
stroke-width: $trackStroke - 2;
}
.track-overlay {
pointer-events: stroke;
stroke-width: 50px;
cursor: ew-resize;
}
.handle {
fill: #fff;
stroke: #000;
stroke-opacity: 0.5;
stroke-width: 1.25px;
cursor: ew-resize;
user-select: none;
pointer-events: none;
}
.line {
fill: none;
stroke: black;
stroke-width: 2px;
}
.grid {
line {
stroke: white;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}
path {
stroke-width: 0;
}
}
.g-parameter-input{
position: relative;
left: -230px;
display: inline;
min-width: 160px;
input{
padding: 4px 0;
width: 40px;
margin: auto;
}
}
.g-parameter-tip {
z-index: 1;
pointer-events: none;
position: absolute;
left: 50%;
text-anchor: middle;
path {
fill: hsl(69, 91%, 44%);
}
}
JavaScript
$(document).ready(function() {
function getData() {
var a = 0.04;
var data = [];
for (var b = 8; b <= 50; b = b + 1) {
data.push({
xVar: b,
yVar: b / a
});
}
return data;
}
function drawChart(selector, data) {
var chartEl = d3.select(selector);
var xAxisLabel = chartEl.attr("data-xAxisLabel");
var xAxisFormat = chartEl.attr("data-xAxisFormat");
var yAxisLabel = chartEl.attr("data-yAxisLabel");
var yAxisFormat = chartEl.attr("data-yAxisFormat");
chartEl.selectAll("*").remove();
var svg = chartEl.append("svg");
svg.attr('width', 350).attr('height', 300).attr('viewBox', '0 0 350 300');
var margin = {
top: 50,
right: 20,
bottom: 40,
left: 70
};
var width = +svg.attr("width") - margin.left - margin.right;
var height = +svg.attr("height") - margin.top - margin.bottom;
var sliderTop = 0 + height + margin.top;
var xBandScale = d3.scaleBand().rangeRound([0, width]).padding(0.1);
var xAxisScale = d3.scaleLinear().rangeRound([0, width]); //TODO: allow log scale via attr
var yAxisScale = d3.scaleLinear().rangeRound([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
xBandScale.domain(data.map(function(d) {
return d.xVar;
}));
xAxisScale.domain([d3.min(data, function(d) {
return d.xVar;
}), d3.max(data, function(d) {
return d.xVar;
})]);
yAxisScale.domain([d3.min(data, function(d) {
return d.yVar;
}), d3.max(data, function(d) {
return d.yVar;
})]);
var yTicks = 6;
var gX = g.append("g") //add x-axis
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xAxisScale).ticks(5, xAxisFormat));
g.append("text") //add x-axis label
.attr("class", "axisLabel xAxisLabel")
...