39

ブラウザのSVGでパスを歪ませて、JavaScriptまたはcssを使用して特定の視点に歪めるようにするにはどうすればよいですか?PhotoshopやIllustratorなどで遠近法の歪みを簡単に作ることができますが、ブラウザはどうですか?

これはソースパスです:

ここに画像の説明を入力してください

そして、これは変換後のパスです。

ここに画像の説明を入力してください

4

2 に答える 2

36

これは私のドラッグディストーションの提案です(知識を共有し、Q&Aスタイル)。

ライブの例はhttp://jsfiddle.net/xjHUk/278/にあり、メインコードは次のとおりです:(
出力ウィンドウのみ:http://jsfiddle.net/xjHUk/279/embedded/result/

関数transferPoint(xI、yI、ソース、宛先)
{{
    var ADDING = 0.001; //ゼロ除算を回避する

    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;

    //計算
    //ポイントが同じ場合は、ゼロ除算を回避するためにADDINGを追加する必要があります
    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+=追加;
    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};
    bx = Math.round(bx);
    by = Math.round(by);
    bを返す;
}

結果は、遠近法に対して正しく歪められます(2つの消失点1)。2点遠近法計算の原理はここにあります。スクリプトは、次の要件を満たしている場合、SVGパスデータを処理できます。

  • すべての座標は絶対です(大文字を意味します)。これを参照してください。
  • アーク(「A」)は使用されません
  • VとHはLに正規化されます

アークは正規化できますが、クロスブラウザの方法はまだ見つかりません。VおよびHからLは簡単な作業です。最後に使用したxまたはy座標を取得し、Lの後に欠落している座標を追加する必要があります。

同じスクリプトでパス内の曲線も処理できます(曲線はTimesからのものです)。以下はまったく同じコードですが、パス属性( "d")が異なります。

http://jsfiddle.net/xjHUk/277/ function dummy(a) {return a;} (このコードには、上記のように無効な位置のチェックはありません)。

上記の例のパスは、SVGバージョンのArialとTimesから取得されています。フォントはデカルト座標系を使用していることに注意してください。デカルト座標系では、上に行くとy座標が増加します。それ以外の場合、SVGはビットマップ画像とcssで使用される極座標系を使用します。これは、上記のコードでSVGフォントからのパスを使用する場合、パスを垂直方向に反転し、目的のフォントサイズに拡大縮小する必要があることを意味します。TTFフォント(および対応するSVGフォント)のemサイズは通常2048であるため、グリフのバウンディングボックスは2048 pxにスケーリングされません。これは、通常、SVGグリフパスがSVGパスに変換されるときに大きすぎます。

ただし、他のSVGパスを歪めたい場合は、フリップとスケーリングは不要です。

これはかなり長いコードです(ドラッグ機能のため)が、同じ効果がいくつかのcss-3D-transform-wayでも達成できると思いますが、そのような実装ではまだ運がありません...

比較のために、非遠近法による歪みの例(SVGの主な競合SWF):
http ://www.rubenswieringa.com/code/as3/flex/DistortImage/

さらに比較するために、有効なパースペクティブ計算の例:http:
//zehfernando.com/f/TriangleTest.swf

于 2012-10-16T16:36:12.973 に答える
16

選択した回答は古くなっています。

SVGは要素のパースペクティブの変更をサポートしていませんが、CSS3変換を使用してこれを実現することは可能です。

CSS3は、オブジェクトをアニメーション化する非常に強力な方法です。CSS3 Transformは、Javascriptを使用してリアルタイムで作成および適用できます。

CSS3 Transformは適切にサポートされており、最近のすべてのバージョンの主要なブラウザーがCSS3Transformをサポートしています。(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 Transformのプロパティには次のようなものがあります:rotate(angle)scale(dimension)rotate(angle)私は知っています、それらはSVGトランスフォームに非常に似ていますscale(x y)が、CSS3はSVGトランスフォームよりもはるかに強力であり、2つの間に根本的な違いがあるため、それらを同等と見なさないことが最善です。さらに、CSS3 Transformsには、perspective必ず確認する必要のあるプロパティがあります。

W3よりもCSS3トランスフォームに関する詳細情報を見つけるのに最適な場所はありません:http ://www.w3.org/TR/css3-transforms/

コードスニペットは次のとおりです。 CSS3変換の例

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>

幸せな変身!

于 2015-02-08T17:56:33.073 に答える