2016-10-04 13 views
0

d3.jsライブラリを使用して単純なアニメーションを開発し、キャンバスに表示しますが、キャンバスは反応しません。D3ライブラリを使用してレスポンシブなキャンバスアニメーションを作成する方法

コードの冒頭では、元の幅を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 
 
    }], 
 
    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>

+0

あなたはこれを達成するためにCSSやJavaScriptを使用したくないと言っていますか?その最後の文はどういう意味ですか? – HeadCode

+0

@HeadCodeいいえ、jsまたはcssのソリューションがあれば歓迎します –

+0

d3ライブラリはこれを実現します。キャンバスを使用する必要はありません – markE

答えて

1

キャンバス画像のようです。それは独自の物理的な次元を持っていますが、それでもCSSで拡大縮小できます。 widthheightの属性を使用して物理的な寸法を設定し、CSSを使用して%で縮尺を変えて応答します。

例...

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>

+0

この場合の問題は、幅と高さを設定し、すべてのCSSをオーバーライドするjavascriptファイルの原因になります。 –

+0

@coreid - 例で示すように、キャンバスの幅と高さはCSSの幅と高さをオーバーライドしません。彼らは2つの異なるものであり、一緒に使用されることを意図しています。 –

+0

つまり、(キャンバスの幅と高さに関係なく)キャンバスを反応させるために必要なのは、CSSを使用して幅をパーセンテージに設定することだけです。キャンバス自体に 'style = 'width:100%;''を追加するだけで反応的です。 –

関連する問題