SVG路径的透视变换(四角变形) [英] Perspective transform of SVG paths (four corner distort)

查看:336
本文介绍了SVG路径的透视变换(四角变形)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在浏览器中扭曲SVG中的路径,以便使用可能的javascript或CSS将它们扭曲到某些透视?

How is it possible to distort paths in SVG in browser so that they are distorted to certain perspective using possibly javascript or css? The perspective distort can be made easily in Photoshop, Illustrator etc, but how about browsers?

这是源路径:

>

是转换后的路径:

推荐答案

这是我的拖曳建议(分享您的知识,Q& A风格)。

This is my drag distort proposal (share you knowledge, Q&A-style).

现场示例在 http://jsfiddle.net/xjHUk/209/ 和主代码是这样:

(仅输出窗口: http://jsfiddle.net / xjHUk / 210 / embedded / result /

Live example is in http://jsfiddle.net/xjHUk/209/ and the main code is this:
(only output window: http://jsfiddle.net/xjHUk/210/embedded/result/)


function transferPoint (xI, yI, source, destination)
{
    var ADDING = 0.001; // to avoid dividing by zero

    var xA = source[0].x;
    var yA = source[0].y;

    var xC = source[2].x;
    var yC = source[2].y;

    var xAu = destination[0].x;
    var yAu = destination[0].y;

    var xBu = destination[1].x;
    var yBu = destination[1].y;

    var xCu = destination[2].x;
    var yCu = destination[2].y;

    var xDu = destination[3].x;
    var yDu = destination[3].y;

    // Calcultations
    // if points are the same, have to add a ADDING to avoid dividing by zero
    if (xBu==xCu) xCu+=ADDING;
    if (xAu==xDu) xDu+=ADDING;
    if (xAu==xBu) xBu+=ADDING;
    if (xDu==xCu) xCu+=ADDING;
    var kBC = (yBu-yCu)/(xBu-xCu);
    var kAD = (yAu-yDu)/(xAu-xDu);
    var kAB = (yAu-yBu)/(xAu-xBu);
    var kDC = (yDu-yCu)/(xDu-xCu);

    if (kBC==kAD) kAD+=ADDING;
    var xE = (kBC*xBu - kAD*xAu + yAu - yBu) / (kBC-kAD);
    var yE = kBC*(xE - xBu) + yBu;

    if (kAB==kDC) kDC+=ADDING;
    var xF = (kAB*xBu - kDC*xCu + yCu - yBu) / (kAB-kDC);
    var yF = kAB*(xF - xBu) + yBu;

    if (xE==xF) xF+=ADDING;
    var kEF = (yE-yF) / (xE-xF);

    if (kEF==kAB) kAB+=ADDING;
    var xG = (kEF*xDu - kAB*xAu + yAu - yDu) / (kEF-kAB);
    var yG = kEF*(xG - xDu) + yDu;

    if (kEF==kBC) kBC+=ADDING;
    var xH = (kEF*xDu - kBC*xBu + yBu - yDu) / (kEF-kBC);
    var yH = kEF*(xH - xDu) + yDu;

    var rG = (yC-yI)/(yC-yA);
    var rH = (xI-xA)/(xC-xA);

    var xJ = (xG-xDu)*rG + xDu;
    var yJ = (yG-yDu)*rG + yDu;

    var xK = (xH-xDu)*rH + xDu;
    var yK = (yH-yDu)*rH + yDu;

    if (xF==xJ) xJ+=ADDING;
    if (xE==xK) xK+=ADDING;
    var kJF = (yF-yJ) / (xF-xJ); //23
    var kKE = (yE-yK) / (xE-xK); //12

    var xKE;
    if (kJF==kKE) kKE+=ADDING;
    var xIu = (kJF*xF - kKE*xE + yE - yF) / (kJF-kKE);
    var yIu = kJF * (xIu - xJ) + yJ;

    var b={x:xIu,y:yIu}; 
    b.x=Math.round(b.x);
    b.y=Math.round(b.y);
    return b;
}

结果正确地扭曲到透视图(两个消失点一)。两点透视计算的原理是此处。如果满足以下要求,脚本可以处理SVG路径数据:

The result is distorted correctly to perspective (two vanishing point one). The principle of two point perspective calculation is here. The script can handle SVG path data if it meets the following requirements:


  • 所有坐标都是绝对的(意思是大写字母)。请参见

  • 弧( A)不使用

  • V和H归一化为L

被规范化,但我还没有找到任何交叉浏览器的方式。 V和H到L是容易的任务,你必须得到最后使用的x或y坐标,并添加缺失后L。

Arcs can be normalized, but I have not found any crossbrowser way yet. V and H to L is easy task, you have to get the last used x or y coordinate and add the missing one after L.

同样的脚本也可以处理曲线(曲线来自Times)。以下是完全相同的代码,但路径属性(d)是不同的:

The same script can handle also curves in path (curves are from Times). The following is exactly same code but the path attribute ("d") is different:

http://jsfiddle.net/xjHUk/45/ 函数dummy(a){return a;}
(此代码没有检查无效位置,如上所示)。

http://jsfiddle.net/xjHUk/45/ function dummy(a) {return a;} (This code has no check for invalid positions, like the above).

上述示例的路径来自Arial和Times的SVG版本。请注意,字体使用笛卡尔坐标系,其中y坐标在向上时增加。否则SVG使用极坐标系统,用于位图图像和css。这意味着,当在上面的代码中使用SVG字体的路径时,路径必须垂直翻转并缩放到所需的字体大小。 TTF字体(以及它们的SVG对应项)通常大小为2048,所以字形的边界框没有缩放2048像素,当SVG字形路径转换为SVG路径时,通常太大。

Paths of above examples are got from SVG versions of Arial and Times. Please note that fonts uses Cartesian coordinate system, in which y-coordinate increases when going upwards. Otherwise SVG uses Polar coordinate system, which is used in bitmap images and css. This means that when using paths from SVG fonts in above code, the path have to be flipped vertically and scaled to desired font-size. TTF fonts (and their SVG counterparts) have usually em size 2048, so the bounding box of glyph is without scaling 2048 px, which usually is too much when SVG glyph path is converted to SVG path.

但是如果你想扭曲其他的SVG路径,那么不必要的翻转和缩放。

But if you want to distort other SVG paths, then flipping and scaling in unnecessary.

这是相当长的代码,但我认为同样的效果也可以实现一些css-3D转换方式,但不是运气在这样的实现...

This is fairly long code (much because of drag functionality), but I think that the same effect can be achieved also some css-3D-transform-way, but not luck in such implementation yet...

为了比较一个例子的非透视变形(SVG的主要竞争对手SWF):

http ://www.rubenswieringa.com/code/as3/flex/DistortImage/

For comparison an example of non-perspective distort (SVG's main competitor SWF):
http://www.rubenswieringa.com/code/as3/flex/DistortImage/

另外比较VALID透视计算的一个例子:

http://zehfernando.com/f/TriangleTest.swf

And for additional comparison an example of VALID perspective calculation:
http://zehfernando.com/f/TriangleTest.swf

这篇关于SVG路径的透视变换(四角变形)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆