|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<script src="//d3js.org/d3.v4.min.js"></script> |
|
|
|
<!-- what to achieve? ---------------------------------- |
|
1. create a line |
|
2. transition to push new data into line data |
|
3. remove the begining data each time when pushing new data |
|
--> |
|
|
|
<!---- step 1: mannually create a svg with height and width --> |
|
<svg width="960" height="500"></svg> |
|
<style> |
|
|
|
|
|
|
|
/* ---- step 2: set styles ------------------------------ |
|
1. className: "line" |
|
2. set fill color, stroke color, and stroke-width |
|
*/ |
|
|
|
.line { |
|
fill: none; |
|
stroke: #000; |
|
stroke-width: 1.5px; |
|
} |
|
|
|
</style> |
|
|
|
|
|
|
|
|
|
<script> |
|
|
|
// ---- step 3: create inner canvas placeholder g --------------- |
|
// 1. select svg |
|
// 2. set margin for centering inner canvas |
|
// 3. set inner canvas' width and height |
|
// 4. upon svg, create a g placeholder |
|
// 5. add transform-translate attr: move g to origin position of inner canvas |
|
// or move g to topLeft corner of inner canvas |
|
var svg = d3.select("svg"), |
|
margin = {top: 20, right: 20, bottom: 20, left: 40}, |
|
width = +svg.attr("width") - margin.left - margin.right, |
|
height = +svg.attr("height") - margin.top - margin.bottom, |
|
|
|
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
|
|
|
|
// ---- step 4: create x,y-axis scale-map functions ------------------ |
|
// 1. set n: num of ticks on x-axis |
|
// 2. scaleLinear for x: |
|
// 2.1 set domain: 0 to n-1 |
|
// 2.2 set range: 0 to width |
|
// 3. scaleLinear for y: |
|
// 3.1 set domain: -1 to 1 |
|
// 3.2 set range: height to 0 |
|
|
|
var n = 40; |
|
var x = d3.scaleLinear() |
|
.domain([0, n - 1]) |
|
.range([0, width]); // [0, innerwidth] |
|
var y = d3.scaleLinear() |
|
.domain([-1, 1]) |
|
.range([height, 0]); // upside down for canvas |
|
|
|
|
|
|
|
// ---- step 5: create line ---------------- |
|
// 1. set line function |
|
// 2. set line.x() |
|
var line = d3.line() |
|
// define x values and y values |
|
.x(function(d, i) { return x(i); }) |
|
.y(function(d, i) { return y(d); }); |
|
|
|
|
|
|
|
|
|
|
|
// The <defs> tag is short for definitions and contains definition of special elements (such as gradients). |
|
var rects = g.append("defs") |
|
// Clipping is about hiding what normally would be drawn. The stencil which defines what is and what isn't drawn is called a clipping path |
|
.append("clipPath") |
|
.attr("id", "clip")// add id attr |
|
.append("rect") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
// by now, under inner canvas g, create a tree: defs, clipPath, rect with inner width and height |
|
// console.log(rects); |
|
|
|
// under inner canvas g, create another g for x-axis |
|
g.append("g") |
|
.attr("class", "axis axis--x") |
|
// for y.domain() is [-1,1], range is [height,0] |
|
// y(0) is height/2 |
|
.attr("transform", "translate(0," + y(0) + ")") |
|
.call(d3.axisBottom(x)); |
|
|
|
// under inner canvas g, create another g for y-axis |
|
g.append("g") |
|
.attr("class", "axis axis--y") |
|
.call(d3.axisLeft(y)); |
|
|
|
|
|
|
|
// ---- create data ----------- |
|
// get population mean at 0, deviation at 0.2 |
|
var random = d3.randomNormal(0, .2); |
|
var data = d3.range(n).map(random);// random is a function |
|
|
|
// get array from 0 to 39 |
|
// console.log(d3.range(40)); |
|
// // get 40 random numbers with 0 mean and 0.2 divation |
|
// console.log(data); |
|
|
|
|
|
|
|
// under inner canvas g, create another g with clip-path attr |
|
g.append("g") |
|
.attr("clip-path", "url(#clip)") |
|
// upon which, create a child path |
|
.append("path") |
|
.datum(data) // bind data using .datum |
|
.attr("class", "line") // add class line attr |
|
// do transition upon path above |
|
.transition() |
|
.duration(5000)// last 0.5 second each |
|
.ease(d3.easeLinear)// do linear ease effect |
|
.on("start", tick); |
|
|
|
function tick() { |
|
|
|
// Push a new data point onto the back. |
|
data.push(random()); |
|
|
|
// Redraw the line. |
|
d3.select(this) |
|
.attr("d", line) |
|
.attr("transform", null); |
|
|
|
// Slide it to the left. |
|
d3.active(this) |
|
.attr("transform", "translate(" + x(-1) + ",0)") |
|
.transition() |
|
.on("start", tick); |
|
|
|
// Pop the old data point off the front. |
|
data.shift(); |
|
|
|
} |
|
|
|
</script> |