forked from interwebjill's block: Zoomable Area SVG
which was forked from mbostock's block: Zoomable Area
Zoom is not centered over the mouse cursor.
forked from interwebjill's block: Zoomable Area Canvas with Retina
forked from lorenzopub's block: Zoomable Area Canvas with Retina
xxxxxxxxxx
<style>
/* to prevent browser overscrolling bounce */
html {
overflow: hidden;
}
body {
margin: 0;
}
</style>
<canvas></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script><script>
var targetWidth = 960,
targetHeight = 500;
var canvas = document.querySelector("canvas");
context = canvas.getContext("2d");
var ratio = getHighDPICanvas(canvas),
canvasWidth = targetWidth * ratio,
canvasHeight = targetHeight * ratio;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.style.width = `${targetWidth}px`;
canvas.style.height = `${targetHeight}px`;
var margin = {top: 20, right: 20, bottom: 30, left: 60},
width = canvasWidth - margin.left - margin.right,
height = canvasHeight - margin.top - margin.bottom;
var parseTime = d3.timeParse("%Y/%m/%d %H:%M");
var x = d3.scaleTime()
.range([0, width]);
var x2 = d3.scaleTime() // for zooming
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var area = d3.area()
.x(function(d) { return x(d.date); })
.y0(y(0))
.y1(function(d) { return y(d.value); })
.curve(d3.curveStep)
.context(context);
// axes text variables
context.strokeStyle = "black";
context.font = '10pt sans-serif';
var tickCount = 10,
tickSize = 6,
tickPadding = 3;
d3.csv("TBLkW.csv", function(d) {
d.date = parseTime(d.date);
d.value = +Math.round(d.TBLkW);
return d;
}, function(error, data) {
if (error) throw error;
var xExtent = d3.extent(data, function(d) { return d.date; });
x.domain(xExtent);
x2.domain(x.domain());
y.domain(d3.extent(data, function(d) { return d.value; }));
var xTicks = x.ticks(tickCount),
xTickFormat = x.tickFormat(),
yTicks = y.ticks(tickCount),
yTickFormat = y.tickFormat(tickCount);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
d3.select("canvas").call(zoom);
// d3.select("canvas").call(zoom.transform, d3.zoomIdentity);
context.translate(margin.left, margin.top);
function draw() {
context.clearRect(-margin.left, -margin.top, canvas.width, canvas.height);
xAxis();
yAxis();
context.save();
// clip path
context.beginPath()
context.rect(0, 0, width, height);
context.clip();
context.beginPath();
area(data);
context.fillStyle = 'steelblue';
context.fill();
// restore context without a clip path
context.restore();
}
draw();
function zoomed() {
t = d3.event.transform;
x = t.rescaleX(x2);
draw();
}
function xAxis() {
context.beginPath();
xTicks.forEach(function(d) {
context.moveTo(x(d), height);
context.lineTo(x(d), height + tickSize);
});
context.stroke();
context.beginPath();
context.moveTo(0, height);
context.lineTo(width, height);
context.stroke();
context.textAlign = "center";
context.textBaseline = "top";
xTicks.forEach(function(d) {
context.fillText(xTickFormat(d), x(d), height + tickSize);
});
// context.save();
//
// // clip path
// context.beginPath()
// context.rect(0, height, width, height + tickSize);
// context.lineWidth = 0;
// context.strokeStyle = "none";
// context.stroke();
// context.clip();
//
// context.restore();
}
function yAxis() {
context.beginPath();
yTicks.forEach(function(d) {
context.moveTo(0, y(d));
context.lineTo(-6, y(d));
});
context.stroke();
context.beginPath();
context.moveTo(-tickSize, 0);
context.lineTo(0.5, 0);
context.lineTo(0.5, height);
context.lineTo(-tickSize, height);
context.stroke();
context.textAlign = "right";
context.textBaseline = "middle";
yTicks.forEach(function(d) {
context.fillText(yTickFormat(d), -tickSize - tickPadding, y(d));
});
context.save();
context.rotate(-Math.PI / 2);
context.textAlign = "right";
context.textBaseline = "top";
context.fillText("Power (kW)", -10, 10);
context.restore();
}
});
function getHighDPICanvas(c) {
var devicePixelRatio = window.devicePixelRatio || 1;
var backingStoreRatio = [
c.webkitBackingStorePixelRatio,
c.mozBackingStorePixelRatio,
c.msBackingStorePixelRatio,
c.oBackingStorePixelRatio,
c.backingStorePixelRatio,
1
].reduce(function(a, b) { return a || b });
return devicePixelRatio / backingStoreRatio;
}
</script>
https://d3js.org/d3.v4.min.js