简体   繁体   中英

How to make a responsive canvas animation using the D3 library

I'm developing a simple animation using d3.js library and show it through canvas, but my canvas isn't responsive.

In the beginning of the code, I set original width to 960 and height to 500, but how can I make it resizable (responsive)? I'm not using CSS to apply some style (width and height) to the canvas, I'm using JavaScript to do it. The solution can be CSS or JavaScript.

 var width = 960, height = 500, τ = 2 * Math.PI, gravity = .05; var sample = poissonDiscSampler(width, height, 30), nodes = [{ x: 0, y: 0 }], s; while (s = sample()) nodes.push(s); var force = d3.layout.force() .size([width, height]) .nodes(nodes.slice()) .gravity(0) .charge(function(d, i) { return i ? -30 : -3000; }) .on("tick", ticked) .start(); var voronoi = d3.geom.voronoi() .x(function(d) { return dx; }) .y(function(d) { return dy; }); var root = nodes.shift(); root.fixed = true; var links = voronoi.links(nodes); var canvas = d3.select("#canvas").append("canvas") .attr("width", width) .attr("height", height) .on("ontouchstart" in document ? "touchmove" : "mousemove", moved); var context = canvas.node().getContext("2d"); function moved() { var p1 = d3.mouse(this); root.px = p1[0]; root.py = p1[1]; force.resume(); } function ticked() { force.resume(); for (var i = 0, n = nodes.length; i < n; ++i) { var node = nodes[i]; node.y += (node.cy - node.y) * gravity; node.x += (node.cx - node.x) * gravity; } context.clearRect(0, 0, width, height); context.beginPath(); for (var i = 0, n = links.length; i < n; ++i) { var link = links[i]; context.moveTo(link.source.x, link.source.y); context.lineTo(link.target.x, link.target.y); } context.lineWidth = 1; context.strokeStyle = "#bbb"; context.stroke(); context.beginPath(); for (var i = 0, n = nodes.length; i < n; ++i) { var node = nodes[i]; context.moveTo(node.x, node.y); context.arc(node.x, node.y, 2, 0, τ); } context.lineWidth = 3; context.strokeStyle = "#fff"; context.stroke(); context.fillStyle = "#000"; context.fill(); } // Based on https://www.jasondavies.com/poisson-disc/ function poissonDiscSampler(width, height, radius) { var k = 30, // maximum number of samples before rejection radius2 = radius * radius, R = 3 * radius2, cellSize = radius * Math.SQRT1_2, gridWidth = Math.ceil(width / cellSize), gridHeight = Math.ceil(height / cellSize), grid = new Array(gridWidth * gridHeight), queue = [], queueSize = 0, sampleSize = 0; return function() { if (!sampleSize) return sample(Math.random() * width, Math.random() * height); // Pick a random existing sample and remove it from the queue. while (queueSize) { var i = Math.random() * queueSize | 0, s = queue[i]; // Make a new candidate between [radius, 2 * radius] from the existing sample. for (var j = 0; j < k; ++j) { var a = 2 * Math.PI * Math.random(), r = Math.sqrt(Math.random() * R + radius2), x = sx + r * Math.cos(a), y = sy + r * Math.sin(a); // Reject candidates that are outside the allowed extent, // or closer than 2 * radius to any existing sample. if (0 <= x && x < width && 0 <= y && y < height && far(x, y)) return sample(x, y); } queue[i] = queue[--queueSize]; queue.length = queueSize; } }; function far(x, y) { var i = x / cellSize | 0, j = y / cellSize | 0, i0 = Math.max(i - 2, 0), j0 = Math.max(j - 2, 0), i1 = Math.min(i + 3, gridWidth), j1 = Math.min(j + 3, gridHeight); for (j = j0; j < j1; ++j) { var o = j * gridWidth; for (i = i0; i < i1; ++i) { if (s = grid[o + i]) { var s, dx = sx - x, dy = sy - y; if (dx * dx + dy * dy < radius2) return false; } } } return true; } function sample(x, y) { var s = { x: x, y: y, cx: x, cy: y }; queue.push(s); grid[gridWidth * (y / cellSize | 0) + (x / cellSize | 0)] = s; ++sampleSize; ++queueSize; return s; } } 
 <script src="https://d3js.org/d3.v3.min.js"></script> <section> <div id="canvas"> </div> </section> 

Canvas is like an image. It has it's own physical dimensions but can still be scaled with CSS. Use the width and height attributes to set the physical dimensions and then use CSS to scale it with a % to make it responsive.

Example...

 var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); ctx.rect(20, 20, 150, 100); ctx.stroke(); 
 <canvas id="myCanvas" width="300" height="150" style="width:100%;"></canvas> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM