Reputation: 861
I made a hexagonal grid with an SVG pattern.
To zoom in, I used transform's scale function, and to keep it scaling from the center I set transform-origin
to the center of the page.
This is perfectly working on Chrome but not on Safari and Firefox. How can I make it work on all browsers?
Here's what I made so far:
const pattern = document.getElementById('hexagons');
const center = {
x: window.innerWidth / 2,
y: window.innerHeight / 2
};
const transformOrigin = `${center.x}px ${center.y}px`;
let zoom = 1;
const formatPatternTransform = (zoom) => `rotate(90) scale(${zoom})`;
function animate() {
if (zoom > 3)
return;
zoom += .005;
pattern.setAttribute('patternTransform', formatPatternTransform(zoom));
requestAnimationFrame(animate);
}
pattern.setAttribute('transform-origin', transformOrigin);
animate();
* {
margin: 0;
padding: 0;
}
svg {
background: #0a0a0a;
height: 100vh;
width: 100vw;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
Upvotes: 0
Views: 408
Reputation: 272592
why not simply scaling the whole SVG:
* {
margin: 0;
padding: 0;
}
svg {
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
background: #0a0a0a;
animation:zoom 3s ease-out forwards
}
@keyframes zoom {
to {
transform:scale(3);
}
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
To avoid the lag you can keep you JS code:
let s = document.querySelector('svg');
let zoom = 1;
function animate() {
if (zoom > 3)
return;
zoom += .005;
s.style.transform = "scale(" + zoom + ")";
requestAnimationFrame(animate);
}
animate();
* {
margin: 0;
padding: 0;
}
svg {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #0a0a0a;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
You can easily zoom out too:
let s = document.querySelector('svg');
let zoom = 1;
function animate() {
if (zoom < 0.2)
return;
zoom -= .005;
s.style.transform = "scale(" + zoom + ")";
requestAnimationFrame(animate);
}
animate();
* {
margin: 0;
padding: 0;
}
svg {
position:fixed;
top:-300%;
left:-300%;
width:700%;
height:700%;
background: #0a0a0a;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" width="100%" height="100%" fill="url(#hexagons)" />
</svg>
Upvotes: 2
Reputation: 33024
This is an alternative solution. Instead of using transform-origin
you can center the <rect id="mosaic"
around the origin of the svg canvas. In this case you will need a viewBox attribute: viewBox="-250 -250 500 500"
and preserveAspectRatio="xMidYMid slice"
"xMidYMid (the default) - Force uniform scaling. Align the midpoint X value of the element's viewBox with the midpoint X value of the viewport. Align the midpoint Y value of the element's viewBox with the midpoint Y value of the viewport." "slice - Scale the graphic such that: aspect ratio is preserved the entire viewport is covered by the viewBox the viewBox is scaled down as much as possible, while still meeting the other criteria"
And this is the rectangle filled with the pattern:
<rect id="mosaic" x="-250" y="-250" width="500" height="500" fill="url(#hexagons)" />
Next comes a working example:
const pattern = document.getElementById('hexagons');
const center = {
x: window.innerWidth / 2,
y: window.innerHeight / 2
};
//const transformOrigin = `${center.x}px ${center.y}px`;
let zoom = 1;
const formatPatternTransform = (zoom) => `rotate(90) scale(${zoom})`;
function animate() {
if (zoom > 3)
return;
zoom += .005;
pattern.setAttribute('patternTransform', formatPatternTransform(zoom));
requestAnimationFrame(animate);
}
//pattern.setAttribute('transform-origin', transformOrigin);
animate();
* {
margin: 0;
padding: 0;
}
svg {
background: #0a0a0a;
height: 100vh;
width: 100vw;
}
<svg ref="svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-250 -250 500 500" preserveAspectRatio="xMidYMid slice">
<defs>
<pattern
id="hexagons"
ref="pattern"
width="50"
height="43.4"
patternUnits="userSpaceOnUse"
patternTransform="rotate(90)"
x="50%"
y="50%"
>
<polygon
id="hex"
points="24.8,22 37.3,29.2 37.3,43.7 24.8,50.9 12.3,43.7 12.3,29.2"
fill="#0a0a0a"
stroke="#222"
/>
<use xlink:href="#hex" x="25" />
<use xlink:href="#hex" x="-25" />
<use xlink:href="#hex" x="12.5" y="-21.7" />
<use xlink:href="#hex" x="-12.5" y="-21.7" />
</pattern>
</defs>
<rect id="mosaic" x="-250" y="-250" width="500" height="500" fill="url(#hexagons)" />
</svg>
Upvotes: 2