Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="data.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
console.clear()
const margin = { left: 60, right: 40, top: 0, bottom: 40};
const width = 680;
const height = 630;
var svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
const getTranslation = transform => /translate\((\d*\.?\d*),/.exec(transform)[1];
const xExtent = d3.extent(data, stock => stock.time);
const y1Extent = d3.extent(data, stock => stock.value);
const y2Extent = d3.extent(data, stock => stock.peRatio);
const xScale = d3.scaleTime()
.range([ margin.left, width - margin.right, ])
.domain(xExtent);
const y1Scale = d3.scaleLinear()
.range([ height - margin.bottom, margin.top, ])
.domain([ y1Extent[0] -30, y1Extent[1] + 10,]);
const y2Scale = d3.scaleLinear()
.range([ height - margin.bottom, margin.top, ])
.domain([ 0, y2Extent[1] + 10,]);
const xAxis = svg.append('g')
.attr('transform', `translate(0, ${height - margin.bottom})`)
.call(
d3.axisBottom(xScale)
.tickFormat(d3.timeFormat('%Y'))
.ticks(d3.timeYear.every(2))
);
const xTicks = [];
xAxis.selectAll('.tick').each(function(tick){
xTicks.push(getTranslation(d3.select(this).attr("transform")))
})
if (xTicks[0] > margin.left) xTicks.unshift(margin.left);
const bg = svg.selectAll('rect')
.data(xTicks)
.enter()
.append('g')
bg.append('rect')
.attr('x', d => d)
.attr('width', (d, i) => i < xTicks.length - 1
? xTicks[i + 1] - d
: (width - margin.right) - d
)
.attr('height', height - margin.bottom)
.attr('fill', (d,i) => i%2 > 0
?'white'
:'rgba(178,178,178, 0.05)'
);
bg.append('line')
.attr('x1', d => d)
.attr('x2', d => d)
.attr('y1', 0)
.attr('y2', height - margin.bottom)
.attr('stroke', (d,i) => i > 0 ? 'rgba(178,178,178, 0.15)' : 'none')
const valueArea = d3.area()
.x (d => xScale(d.time))
.y0(d => height - margin.bottom)
.y1(d => y1Scale(d.value));
const peRatioArea = d3.area()
.x (d => xScale(d.time))
.y0(d => height - margin.bottom)
.y1(d => y2Scale(d.peRatio));
const valueLine = d3.line()
.x(d => xScale(d.time))
.y(d => y1Scale(d.value));
const peRatioLine = d3.line()
.x(d => xScale(d.time))
.y(d => y2Scale(d.peRatio));
svg.append('path')
.data([data])
.attr('d', valueArea)
.attr('fill', '#fce1ce')
.attr('opacity', 0.6);
svg.append('path')
.attr('d', valueLine(data))
.attr('stroke', '#fce1ce')
.attr('stroke-width', 3)
.attr('fill', 'none');
svg.append('path')
.attr('d', peRatioLine(data))
.attr('stroke', '#d5d6e9')
.attr('stroke-width', 3)
.attr('fill', 'none');
svg.append('path')
.data([data])
.attr('d', peRatioArea)
.attr('fill', '#d5d6e9')
.attr('opacity', 0.6);
const y1Axis = svg.append('g')
.attr('transform', `translate(${margin.left}, 0)`)
.call(d3.axisLeft(y1Scale));
const y2Axis = svg.append('g')
.attr('transform', `translate(${width - margin.right}, 0)`)
.call(d3.axisRight(y2Scale));
xAxis.select('path').remove();
y1Axis.select('path').remove();
y2Axis.select('path').remove();
xAxis.selectAll('.tick line').attr('stroke', '#b2b2b2');
y1Axis.selectAll('.tick line').attr('stroke', '#b2b2b2');
y2Axis.selectAll('.tick line').attr('stroke', '#b2b2b2');
const poly = [
{ x: margin.left, y: 0, },
{ x: margin.left, y: height - margin.bottom, },
{ x: width - margin.right, y: height - margin.bottom, },
{ x: width - margin.right, y: 0, },
];
svg.append('polygon')
.data([ poly, ])
.attr('stroke', '#b2b2b2')
.attr('stroke-width', 0.5)
.attr('fill', 'none')
.attr('points', points => points.map(point => [ point.x, point.y, ].join(',')).join(' '));
svg.selectAll('text')
.attr('fill', '#5a5a5a')
.attr('stroke', '#5a5a5a')
.attr('stroke-width', 0.5)
.attr('font-size', '17px')
.attr('style', 'font-family: "Open Sans Hebrew","Helvetica Neue",Helvetica,Arial,sans-serif; overflow: visible;');
</script>
</body>
https://d3js.org/d3.v4.min.js