Home > Back-end >  d3 svg shadow difference
d3 svg shadow difference

Time:10-30

I make a copy of crypto bubbles where I want the coins to float around like bubbles now I run into the problem that a squares are completely filled and some are not this is because of the shadow? How do I solve this?

import React, { Component } from "react";
import "../styles/style.css";
import $ from "jquery";
import * as d3 from "d3";

const crypto = require("../data/cryptoData.json");
const coins = [];
var data = [];

for (let i = 0; i < crypto.length; i  ) {
  var coin = crypto[i];
  var minplus = String(coin.market_data.price_change_percentage_24h);
  if (minplus.includes("-")) {
    coin["color"] = "red";
  } else {
    coin["color"] = "green";
  }
  coins.push(coin);
}

coins.forEach((coin) => {
  var text = coin.symbol;
  var r = coin.market_data.market_cap.usd / 3500000000;
  if (r < 5) {
    r = 20;
  }
  data.push({
    text: text,
    category: coin.market_data.price_change_percentage_24h   "%",
    image: coin.image.large,
    color: coin.color,
    r: r,
    r_change_1: coin.market_data.market_cap.USD / 3500000000,
    r_change_2: coin.market_data.market_cap.USD / 3500000000,
  });
});

function collide(alpha) {
  var quadtree = d3.geom.quadtree(data);
  return function (d) {
    var r = d.r   10,
      nx1 = d.x - r,
      nx2 = d.x   r,
      ny1 = d.y - r,
      ny2 = d.y   r;
    quadtree.visit(function (quad, x1, y1, x2, y2) {
      if (quad.point && quad.point !== d) {
        var x = d.x - quad.point.x,
          y = d.y - quad.point.y,
          l = Math.sqrt(x * x   y * y),
          r = d.r   quad.point.r;
        if (l < r) {
          l = ((l - r) / l) * (1   alpha);
          d.x -= x *= l;
          d.y -= y *= l;
          quad.point.x  = x;
          quad.point.y  = y;
        }
      }
      return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
    });
  };
}

const bubbleCloud = (element) => {
  var container = d3.select(".bubble-cloud");
  var $container = $(".bubble-cloud");
  var containerWidth = $container.width();
  var containerHeight = $container.height();
  var svgContainer = container
    .append("svg")
    .attr("width", containerWidth)
    .attr("height", containerHeight)
    .call(
      d3.behavior.zoom().on("zoom", function () {
        node.attr(
          "transform",
          "translate("  
            d3.event.translate  
            ")"  
            " scale("  
            d3.event.scale  
            ")"
        );
      })
    );

  // prepare layout
  var force = d3.layout
    .force()
    .size([containerWidth, containerHeight])
    .gravity(0)
    .charge(0)
    .friction(1);
  // load data
  force.nodes(data).start();

  // create item groups
  var node = svgContainer
    .selectAll(".node")
    .data(data)
    .enter()
    .append("g")
    .attr("class", "node")
    .call(force.drag);

  // create circles
  var defs = node.append("defs");

  function makeFiter(id, color) {
    //make a filter if filter id not present
    if (defs.selectAll("#"   id).empty()) {
      var filter = defs.append("filter").attr("id", id).attr("height", "130%");

      filter
        .append("feGaussianBlur")
        .attr("in", "SourceAlpha")
        .attr("stdDeviation", 20)
        .attr("result", "blur");

      filter
        .append("feOffset", 0)
        .attr("in", "blur")
        .attr("result", "offsetBlur");

      filter
        .append("feFlood")
        .attr("in", "offsetBlur")
        .attr("flood-color", color)
        .attr("flood-opacity", "1")

        .attr("result", "offsetColor");

      filter
        .append("feComposite")
        .attr("in", "offsetColor")
        .attr("in2", "offsetBlur")
        .attr("operator", "in")
        .attr("result", "offsetBlur");

      var feMerge = filter.append("feMerge");

      feMerge.append("feMergeNode").attr("in", "offsetBlur");
      feMerge.append("feMergeNode").attr("in", "SourceGraphic");
    }
    return "url(#"   id   ")"; //return the filter id
  }

  function getFilter(d) {
    if (d.color === "red") {
      return makeFiter("fill-text-red", "red");
    } else if (d.color === "green") {
      return makeFiter("fill-text-green", "green");
    }
  }

  defs
    .selectAll(null)
    .data(data)
    .enter()
    .append("pattern")
    .attr("id", function (d) {
      return d.image;
    })
    .attr("height", "100%")
    .attr("width", "100%")
    .attr("patternContentUnits", "objectBoundingBox")
    .append("image")
    .attr("height", 1)
    .attr("width", 1)
    .attr("preserveAspectRatio", "none")
    .attr("xlink:href", function (d) {
      return d.image;
    });

  node
    .append("circle")
    .attr("r", 1e-6)
    .style("fill", function (d) {
      return "url(#"   d.image   ")";
    })
    .attr("filter", function (d) {
      return getFilter(d);
    });

  // create labels
  node
    .append("text")
    .text(function (d) {
      return d.text;
    })
    .classed("text", true)
    .style({
      fill: "#ffffff",
      "text-anchor": "middle",
      "font-size": "1vw",
      "font-weight": "bold",
      "text-transform": "uppercase",
      "font-family": "Tahoma, Arial, sans-serif",
    })
    .attr("stroke", "black")
    .attr("stroke-width", "1px");

  node
    .append("text")
    .text(function (d) {
      return d.category;
    })
    .classed("category", true)
    .style({
      fill: "#ffffff",
      "text-anchor": "middle",
      "font-size": "12px",
      "font-weight": "bold",
      "text-transform": "uppercase",
      "font-family": "Tahoma, Arial, sans-serif",
    })
    .attr("stroke", "black")
    .attr("stroke-width", "1px");

  node
    //.append("line")
    //.classed("line", true)
    //.attr({
    //  x1: 0,
    //  y1: 0,
    //  x2: 0,
    //  y2: 0,
    //})
    .attr("stroke-width", 1)
    .attr("stroke", function (d) {
      return d.stroke;
    });

  // put circle into movement
  force.on("tick", function (e) {
    d3.selectAll("circle")
      .each(collide(0.1))
      .attr("r", function (d) {
        return d.r;
      })
      .attr("cx", function (d) {
        // boundaries
        if (d.x <= d.r) {
          d.x = d.r   1;
        }
        if (d.x >= containerWidth - d.r) {
          d.x = containerWidth - d.r - 1;
        }
        return d.x;
      })
      .attr("cy", function (d) {
        // boundaries
        if (d.y <= d.r) {
          d.y = d.r   1;
        }
        if (d.y >= containerHeight - d.r) {
          d.y = containerHeight - d.r - 1;
        }
        return d.y;
      });

    d3.selectAll("line").attr({
      x1: function (d) {
        return d.x - d.r   10;
      },
      y1: function (d) {
        return d.y;
      },
      x2: function (d) {
        return d.x   d.r - 10;
      },
      y2: function (d) {
        return d.y;
      },
    });

    d3.selectAll(".text")
      .attr("x", function (d) {
        return d.x;
      })
      .attr("y", function (d) {
        return d.y - 10;
      });

    d3.selectAll(".category")
      .attr("x", function (d) {
        return d.x;
      })
      .attr("y", function (d) {
        return d.y   20;
      });
    force.alpha(0.1);
  });
};

class Bubbles extends Component {
  render() {
    return <div className="bubble-cloud" ref={bubbleCloud}></div>;
  }
}
export default Bubbles;

I want it to look like the Ethereum image but have no idea what i have to change... enter image description here

What properties need to be changed?

CodePudding user response:

Use a smaller stdDeviation or enlarge your filter region. Something like this might work:

var filter = defs.append("filter").attr("id", id)
    .attr("height", "300%")
    .attr("width", "300%")
    .attr("x", "-100%")
    .attr("y", "-100%");

An alternative is to express the drop shadows as a % of the box size rather than in absolute units. Something like this:

var filter = defs.append("filter").attr("id", id)
    .attr("primitiveUnits", "objectBoundingBox");

  filter
    .append("feGaussianBlur")
    .attr("in", "SourceAlpha")
    .attr("stdDeviation", "0.1")
    .attr("result", "blur");
  • Related