Skip to content

Instantly share code, notes, and snippets.

@1Cr18Ni9
Last active November 1, 2019 06:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 1Cr18Ni9/4fcf99fc2fa872ddb1991d00459c0e47 to your computer and use it in GitHub Desktop.
Save 1Cr18Ni9/4fcf99fc2fa872ddb1991d00459c0e47 to your computer and use it in GitHub Desktop.
svg & canvas & brush
license: mit

This demo is utilised with svg and canvas and brush features.

DOM structure: div.box > canvas + svg , div is relative positioned and the graphic elements are absolute and the svg is on the top of canvas.

SVG has some performance issues when nodes quantity reach 10k. d3.brush is a good feature but it is not working on canvas. So I put them together.

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.12.0/d3.min.js" integrity="sha256-+9Mf3cAVmxxudDsr1XwXUeRZFtvdWVYdq5/vcgiYyNU=" crossorigin="anonymous"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
canvas, svg {
display: block;
position: absolute;
top: 0;
left: 0;
}
.box {
position: relative;
width: 1100px;
margin: 2em auto;
}
</style>
</head>
<body>
<style>
canvas, svg {
display: block;
position: absolute;
top: 0;
left: 0;
}
.box {
position: relative;
width: 900px;
margin: 2em auto;
}
</style>
<div class="box" id="box"></div>
<script>
var w = 900, h = 450,
p = {top: 20, right: 20, bottom: 40, left: 50},
cw = w - p.left - p.right,
ch = h - p.top - p.bottom;
var data = d3.range(1000)
.map(function (d, i) {
return {
x: Math.random() * cw,
y: Math.random() * ch,
r: Math.random() * 5 + 3
};
});
var point = {x: 0, y: 0},
area = [[0, 0], [0, 0]];
var box = d3.select("#box");
box.on("mousemove", function () {
var t = d3.mouse(this);
point.x = t[0]; point.y = t[1];
})
.on("click", function () { area = [[0, 0], [0, 0]]; });
var canvas = box.append("canvas").attr("width", w).attr("height", h);
var ctx = canvas.node().getContext("2d");
var svg = box.append("svg").attr("width", w).attr("height", h);
function canvasDraw () {
ctx.save();
ctx.clearRect(0, 0, w, h);
ctx.translate(p.left, p.top);
ctx.strokeStyle = "#666";
ctx.fillStyle = "rgba(250,0,0,1)";
ctx.lineWidth = 1;
var i = 0, length = data.length,
c,
hc,
isMouseOver = false,
isFenced = false;
while (i < length) {
c = data[i];
ctx.beginPath();
ctx.arc(c.x, ch - c.y, c.r, 0, Math.PI * 2, false);
isFenced = c.x >= area[0][0] &&
c.x <= area[1][0] &&
(ch - c.y) >= area[0][1] &&
(ch - c.y) <= area[1][1];
isMouseOver = ctx.isPointInPath(point.x, point.y);
if (isFenced) { ctx.fill(); }
if (isMouseOver) { hc = c; }
ctx.stroke();
i++;
}
if (hc) {
ctx.beginPath();
ctx.arc(hc.x, ch - hc.y, hc.r, 0, Math.PI * 2, false);
ctx.fill();
}
ctx.restore();
window.requestAnimationFrame(canvasDraw);
}
function SVGDraw () {
var yScale, xScale, yAxis, xAxis;
yScale = d3.scaleLinear().domain([0, ch]).range([ch, 0]);
xScale = d3.scaleLinear().domain([0, cw]).range([0, cw]);
yAxis = d3.axisLeft().scale(yScale);
xAxis = d3.axisBottom().scale(xScale);
var brush = d3.brush()
.extent([[0, 0], [cw, ch]])
.on("brush", function () { area = d3.event.selection; });
svg.append("g")
.attr("transform", "translate(" + [p.left, p.top] + ")")
.call(yAxis);
svg.append("g")
.attr("transform", "translate(" + [p.left, p.top + ch] + ")")
.call(xAxis);
svg.append("g")
.attr("transform", "translate(" + [p.left, p.top] + ")")
.call(function (g) {
g.call(brush);
// active one brush area
brush.move(g, [[300,100], [500, 250]]);
});
}
SVGDraw();
canvasDraw();
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment