如何将SVG剪裁路径保持在视口中心

huangapple go评论82阅读模式
英文:

How to keep an SVG clip-path to the center of the viewport

问题

我开始学习网页开发已经有一段时间了,但我遇到了一个问题,我已经困扰了好几个月。

问题是这样的,我有一个SVG路径,它在我的背景div上裁剪(该div包含一个img和一个iframe)。这个形状在每次切换部分时都会变化(共5个部分,五次),使用JS进行形状变换。但我希望这个形状始终居中,因为在某些屏幕上,根据尺寸的不同,它的呈现效果不如预期。

1920x919
1440x900

SVG:

<svg class="morph" viewBox="0 0 '+ viewportWidth +' '+ viewportHeight +'" height="'+ viewportHeight +'px" width="'+ viewportWidth +'px" preserveAspectRatio="xMidYMid meet" xml:space="peserve"><clipPath id="clipMorph"><path id="morphPath" d="M 262.9,252.2 C 210.1,338.2 212.6,487.6 288.8,553.9 372.2,626.5 511.2,517.8 620.3,536.3 750.6,558.4 860.3,723 987.3,686.5 1089,657.3 1168,534.7 1173,429.2 1178,313.7 1096,189.1 995.1,130.7 852.1,47.07 658.8,78.95 498.1,119.2 410.7,141.1 322.6,154.8 262.9,252.2 Z" /></clipPath></svg>

背景div的CSS:

.background {
  height: 100vh;
  width: 100vw;
  position: fixed;
  z-index: 0;
  clip-path: url(#clipMorph);
  -webkit-clip-path: url(#clipMorph);
  background-image: url(../home_mobile.jpg);
  background-size: cover;
}

我尝试过以下方法:

  • 使用preserveAspectRatio,但没有任何效果。

  • 使用clipPathUnits似乎会使形状和背景div消失。

  • 尝试获取边界框以用于平移路径,但该函数总是返回宽度和高度为0的值。

英文:

I started learn web dev some times ago and I came across an issue I've been on for months now.

Here's the thing, I got an svg path that's clipping my background div (which contain an img and an iframe). The shape is morphing every change of sections (5 sections, five time) using JS. But I want the shape to always be centered beacause on some screens depending on the dimensions, it doesn't render like it should.

1920x919
1440x900

The SVG :

&lt;svg class=&quot;morph&quot; viewBox=&quot;0 0 &#39;+ viewportWidth +&#39; &#39;+ viewportHeight +&#39;&quot; height=&quot;&#39;+ viewportHeight +&#39;px&quot; width=&quot;&#39;+ viewportWidth +&#39;px&quot; preserveAspectRatio=&quot;xMidYMid meet&quot; xml:space=&quot;peserve&quot;&gt;&lt;clipPath id=&quot;clipMorph&quot;&gt;&lt;path id=&quot;morphPath&quot; d=&quot;M 262.9,252.2 C 210.1,338.2 212.6,487.6 288.8,553.9 372.2,626.5 511.2,517.8 620.3,536.3 750.6,558.4 860.3,723 987.3,686.5 1089,657.3 1168,534.7 1173,429.2 1178,313.7 1096,189.1 995.1,130.7 852.1,47.07 658.8,78.95 498.1,119.2 410.7,141.1 322.6,154.8 262.9,252.2 Z&quot; /&gt;&lt;/clipPath&gt;&lt;/svg&gt;

Background div CSS :

.background{
height:100vh;
width:100vw;
position:fixed;
z-index:0;
clip-path:url(#clipMorph);
-webkit-clip-path:url(#clipMorph);
background-image:url(../home_mobile.jpg);
background-size:cover}

I tried to :

.preserveAspectRatio but nothing append

.clipPathUnits seems to make shape and background div disappear

.getting the bounding box to manipulate the path with translate but the function always return no width or height for it

{ x: 959.5, y: 459.5, width: 0, height: 0, top: 459.5, right: 959.5, bottom: 459.5, left: 959.5 }

答案1

得分: 0

感谢@StuartNichols的评论。我将解释我的过程,以便那些需要相同结果的人。

我使用SvgPathEditor绘制相对路径中的形状,使用网格(每个形状都居中在一个网格方格中)。

<svg class="morph" viewBox="0 0 1 1" preserveAspectRatio="xMidYMid meet" xml:space="preserve"><clipPath id="clipMorph" clipPathUnits="objectBoundingBox"><path id="morphPath" d="M 262.9,252.2 C 210.1,338.2 212.6,487.6 288.8,553.9 372.2,626.5 511.2,517.8 620.3,536.3 750.6,558.4 860.3,723 987.3,686.5 1089,657.3 1168,534.7 1173,429.2 1178,313.7 1096,189.1 995.1,130.7 852.1,47.07 658.8,78.95 498.1,119.2 410.7,141.1 322.6,154.8 262.9,252.2 Z" /></clipPath></svg>

我保留了视口框的设置为"0 0 1 1",然后重新缩放了clipPath。

var viewportWidth = $(window).width();
var viewportHeight = $(window).height();
var svgClip = document.querySelector('#clipMorph');
var clipScale = (viewportHeight/viewportWidth).toFixed(2);
setAttributes(svgClip, {"transform": "scale("+ clipScale +",1)"});

将视口框设置为"0 0 1 1"意味着您的1x1相对形状将被拉伸(形状的宽度和高度将匹配视口的宽度和高度)。如果视口框设置为"0 0 2 1",则形状的宽度将是视口宽度的1/2。
使用您的SVG容器的比例(在我的情况下是视口)来保持其比例缩放。

然后,我使用以下变量来设置路径本身的X平移(而不是clipPath!)。变换以百分比表示。

var transX = ((1-svgScale)*100)

对于移动设备和平板电脑版本,我需要形状超出视口的宽度,因此我使用了

var transX = ((1-svgScale)*10)

由于svgScale超过1,平移值将为负值。如果这有助于更多人理解clip-path的缩放和位置,请再次感谢@StuartNichols。

英文:

Thanks to @StuartNichols for his comment. I'm gonna explain my process for thoses who would need the same result.

I used SvgPathEditor to draw my shapes in relative path using the grid (each shape being centered in a grid square).

&lt;svg class=&quot;morph&quot; viewBox=&quot;0 0 1 1&quot; preserveAspectRatio=&quot;xMidYMid meet&quot; xml:space=&quot;peserve&quot;&gt;&lt;clipPath id=&quot;clipMorph&quot; clipPathUnits=&quot;objectBoundingBox&quot;&gt;&lt;path id=&quot;morphPath&quot; d=&quot;M 262.9,252.2 C 210.1,338.2 212.6,487.6 288.8,553.9 372.2,626.5 511.2,517.8 620.3,536.3 750.6,558.4 860.3,723 987.3,686.5 1089,657.3 1168,534.7 1173,429.2 1178,313.7 1096,189.1 995.1,130.7 852.1,47.07 658.8,78.95 498.1,119.2 410.7,141.1 322.6,154.8 262.9,252.2 Z&quot; /&gt;&lt;/clipPath&gt;&lt;/svg&gt;

I kept the viewbox to "0 0 1 1" and rescaled the clipPath.

var viewportWidth = $(window).width();
	var viewportHeight = $(window).height();
	var svgClip = document.querySelector(&#39;#clipMorph&#39;);
	var clipScale = (viewportHeight/viewportWidth).toFixed(2);
	setAttributes(svgClip, {&quot;transform&quot;: &quot;scale(&quot;+ clipScale +&quot;,1)&quot;});

Setting the viewbox to "0 0 1 1" meaning your 1x1 relative shape will be stretch (shape width and height will match viewport width and height). If the viewbox was set to "0 0 2 1", your shape width will be 1/2 of the viewbox width.
Use your SVG container's ratio (in my case the viewport) to keep it scaled.

Then I used the following var to set the X translation of the path itself (not the clipPath !). Transformation is expressed in %.

var transX = ((1-svgScale)*100) 

For mobile and pad version I needed the shape exceed the viewport width so I used

var transX = ((1-svgScale)*10)

The svgScale beeing over 1 the translate value will be negative. If it can helps more peoples to understand clip-path scaling and position. Thanks again to @StuartNichols.

huangapple
  • 本文由 发表于 2023年6月19日 22:40:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76507693.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定