gpt4 book ai didi

javascript - 在 SVG 上使用 skewX 和 skewY 时如何补偿平移

转载 作者:行者123 更新时间:2023-11-29 21:16:34 27 4
gpt4 key购买 nike

上下文:@AnaTudor (@daredevil) is talking about使用 skewXskewY 时 SVG 的 d 移动距离,所以我想知道是否有任何方法可以按顺序计算该距离补偿翻译,并避免使用链式 translate

测试用例:在下面的代码片段中,我们不会使用特定于 SVG 的链接和/或嵌套,我们仅使用相同的变换值,但按照变换函数的特定顺序;

  • LEFT 绿色矩形 通过 style:translaterotateskewXskewY, scale;
  • RIGHT olive rectangle 通过 transform 属性:translatescalerotate , skewX, `skewY.

现在,如您所见,两个矩形的位置不同,如果您单击按钮,第二个矩形会更接近我们的预期,但仍需要针对所有情况进行更多计算。

问题:我们如何更改 fixOrigin 函数来调整所有可能的变换函数组合的翻译,以一种看起来与 CSS3 变换相同的方式?

var el1 = document.querySelectorAll('path')[0],
el2 = document.querySelectorAll('path')[1],
el2BB = el2.getBBox(), el2cx = el2BB.x + el2BB.width/2, el2cy = el2BB.y + el2BB.height/2,
btn = document.querySelectorAll('button')[0], btn1 = document.querySelectorAll('button')[1],
x = 20, y = 20, scale = 0.6, rotate = 45, skewX = 20, skewY = -20;


el1.style.transform = 'translate(20px, 20px) rotate(45deg) skewX(20deg) skewY(-20deg) scale(0.6)';
el1.style.transformOrigin = '50% 50% 0px';

el2.setAttribute('transform', 'translate('+x+','+y+') scale('+scale+') rotate('+rotate+' '+el2cx+','+el2cy+') skewX('+skewX+') skewY('+skewY+')');

function fixOrigin(){
x += (1-scale) * el2BB.width/2;
y += (1-scale) * el2BB.height/2;
el2.setAttribute('transform', 'translate('+x+','+y+') scale('+scale+') rotate('+rotate+' '+el2cx+','+el2cy+') skewX('+skewX+') skewY('+skewY+')');
}
btn.addEventListener('click',fixOrigin,false);

function fixEverything() {
// scale binds all transform functions together
if ( !!scale ) {
//most important make sure we have translation values
//!!(x) && (x=0); !!(y) && (y=0);

// first adjust translate based on scale value
x += (1-scale) * el2BB.width/2;
y += (1-scale) * el2BB.height/2;

//now we also adjust the rotation transform origin based on SKEWS
if (!!rotate) {
// el2cx += .... el2cy += ...
}

//almost there, now we adjust the translation based on SKEWS
// x += ... y += ...

// last case, when SKEWS are used alone
} else if ( !scale && !rotate ) {
// adjust translation here
// x += ... y += ...
}

el2.setAttribute('transform', 'translate(' + x + ',' + y + ') scale(' + scale + ') rotate(' + rotate + ' ' + el2cx + ',' + el2cy + ') skewX(' + skewX + ') skewY(' + skewY + ')');
}

btn1.addEventListener('click', fixEverything, false);
/* desired transform
transform-origin: 50% 50% 0px;
transform: translate(20px, 20px) rotate(45deg) skewX(20deg) skewY(-20deg) scale(0.6);
*/

svg {
overflow: visible; width:30%;
border: 1px solid #eee; /* some sort of ruler */
}
<button>Fix Transform Origin</button><button>Fix All</button><br>
<p>Click to change the `transform` attribute</p>
<svg id="svgMixedCSS" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 500">
<path fill="green" d="M426.671 0h-341.328c-46.937 0-85.343 38.405-85.343 85.345v341.311c0 46.969 38.406 85.344 85.343 85.344h341.328c46.938 0 85.329-38.375 85.329-85.345v-341.31c0-46.94-38.391-85.345-85.329-85.345z" ></path>
</svg>
<svg id="svgMixedAttr" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 500">
<path fill="indigo" d="M426.671 0h-341.328c-46.937 0-85.343 38.405-85.343 85.345v341.311c0 46.969 38.406 85.344 85.343 85.344h341.328c46.938 0 85.329-38.375 85.329-85.345v-341.31c0-46.94-38.391-85.345-85.329-85.345z"></path>
</svg>

我制作了一个超酷的片段供您玩玩。更新:它还有一个包含所有可能情况的功能草案。

最佳答案

由于您目前的核心问题似乎是如何计算 d距离。它来自一个谈话,其中对于 skewX 的情况,倾斜操作基本上被描述为 (x, y) ↦ (x + d, y) .如果你看the SVG spec你会发现一个矩阵,它基本上说明了 skewX(a) 的确切公式是(x, y) ↦ (x + cos(a) y, y) .同样对于 skewY(a)你有(x, y) ↦ (x, y + cos(a) x) .所以我会说 d := cos(a) * y在第一种情况下和 d := cos(a) * x在第二种情况下。

不过,问题标题向我提出了一个不同的问题。该问题可以表述如下:给定 transform="skewX(c) translate(a, b)"对于一些数字 a , bc , 找到 de这样我刚才给出的转换与 translate(d, e) skewX(c) 相同.或者换句话说:我必须如何更改 transform 的条目?如果我想将转换移动到 skewX 的外部.

要找到这些数字,请查看相应的矩阵乘积,如defined in the spec :

⎡1 tan(c) 0⎤ ⎡1 0 a⎤   ⎡1  tan(c)  a + tan(c) b⎤   ⎡1 0 a + tan(c) b⎤ ⎡1 tan(c) 0⎤
⎢0 1 0⎥∙⎢0 1 b⎥ = ⎢0 1 b ⎥ = ⎢0 1 b ⎥∙⎢0 1 0⎥
⎣0 0 1⎦ ⎣0 0 1⎦ ⎣0 0 1 ⎦ ⎣0 0 1 ⎦ ⎣0 0 1⎦

所以你会得到 d = a + tan(c) * be = b .您只需将倾斜变换应用于平移向量。换句话说:

skewX(c) translate(a, b) = translate(a + tan(c) * b, b) skewX(c)

您可以对 y 进行类似的计算并获得:

skewY(c) translate(a, b) = translate(a, b + tan(c) * a) skewY(c)

如果你同时拥有 skewXskewY合并后,您可以移动 translate一次走出一步,这样在每一步你只需要处理一个倾斜方向。如果你想要相反的方向(即移动 translate 更接近倾斜的内部),使用 - tan(c)而不是 + tan(c)在这些公式中。

关于javascript - 在 SVG 上使用 skewX 和 skewY 时如何补偿平移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39191054/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com