2 votes

Mise à jour d'un clip-path dans d3.js ?

Dans mon récent projet, je souhaite créer un chemin de clips qui se déplace avec mon déplacement de souris. Mon idée initiale était simplement de sélectionner et de repositionner l'ellipse avec ses attributs cx et cy en utilisant les coordonnées du déplacement de la souris, puis en sélectionnant le rectangle et en réinitialisant ses coordonnées. clip-path attribut.

Toutefois, cela ne semble pas fonctionner. La seule solution viable que j'ai trouvée jusqu'à présent consiste à supprimer le rectangle et le chemin du clip, puis à les réinitialiser aux nouvelles coordonnées. Cela fonctionne bien pour le cas-test simple ci-dessous, mais dans mon expérience réelle, l'objet que j'essaierai de clipper est un svg chargé en externe, et le fait de devoir le recharger à chaque passage de la souris pourrait s'avérer trop coûteux.

Avez-vous des suggestions sur la façon d'obtenir le même effet que celui que j'ai montré ci-dessous sans tout réinitialiser ?

<!DOCTYPE html>
<html>

  <head>
    <script src="https://unpkg.com/mathjs/lib/browser/math.js"></script>
    <script src="https://d3js.org/d3.v4.min.js"></script>

    <style>

    </style>
  </head>

<!-- Create a div where the graph will take place -->
<div id="my_datavisualization">
  <svg id="click" xmlns="http://www.w3.org/2000/svg">
      <defs>
          <g id="pointer" transform="scale(0.5)">
              <circle cx="0" cy="0" r="20" id="dragcircle" />
          </g>
      </defs>
  </svg>
</div>

  <body style='overflow:hidden'>

    <script>

        // Get the viewport height and width
      const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
      const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)

      // Fit to viewport
      var height            = vw*0.7;
      var width             = vw;

      // Create the canvas. We will use only part of it for the main plot
      var svg = d3.select("#click") // This selects the div
          .attr("width", width) // This defines the canvas' width
          .attr("height", height) // This defines the canvas' height

      // define the clipPath
      svg.append("clipPath")       // define a clip path
          .attr("id", "ellipse-clip") // give the clipPath an ID
        .append("ellipse")          // shape it as an ellipse
          .attr("cx", 175)         // position the x-centre
          .attr("cy", 100)         // position the y-centre
          .attr("rx", 100)         // set the x radius
          .attr("ry", 50);         // set the y radius

      // draw clipped path on the screen
      svg.append("rect")        // attach a rectangle
          .attr("id","cliprect")
          .attr("x", 125)        // position the left of the rectangle
          .attr("y", 75)         // position the top of the rectangle
          .attr("clip-path", "url(#ellipse-clip)") // clip the rectangle
          .style("fill", "lightgrey")   // fill the clipped path with grey
          .attr("height", 100)    // set the height
          .attr("width", 200);    // set the width

      // Shift the marker around on mouseover; restrict it to the contour
      var movex
      var movey

      svg
        .on("mousemove", function () {

            // Get the current mouseover coordinates
            movex = d3.event.x;
            movey = d3.event.y;

          // The only way I get this to work right now is by removing the previous clipped shape, then re-adding it
          d3.select("#cliprect").remove()
          d3.select("#ellipse-clip").remove()

          // define the clipPath
          svg.append("clipPath")       // define a clip path
              .attr("id", "ellipse-clip") // give the clipPath an ID
            .append("ellipse")          // shape it as an ellipse
              .attr("cx", movex)         // position the x-centre
              .attr("cy", movey)         // position the y-centre
              .attr("rx", 100)         // set the x radius
              .attr("ry", 50);         // set the y radius

          // draw clipped path on the screen
          svg.append("rect")        // attach a rectangle
              .attr("id","cliprect")
              .attr("x", 125)        // position the left of the rectangle
              .attr("y", 75)         // position the top of the rectangle
              .attr("clip-path", "url(#ellipse-clip)") // clip the rectangle
              .style("fill", "lightgrey")   // fill the clipped path with grey
              .attr("height", 100)    // set the height
              .attr("width", 200);    // set the width

          });

    </script>
  </body>

</html>

1voto

SmokeyShakers Points 2075

Utilisez-le à la place de votre callback mousemove

function() {

            // Get the current mouseover coordinates
            movex = d3.event.x;
            movey = d3.event.y;

          // move the clipPath
          d3.select("#ellipse-clip") // selects the clipPath
            .select("ellipse")          // selects the ellipse
              .attr("cx", movex)         // position the x-centre
              .attr("cy", movey)         // position the y-centre

          // move clipped path on the screen
          svg.select("rect")        // attach a rectangle
              .attr("x", movex)        // position the left of the rectangle
              .attr("y", movey)         // position the top of the rectangle

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X