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>