javascriptanimationd3.js

how to resize points in d3.js icosahedron


so i found codepen with the perfect d3 drag rotate animation except that i need points to be smaller. I don't understand how do I customize them? I tried to fix size of points by adding a stroke but nothing seems to be working

I use d3.js v5

https://codepen.io/pr0da/pen/OmzKNq

here is CSS styles:

.point {
  fill: #000;
  stroke: #fff;
}

.edge {
  fill: none;
  stroke: #000;
  stroke-opacity: .4;
}

.face {
  fill: #eee;
  fill-rule: nonzero;
}

and d3 script

/**
 * Resources: 
 * https://bl.ocks.org/ivyywang/7c94cb5a3accd9913263
 * https://bl.ocks.org/mbostock/3055104
 * 
 */


var width = 960, height = 500;
var sens = 0.25;
var velocity = [0.18, 0.06];

var projection = d3.geoOrthographic().scale(240);

var path = d3.geoPath().projection({
  stream: function(out) {
    return {
      point: function(x, y) {
        var p = projection([x, y]);
        out.point(p[0], p[1]);
      },
      lineStart: function() {
        out.lineStart();
      },
      lineEnd: function() {
        out.lineEnd();
      },
      polygonStart: function() {
        out.polygonStart();
      },
      polygonEnd: function() {
        out.polygonEnd();
      }
    };
  }
});

var svg = d3
  .select("#root")
  .append("svg")
  .attr("width", width)
  .attr("height", height);

var face = svg
  .selectAll(".face")
  .data(icosahedron_faces)
  .enter()
  .append("path")
  .attr("class", "face");

const points = icosahedron_points();
console.log(JSON.stringify(points));
var edge = svg.append("path").datum(icosahedron_edges).attr("class", "edge");

var point = svg.append("path").datum({
  type: "MultiPoint", coordinates: points
}).attr("class", "point");

var dragging = false;
var drag = d3.drag()
  .subject(function() { var r = projection.rotate(); return {x: r[0] / sens, y: -r[1] / sens}; })
  .on("start", () => {
    dragging = true;
  })
  .on("end", () => {
    dragging = false;
  })
  .on("drag", function() {
    var rotate = projection.rotate();
    projection.rotate([d3.event.x * sens, -d3.event.y * sens, rotate[2]]);
    refresh();
  });
svg.call(drag);

d3.timer(function(elapsed) {
  if(!dragging) {
    const r = projection.rotate();
    projection.rotate([r[0] + velocity[0], r[1] + velocity[1]]);
    refresh();
  }
});

function refresh() {
  point.attr("d", path);
  edge.attr("d", path);
  face.attr("d", path);
}

function icosahedron_points() {
  var points = [], y = Math.atan2(1, 2) * 180 / Math.PI;
  points.push([0, -90]);
  for (var x = 0; x < 360; x += 36) {
    points.push([x, -y], [(x += 36), y]);
  }
  points.push([0, 90]);
  return points;
}

function icosahedron_edges() {
  var edges = [], y = Math.atan2(1, 2) * 180 / Math.PI;
  for (var x = 0; x < 360; x += 72) {
    edges.push([[x + 0, -90], [x + 0, -y]]);
    edges.push([[x + 0, -y], [x + 72, -y]]);
    edges.push([[x + 36, y], [x - 36, y]]);
    edges.push([[x + 36, y], [x + 0, -y]]);
    edges.push([[x - 36, y], [x + 0, -y]]);
    edges.push([[x + 36, 90], [x + 36, y]]);
  }
  console.log(JSON.stringify(edges));
  return { type: "MultiLineString", coordinates: edges };
}

function icosahedron_faces() {
  var faces = [], y = Math.atan2(1, 2) * 180 / Math.PI;
  for (var x = 0; x < 360; x += 72) {
    faces.push([[[x + 0, -90], [x + 0, -y], [x + 72, -y], [x + 0, -90]]]);
    faces.push([[[x + 0, -y], [x + 72, -y], [x + 36, y], [x + 0, -y]]]);
    faces.push([[[x + 36, y], [x + 0, -y], [x - 36, y], [x + 36, y]]]);
    faces.push([[[x - 36, 90], [x - 36, y], [x + 36, y], [x + 36, 90]]]);
  }
  return faces.map(function(face) {
    return { type: "Polygon", coordinates: face };
  });
  ///
}


Solution

  • Call pointRadius() on the d3.geoPath().

    Example settings the radius to 10:

    var path = d3.geoPath()
      .pointRadius(10)
      .projection({
        stream: function(out) {
          return {
            ...
    

    Reference: https://d3js.org/d3-geo/path#path_pointRadius

    Screenshot: icosahedron with bigger point radius

    Found the solution here: https://stackoverflow.com/a/23109568/7376577