将 SVG 元素转换为等轴测视图

发布于 2024-10-13 19:51:37 字数 572 浏览 7 评论 0原文

我正在编写一些 JavaScript 代码来渲染标准 2D SVG/Canvas 元素(用 Raphael-JS 绘制)等距 3Dish 视图。

假设我们有两个相邻的矩形。然后我以正确的角度(基本上是 30 度扭曲)重新绘制它们以获得等轴测视图。

alt text

在上图中,我显示了两个相应元素的来源。

我的问题是我不知道如何正确翻译所有单个元素,以便它们正确“平铺”而不是仅仅重叠。

虽然实际上使用图块会让事情变得更容易,因为我可以将任何给定图块的放置基于它之前的图块,但图块在这种情况下不起作用。一切都是动态的,并且比简单的 x/y 平面更加复杂。

这是一些等距图块的图像,如果我对这些对象的方式有任何疑问被放置。

I'm working on some JavaScript code to render standard 2D SVG/Canvas elements (drawn with Raphael-JS) in an isometric 3Dish view.

Say we have two rectangles drawn next to each other. I then have them redrawn at the correct angles (basically a 30 degree twist) for an isometric view.

alt text

(In the image above I've shown the origin for two corresponding elements.)

My problem is I don't know how to properly translate all the individual elements so they "tile" correctly instead of just overlapping.

While actually using tiles would make things easier as I could just base any given tile's placement on the one before it, tiles won't work in this case. Everything is dynamic and will be more complex than simple x/y planes.

Here is an image of some isometric tiles if there's any confusions as to how I want these objects to be placed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

誰ツ都不明白 2024-10-20 19:51:37

您不应将转换应用于单个元素,而应将转换应用于作为集合的源元素。在 Raphael 中,你可以使用类似的东西

var s = paper.set();
s.push(square1, square2);

,现在不需要太多数学就可以进行转换,它应该像这样工作:(

// s.clone(); // if you want to keep originals
s.rotate(45, 0, 0).scale(1, .7).translate(100, 0);

但是,旋转项目的缩放在 RaphaelJS 中似乎被破坏了。)

纯 SVG 示例:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
    viewBox="-200,-500 1000,1000">
    <title>Isometric</title>
       <g id="source"> <!-- group -->
           <circle cx="-50" cy="-50" r="50"/>
           <rect width="100" height="100"/>
           <rect width="100" height="100" x="101"/>
           <rect width="100" height="100" x="50" y="-200"/>
       </g>
       <!-- make copy of group and apply transformations -->
       <use xlink:href="#source" transform="translate(500) scale(1, .7) rotate(-45)"/>
</svg>

You shouldn't apply the transformation to the individual elements, but to the source elements as a collection. In Raphael, you could use something like

var s = paper.set();
s.push(square1, square2);

and now do the transformations without too much math, which is supposed to work like this:

// s.clone(); // if you want to keep originals
s.rotate(45, 0, 0).scale(1, .7).translate(100, 0);

(However, scaling of rotated items seems to be broken in RaphaelJS.)

Plain SVG example:

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
    viewBox="-200,-500 1000,1000">
    <title>Isometric</title>
       <g id="source"> <!-- group -->
           <circle cx="-50" cy="-50" r="50"/>
           <rect width="100" height="100"/>
           <rect width="100" height="100" x="101"/>
           <rect width="100" height="100" x="50" y="-200"/>
       </g>
       <!-- make copy of group and apply transformations -->
       <use xlink:href="#source" transform="translate(500) scale(1, .7) rotate(-45)"/>
</svg>
温暖的光 2024-10-20 19:51:37

使用 Raphel.js 2.0 您可以使用 .transform() 方法并提供旋转 45 度的变换字符串来实现此目的垂直缩放 70%(或任何您想要的音高)。请务必注意旋转和缩放的位置 - 在本例中我使用 0,0。您还会注意到我将 100 向右平移以补偿旋转。

变换字符串也非常适合此用例,因为您可以简单地将投影变换添加到场景中其他对象的变换中,并且它们最终都会出现在正确的位置。

例如(请参阅http://jsfiddle.net/k22yG/):

var paper = Raphael(10, 10, 320, 240),
    set = paper.set();

// Build a set to make it easier to transform them all at once
set.push(
    // Grid of rectangles
    paper.rect(0, 0, 50, 50),
    paper.rect(60, 0, 50, 50),
    paper.rect(0, 60, 50, 50),
    paper.rect(60, 60, 50, 50)
);

// Rotate, then scale, then move (describe in "reverse" order)
set.transform('t100,0s1,0.7,0,0r45,0,0');​

Using Raphel.js 2.0 you can do this using the .transform() method and providing a transform string that rotates 45 degrees and scales vertically 70% (or whatever pitch you want). It's important to pay attention to the position you are rotating and scaling around as well - in this case I'm using 0,0. You will also notice I'm translating 100 over to the right to compensate for the rotation.

Transform strings are also great for this use case because you can simply prepend the projection transformation to the transformation of other objects in the scene and they will all end up in the right place.

For example (see http://jsfiddle.net/k22yG/):

var paper = Raphael(10, 10, 320, 240),
    set = paper.set();

// Build a set to make it easier to transform them all at once
set.push(
    // Grid of rectangles
    paper.rect(0, 0, 50, 50),
    paper.rect(60, 0, 50, 50),
    paper.rect(0, 60, 50, 50),
    paper.rect(60, 60, 50, 50)
);

// Rotate, then scale, then move (describe in "reverse" order)
set.transform('t100,0s1,0.7,0,0r45,0,0');​
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文