如何在浏览器中扭曲SVG中的路径,以便使用javascript或css将它们扭曲到某个角度?透视扭曲可以在Photoshop,Illustrator等中轻松实现,但是浏览器呢?
这是源路径:
这是转型后的道路:
答案 0 :(得分:27)
这是我的拖拽扭曲提案(share you knowledge, Q&A-style)。
实例位于http://jsfiddle.net/xjHUk/278/,主要代码如下:
(仅输出窗口:http://jsfiddle.net/xjHUk/279/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; }
结果正确地扭曲到透视(两个消失点1)。两点透视计算的原理是here。如果SVG路径数据满足以下要求,则该脚本可以处理它:
Arcs可以标准化,但我还没有发现任何crossbrowser方式。 V和H到L是很容易的任务,你必须得到最后使用的x或y坐标并在L之后添加缺失的坐标。
相同的脚本也可以处理路径中的曲线(曲线来自Times)。以下是完全相同的代码,但路径属性(“d”)不同:
http://jsfiddle.net/xjHUk/277/ function dummy(a) {return a;}
(此代码没有检查无效位置,如上所述。)
以上示例的路径来自Arial和Times的SVG版本。请注意,字体使用Cartesian coordinate system,其中y坐标在向上时会增加。否则SVG使用极坐标系,用于位图图像和css。这意味着在上面的代码中使用SVG字体的路径时,必须垂直翻转路径并缩放到所需的字体大小。 TTF字体(及其SVG对应物)通常具有2048个字符,因此字形的边界框没有缩放2048像素,这在SVG字形路径转换为SVG路径时通常太多。
但是如果你想扭曲其他SVG路径,那么翻转和缩放不必要的。
这是相当长的代码(很多是因为拖动功能),但我认为同样的效果也可以通过一些css-3D-transform-way来实现,但在这样的实现中却没有运气......
为了比较一个非透视扭曲的例子(SVG的主要竞争对手SWF):
http://www.rubenswieringa.com/code/as3/flex/DistortImage/
进一步比较VALID透视计算的一个例子:
http://zehfernando.com/f/TriangleTest.swf
答案 1 :(得分:11)
所选答案已过时。
尽管SVG不支持更改元素的透视图,但可以通过使用CSS3 Transforms实现此目的。
CSS3是一种非常强大的动画对象动画方式。可以使用Javascript实时创建和应用CSS3转换。
对CSS3 Transform有很好的支持,所有最新版本的主流浏览器都支持它。 (IE 8 +,Chrome 31 +,Safari 7.1 +,Opera 26 +,Firefox 34 +,Android浏览器4.1+)。更多信息:http://caniuse.com/#feat=transforms2d
对于某些浏览器版本,您需要使用特定于浏览器的前缀来创建转换。但是,有一个非常简洁的网站,解释了处理这个问题的好方法: http://bl.ocks.org/mbostock/10571478
某些CSS3转换属性为:rotate(angle)
,scale(dimension)
。我知道,它们看起来类似于SVG Transforms rotate(angle)
,scale(x y)
,但最好不要将它们视为相同,因为两者之间存在根本差异,CSS3比SVG变换更强大。此外,CSS3 Transforms有一个你肯定需要查看的属性perspective
。
没有比W3更好的地方找到有关CSS3变换的更多信息:http://www.w3.org/TR/css3-transforms/
这是一段代码:
div {
height: 150px;
width: 150px;
}
.container {
perspective: 500px;
border: 1px solid black;
background: gray;
}
.transformed {
transform: rotateY(50deg);
background: blue;
}

<!doctype html>
<html>
<body>
<div class="container">
<div class="transformed"> Hola! He sido transformado!</div>
</div>
</body>
</html>
&#13;
快乐转型!