Last active
October 9, 2017 12:31
-
-
Save bfunc/9640511725a77d677d4ed2405d2832e3 to your computer and use it in GitHub Desktop.
d3 v4 - issue - axis Date grid uneven line sizes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ | |
"daystamp": { | |
"value": "2017-03-01 00:00:00.000" | |
}, | |
"PL": -13496 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-02 00:00:00.000" | |
}, | |
"PL": -9930 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-07 00:00:00.000" | |
}, | |
"PL": -11506 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-08 00:00:00.000" | |
}, | |
"PL": -1970 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-09 00:00:00.000" | |
}, | |
"PL": 336 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-10 00:00:00.000" | |
}, | |
"PL": 7024 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-13 00:00:00.000" | |
}, | |
"PL": 5876 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-14 00:00:00.000" | |
}, | |
"PL": 4584 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-16 00:00:00.000" | |
}, | |
"PL": 6448 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-17 00:00:00.000" | |
}, | |
"PL": 5782 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-20 00:00:00.000" | |
}, | |
"PL": 5528 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-23 00:00:00.000" | |
}, | |
"PL": 9470 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-24 00:00:00.000" | |
}, | |
"PL": 7328 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-27 00:00:00.000" | |
}, | |
"PL": 7482 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-28 00:00:00.000" | |
}, | |
"PL": 6890 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-03-30 00:00:00.000" | |
}, | |
"PL": -42 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-03 00:00:00.000" | |
}, | |
"PL": -2006 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-04 00:00:00.000" | |
}, | |
"PL": -6590 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-05 00:00:00.000" | |
}, | |
"PL": -5348 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-07 00:00:00.000" | |
}, | |
"PL": -10012 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-10 00:00:00.000" | |
}, | |
"PL": -13742 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-11 00:00:00.000" | |
}, | |
"PL": -16128 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-12 00:00:00.000" | |
}, | |
"PL": -14426 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-13 00:00:00.000" | |
}, | |
"PL": -14036 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-17 00:00:00.000" | |
}, | |
"PL": -14956 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-18 00:00:00.000" | |
}, | |
"PL": -12734 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-19 00:00:00.000" | |
}, | |
"PL": -4370 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-20 00:00:00.000" | |
}, | |
"PL": -3428 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-21 00:00:00.000" | |
}, | |
"PL": 728 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-24 00:00:00.000" | |
}, | |
"PL": 1722 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-25 00:00:00.000" | |
}, | |
"PL": -372 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-26 00:00:00.000" | |
}, | |
"PL": 2864 | |
}, | |
{ | |
"daystamp": { | |
"value": "2017-04-27 00:00:00.000" | |
}, | |
"PL": 2300 | |
} | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Chart!</title> | |
<script src="https://d3js.org/d3.v4.min.js" type="text/javascript" charset="utf-8"></script> | |
<style> | |
svg#chart { | |
background-color: #E0E0E0; | |
position: absolute; | |
} | |
svg#chart path.link { | |
fill: none; | |
stroke-width: 4px; | |
stroke: #4D4D4D; | |
} | |
svg#chart .tick line { | |
stroke: #868686; | |
stroke-opacity: 0.5; | |
shape-rendering: crispEdges; | |
} | |
svg#chart #cipping-mask-rect-bg { | |
fill: #FFFFFF; | |
} | |
svg#chart .tick path { | |
stroke-width: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<svg id='chart'> | |
<defs> | |
<clipPath id='cipping-mask'> | |
<rect id='cipping-mask-rect' x='0' y='0' width='100' height='100' /> | |
</clipPath> | |
</defs> | |
<rect id='cipping-mask-rect-bg' x='0' y='0' width='100' height='100' /> | |
<g id='controls-group' /> | |
<g id='chart-group' clip-path='url(#cipping-mask)' /> | |
</svg> | |
<script> | |
const | |
OFFSET_CHART_X = 50, | |
OFFSET_CHART_Y = 25; | |
window.d3 = d3; | |
/// init vars ////////////////// | |
d3.json("data.json", function (error, json) { | |
if (error) throw error; | |
init(json); | |
}); | |
function init(jsonData) { | |
let svg = d3.select('svg#chart'), | |
controlsGroup = svg.select('g#controls-group'), | |
chartGroup = svg.select('g#chart-group') | |
.attr('transform', `translate(${OFFSET_CHART_X},${OFFSET_CHART_Y})`), | |
mask = d3.select('rect#cipping-mask-rect'), | |
maskBg = d3.select('rect#cipping-mask-rect-bg') | |
.attr('transform', `translate(${OFFSET_CHART_X},${OFFSET_CHART_Y})`), | |
xScale, yScale, xAxisG, yAxisG, xScaleUpdated, | |
width = 750, height = 450, | |
data = jsonData.map(v => ({ date: new Date(v.daystamp.value), value: +v.PL })), | |
formatTime = d3.timeFormat('%B %d, %Y'), | |
lineGenerator = d3.line() | |
.x(d => xScale(d.date)) | |
.y(d => yScale(d.value)) | |
.curve(d3.curveLinear); | |
/// layout //////////////////// | |
svg.attr('width', width); | |
svg.attr('height', height); | |
let maskWidth = width - OFFSET_CHART_X * 2; | |
let maskHeight = height - OFFSET_CHART_Y * 3; | |
mask.attr('width', maskWidth); | |
mask.attr('height', maskHeight); | |
maskBg.attr('width', maskWidth); | |
maskBg.attr('height', maskHeight); | |
updateAxis(); | |
/// d3 enter/update /////////////// | |
let chart = chartGroup.selectAll('path') | |
.data([data]); | |
let grpChartEnter = chart.enter() | |
.append('path') | |
.attr('class', 'link'); | |
chart = grpChartEnter.merge(chart) | |
.attr('d', lineGenerator); | |
/// zoom /////////////////////////// | |
let zoom = d3.zoom().on('zoom', zoomFnc); | |
svg.call(zoom); | |
zoom.scaleTo(svg, 2) | |
/// helper functions /////////////// | |
function zoomFnc() { | |
xAxisG.transition() | |
.duration(1) | |
.call(xAxis.ticks(10).scale(d3.event.transform.rescaleX(xScale))); | |
let | |
new_xScale = d3.event.transform.rescaleX(xScale), | |
new_lineGenerator = d3.line() | |
.x(d => new_xScale(d.date)) | |
.y(d => yScale(d.value)); | |
chart.attr('d', new_lineGenerator); | |
xScaleUpdated = new_xScale; | |
} | |
function updateAxis() { | |
controlsGroup.selectAll('g.axisX').remove(); | |
controlsGroup.selectAll('g.axisY').remove(); | |
xScale = d3.scaleTime().range([0, width - OFFSET_CHART_X * 2]); | |
xScale.domain(expandDateByTs(d3.extent(data, d => d.date))); | |
xAxis = d3.axisBottom(xScale); | |
xAxisG = controlsGroup.append('g') | |
.attr('class', 'axisX') | |
.attr('transform', `translate(${OFFSET_CHART_X},${height - OFFSET_CHART_Y * 2} )`) | |
.call(xAxis); | |
xScaleUpdated = xScale; | |
yScale = d3.scaleLinear().range([height - OFFSET_CHART_Y * 3, 0]); | |
yScale.domain(expandByPercent(d3.extent(data, d => d.value), 10)); | |
yAxis = d3.axisLeft(yScale); | |
yAxisG = controlsGroup.append('g') | |
.attr('class', 'axisY') | |
.attr('transform', `translate(${OFFSET_CHART_X},${OFFSET_CHART_Y})`) | |
.call(yAxis); | |
// Gridline | |
let gridlinesX = xAxis | |
.ticks() | |
.tickSize(-(height - OFFSET_CHART_Y * 3)) | |
.scale(xScale) | |
xAxisG.call(gridlinesX); | |
let gridlinesY = yAxis | |
.ticks() | |
.tickSize(-(width - OFFSET_CHART_X * 2)) | |
.scale(yScale) | |
yAxisG.call(gridlinesY); | |
function expandByPercent(arr, percent) { | |
let val1 = arr[0], val2 = arr[1], | |
val1p = val1 * (percent / 100), | |
val2p = val2 * (percent / 100); | |
return [val1 + val1p, val2 + val2p]; | |
} | |
function expandDateByTs(arr, day = 1000 * 60 * 60 * 24) { | |
let val1 = Date.parse(arr[0]), val2 = Date.parse(arr[1]); | |
return [val1 - day, val2 + day]; | |
} | |
} | |
////////////////////////////////////////// | |
}// end of init function | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment