22

SVGで正弦波を描く最も簡単な解決策は何でしょうか?JavaScriptを使った単純なループで正弦波を繰り返す必要があると思います...:)

これが良いスタートとしてのXY座標です...:)

http://jsbin.com/adaxuy/1/edit

<svg>
  <line x1="0" y1="250" x2="500" y2="250"
        style="stroke:black;stroke-width:1"/>
  <line x1="250" y1="0" x2="250" y2="500"
        style="stroke:black;stroke-width:1"/>
</svg>
4

7 に答える 7

29

直線近似の代わりに、ベジエ近似があります。1つの期間の第1四半期のかなり良い近似は、次の制御点を持つ3次ベジェ曲線です。

 0   0
1/2 1/2
 1   1
π/2  1

編集: 次のコントロールポイントを使用すると、さらに正確な近似が可能です。

0                    0
0.512286623256592433 0.512286623256592433
1.002313685767898599 1
1.570796326794896619 1

(コメントのNominalAnimalの説明を参照してください)

線要素(灰色)と「良い」ベジェ(赤)および「より良い」ベジェ(緑)を比較するデモ。

スプラインの端点の勾配と曲率を正確に補間する近似は次のとおりです。

       0                0 
(6−(3/2π−3)²)/6  (6−(3/2π−3)²)/6
       1                1
      π/2               1

派生を参照

于 2012-12-18T14:46:37.990 に答える
12

lineSVG 要素に複数の要素を追加する概念実証を次に示します。

var svg = document.getElementById('sine_wave').children[0];
var origin = { //origin of axes
    x: 100,
    y: 100
};
var amplitude = 10; // wave amplitude
var rarity = 1; // point spacing
var freq = 0.1; // angular frequency
var phase = 0; // phase angle

for (var i = -100; i < 1000; i++) {
    var line = document.createElementNS("http://www.w3.org/2000/svg", "line");

    line.setAttribute('x1', (i - 1) * rarity + origin.x);
    line.setAttribute('y1', Math.sin(freq*(i - 1 + phase)) * amplitude + origin.y);

    line.setAttribute('x2', i * rarity + origin.x);
    line.setAttribute('y2', Math.sin(freq*(i + phase)) * amplitude + origin.y);

    line.setAttribute('style', "stroke:black;stroke-width:1");

    svg.appendChild(line);
}
html, body, div{
    height:100%;
}
<div id="sine_wave">

  <svg width="1000" height="1000">
    <line x1="100" y1="0" x2="100" y2="200"
          style="stroke:black;stroke-width:1"/>
    <line x1="0" y1="100" x2="1000" y2="100"
          style="stroke:black;stroke-width:1"/>
  </svg>

</div>

于 2012-12-18T13:13:06.317 に答える
11

以下は、SVGグラフに1サイクルの正弦波を追加します。

const XMAX = 500;
const YMAX = 100;

// Create path instructions
const path = [];
for (let x = 0; x <= XMAX; x++) {
    const angle = (x / XMAX) * Math.PI * 2;  // angle = 0 -> 2π
    const y = Math.sin(angle) * (YMAX / 2) + (YMAX / 2);
    // M = move to, L = line to
    path.push((x == 0 ? 'M' : 'L') + x.toFixed(2) + ',' + y.toFixed(2));
}

// Create PATH element
const pathEl = document.createElementNS("http://www.w3.org/2000/svg", "path");
pathEl.setAttribute('d', path.join(' ') );
pathEl.style.stroke = 'blue';
pathEl.style.fill = 'none';

// Add it to svg element
document.querySelector('svg').appendChild(pathEl);
<svg width="500" height="100"/>

これは、「lineto」(直線)コマンドで構成されるPATH要素を使用します。これが機能するのは、当然のことながら、多くの(500)小さな線分が含まれているためです。ベジェ曲線を使用してセグメントを描画することにより、パスを単純化してポイントを少なくすることができますが、これによりコードが複雑になります。そして、あなたは単純なことを求めました。:)

于 2012-12-18T13:02:51.673 に答える
1

X 軸をループし、反復ごとに、現在の X 値で正弦関数を使用して Y 位置を計算します。

于 2012-12-18T12:53:13.913 に答える