如何使用D3库制作响应式画布动画 [英] How to make a responsive canvas animation using the D3 library

查看:835
本文介绍了如何使用D3库制作响应式画布动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用d3.js库开发一个简单的动画,并通过画布显示它,但是我的画布没有反应。



在代码的开头,我将原宽度设置为960,高度设置为500,但是如何使它可以调整大小(响应)?我不使用CSS应用一些样式(宽度和高度)到画布上,我使用JavaScript来做。解决方案可以是CSS或JavaScript。



  var width = 960,height = 500,τ= 2 * Math.PI,gravity = .05; var sample = poissonDiscSampler(width,height,30),nodes = [{x:0,y:0} )nodes.push(s); var force = d3.layout.force().size([width,height]).nodes(nodes.slice()).gravity {return i?-30:-3000;}).on(tick,ticked).start(); var voronoi = d3.geom.voronoi().x(function(d){return dx;})。 var(var)= voronoi.links(nodes); var canvas = d3.select(#canvas) .append(canvas).attr(width,width).attr(height,height).on(ontouchstartin 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  

 < script src =https:// d3js.org/d3.v3.min.js\"</script><section> < div id =canvas> < / div>< / section>  

解决方案

画布就像一个图像。它有自己的物理尺寸,但仍然可以用CSS缩放。使用 width height 属性设置物理尺寸,然后使用CSS将其缩放为<$ c $



示例...



div class =snippetdata-lang =jsdata-hide =falsedata-console =truedata-babel =false>

  var c = document.getElementById(myCanvas); var ctx = c.getContext(2d); ctx.rect ,150,100); ctx.stroke();  

  < canvas id =myCanvaswidth =300height =150style =width:100%;>< / canvas>  div> 


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 d.x;
    })
    .y(function(d) {
        return d.y;
    });

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 = s.x + r * Math.cos(a),
                    y = s.y + 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 = s.x - x,
                        dy = s.y - 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>

这篇关于如何使用D3库制作响应式画布动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆