jQuery(document).ready( function () {
// SVG Size and Location
var width = 500,
height = 200,
margin = {
top : 30,
bottom : 30,
left : 50,
right : 50
};
// SVG DOM creation
var mySvg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// root G creation
var rootG = mySvg.append("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
// Max Data
var xMax = 1000,
yMax = 20;
// Axis Size
// xHeight should be greater than margin.top so that X-Axis will appear
// yWidth should be greater thatn margin.right so that label of X-Axis will appear
var axisMargin = { xHeight : 80, yWidth : 80 };
// D3 Scale creation
// use real data value array as a parameter of domain()
// use pixel value array as a parameter of range()
// if the Origin point of chart is located in the bottom,
// the range array needs to be changed accordingly,
// because the browser's Origin point is located in the top.
var xScale = d3.scale.linear().domain([0, xMax]).range([0, width]),
yScale = d3.scale.linear().domain([0, yMax]).range([height, 0]);
// D3 X-Axis, Y-Axis creation
// note that typeof xAxis === "function" and typeof yAxis === "function",
// which means that svg.axis() returns function.
var xAxis = d3.svg.axis().scale(xScale).orient("bottom"),
yAxis = d3.svg.axis().scale(yScale).orient("left");
// X-Axis, Y-Axis DOM creation
var gXAxis = rootG.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis),
gYAxis = rootG.append("g")
.attr("class", "axis")
.call(yAxis);
//// From here, 02. Add Points
// Group of Point
var pointG = rootG.append("g");
// make new data
function makeNewData() {
var data = {
id: randomString(),
x: Math.random()*xMax,
y: Math.random()*yMax
};
return data;
}
// draw a point(a circle here) to the chart
function addPointToChart(data) {
var r = 4;
pointG.append("circle")
.datum(data)
.attr("cx", function (d) { return xScale(d.x); })
.attr("cy", function (d) { return yScale(d.y); })
.attr("r", r)
.style("fill", randomColorString());
}
// get random String for id
function randomString() {
return Math.random().toString(36).slice(2);
}
// get random Color for fill-color
function randomColorString() {
return "#"+Math.floor(Math.random()*16777215).toString(16);
}
// Test Invoker for adding a point to chart
$('#btnAdd1Point').click(function () {
addPointToChart(makeNewData());
});
//// From here, 03. Streaming the Axis
// toggle switcher for streaming
var isShiftOn = false;
// Shift X-axis to the left continuously, in a word, streaming
function shiftXAxis() {
if (isShiftOn) {
var shiftSize = 50,
currentDomainLeft = xScale.domain()[0],
currentDomainRight = xScale.domain()[1]
// update X-axis domain
xScale.domain([currentDomainLeft + shiftSize, currentDomainRight + shiftSize]);
// apply the updated domain to SVG
//*
gXAxis.transition()
.ease("linear")
.call(xAxis)
.each("end", shiftXAxis);
//*/
// 'transition.call(aFunction)' equals 'aFunction(transition)'
// So, the code below also works OK, but the code above looks better
/*
var t = gXAxis.transition().ease("linear");
xAxis(t);
t.each("end", shiftXAxis);
//*/
}
}
// Test Invoker for streaming X-axis
$('#btnShiftXAxis').click(toggleShift);
// function to toggle the streaming
function toggleShift() {
isShiftOn ? $(this).text("03. Streaming the Axis") : $(this).text("03. Stop Streaming");
isShiftOn = !isShiftOn;
if(isShiftOn) {
shiftXAxis();
}
}
});
External resources loaded into this fiddle:
<body>
<div id='tester'>
<button id='btnAdd1Point' type='button'>02. Add a Point</button>
<button id='btnShiftXAxis' type='button'>03. Streaming the axis</button>
</div>
</body>
/* font inherited from svg */
svg {
font: 12px sans-serif;
}
/* main line of axis */
.axis path {
fill: none;
stroke: darkgray;
font: 10px;
}
/* tick line of axis */
.axis line {
fill: none;
stroke: #3355ff;
}