Reputation: 2437
I want to scale an SVG group element, so that it scales and translates to a point which a path is located on. It means that, when I click on the path, the group has to be scaled and centered to the path in a way that the path fits the height or width of the viewport. I really tried lots of ways, like using getBBox()
to get height, width, x and y of the path and substract them from the viewports offset. I also tried d3.js to manipulate it. But, I couldn't find a good approach.
This is the HTML including SVG:
<div style="width: 700px; height:600px; border:1px solid #d0d0d0; background: #e8e8e8; margin: 0 auto;">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 255.1 170.1" style="enable-background:new 0 0 255.1 170.1;" xml:space="preserve" width="100%" height="100%">
<g id="floorplan">
<path fill="#ED1C24" d="M35.8,51.8h36.3c1.6,0,2.8-1.3,2.8-2.8V22.1c0-1.6-1.3-2.8-2.8-2.8H35.8c-1.6,0-2.8,1.3-2.8,2.8v26.8
C33,50.5,34.3,51.8,35.8,51.8z"/>
<path fill="#4A68B1" d="M209.8,114.3h36.3c1.6,0,2.8-1.3,2.8-2.8V84.6c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
C207,113,208.3,114.3,209.8,114.3z"/>
<path fill="#F8991D" d="M134.3,158.8h36.3c1.6,0,2.8-1.3,2.8-2.8v-26.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
C131.5,157.5,132.8,158.8,134.3,158.8z"/>
<path fill="#ed2590" d="M13.1,124.3h36.3c1.6,0,2.8-1.3,2.8-2.8V94.6c0-1.6-1.3-2.8-2.8-2.8H13.1c-1.6,0-2.8,1.3-2.8,2.8v26.8
C10.2,123,11.5,124.3,13.1,124.3z"/>
<path fill="#356732" d="M161.1,42.5h36.3c1.6,0,2.8-1.3,2.8-2.8V12.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
C158.2,41.2,159.5,42.5,161.1,42.5z"/>
</g>
</svg>
</div>
And this is somehow what I want to have after clicking on the red path:
Upvotes: 3
Views: 1090
Reputation: 4527
Use transform
attribute of a clicked path
element to scale and translate entity. I used a constants for height and width of svg element in the example below, but it helps you to get started.
$("#floorplan path").click(function() {
if ($(this).attr("transform")) {
$(this).removeAttr("transform");
$("#floorplan path:not([transform])").show();
} else {
var objRect = this.getBoundingClientRect();
var svgRect = $("#Layer_1")[0].getBoundingClientRect();
var scaleX = svgRect.width / 255.1;
var scaleY = svgRect.height / 170.1;
var newX = (svgRect.left - objRect.left) / scaleX;
var newY = (svgRect.top - objRect.top) / scaleY;
var xScale = svgRect.width / objRect.width;
var yScale = svgRect.height / objRect.height;
$(this).attr("transform", "matrix(" + xScale + " 0 0 " + yScale + " " + newX * xScale + " " + newY * yScale + ")");
$("#floorplan path:not([transform])").hide();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="width: 700px; height:600px; border:1px solid #d0d0d0; background: #e8e8e8; margin: 0 auto;">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 255.1 170.1" xml:space="preserve">
<g id="floorplan">
<path fill="#ED1C24" d="M35.8,51.8h36.3c1.6,0,2.8-1.3,2.8-2.8V22.1c0-1.6-1.3-2.8-2.8-2.8H35.8c-1.6,0-2.8,1.3-2.8,2.8v26.8
C33,50.5,34.3,51.8,35.8,51.8z"/>
<path fill="#4A68B1" d="M209.8,114.3h36.3c1.6,0,2.8-1.3,2.8-2.8V84.6c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
C207,113,208.3,114.3,209.8,114.3z"/>
<path fill="#F8991D" d="M134.3,158.8h36.3c1.6,0,2.8-1.3,2.8-2.8v-26.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
C131.5,157.5,132.8,158.8,134.3,158.8z"/>
<path fill="#ed2590" d="M13.1,124.3h36.3c1.6,0,2.8-1.3,2.8-2.8V94.6c0-1.6-1.3-2.8-2.8-2.8H13.1c-1.6,0-2.8,1.3-2.8,2.8v26.8
C10.2,123,11.5,124.3,13.1,124.3z"/>
<path fill="#356732" d="M161.1,42.5h36.3c1.6,0,2.8-1.3,2.8-2.8V12.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
C158.2,41.2,159.5,42.5,161.1,42.5z"/>
</g>
</svg>
</div>
You could correct the thansformation matrix to exact match with expected result will be achieved.
Upvotes: 3
Reputation: 108512
@Alexander, beat me to it, but here's a more d3
implementation:
<!DOCTYPE html>
<html>
<head>
<script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div style="width: 700px; height:600px; border:1px solid #d0d0d0; background: #e8e8e8; margin: 0 auto;">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 255.1 170.1" style="enable-background:new 0 0 255.1 170.1;" xml:space="preserve" width="100%" height="100%">
<g id="floorplan">
<path fill="#ED1C24" d="M35.8,51.8h36.3c1.6,0,2.8-1.3,2.8-2.8V22.1c0-1.6-1.3-2.8-2.8-2.8H35.8c-1.6,0-2.8,1.3-2.8,2.8v26.8
C33,50.5,34.3,51.8,35.8,51.8z"></path>
<path fill="#4A68B1" d="M209.8,114.3h36.3c1.6,0,2.8-1.3,2.8-2.8V84.6c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
C207,113,208.3,114.3,209.8,114.3z"></path>
<path fill="#F8991D" d="M134.3,158.8h36.3c1.6,0,2.8-1.3,2.8-2.8v-26.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
C131.5,157.5,132.8,158.8,134.3,158.8z"></path>
<path fill="#ed2590" d="M13.1,124.3h36.3c1.6,0,2.8-1.3,2.8-2.8V94.6c0-1.6-1.3-2.8-2.8-2.8H13.1c-1.6,0-2.8,1.3-2.8,2.8v26.8
C10.2,123,11.5,124.3,13.1,124.3z"></path>
<path fill="#356732" d="M161.1,42.5h36.3c1.6,0,2.8-1.3,2.8-2.8V12.8c0-1.6-1.3-2.8-2.8-2.8h-36.3c-1.6,0-2.8,1.3-2.8,2.8v26.8
C158.2,41.2,159.5,42.5,161.1,42.5z"></path>
</g>
</svg>
</div>
<script>
var svg = d3.select("svg"),
g = svg.select("g");
var v = svg.attr("viewBox").split(" "),
width = v[2],
height = v[3];
svg.on("click", function(d){
g.attr("transform", "translate(" + [0,0] + ")scale(" + 1 + ")");
});
d3.selectAll("path")
.on("click", function() {
var bbox = this.getBBox(),
dx = bbox.width - bbox.x,
dy = bbox.height - bbox.y,
x = (bbox.x + (bbox.x + bbox.width)) / 2,
y = (bbox.y + (bbox.y + bbox.height)) / 2,
scale = Math.min(height / bbox.height, width / bbox.width),
translate = [width / 2 - scale * x, height / 2 - scale * y];
g.attr("transform", "translate(" + translate + ")scale(" + scale + ")");
d3.event.stopPropagation();
});
</script>
</body>
</html>
Upvotes: 5