michimani.net

要素を環状に配置するための座標を生成する

2018-04-19

Webページを作っている時に、要素を環状に配置したい場面があったので、配置するための座標を生成するスクリプトを作ってみました。

ここで言う 座標 とは web ページ上での座標です。つまり、 画面の左上が (0, 0) 画面左上から 右に 10px 、下に 50px 行った場所は (10, 50) という感じです。

satellites-generator | github

使い方

オブジェクトを生成して、 generateCoordinate() を呼ぶと、各要素の座標を持った配列が得られます。

パラメータは以下。 generateCoordinate(number, radius, base, options = {})

説明
number number 配置する要素の数 6
radius number 中心からの距離 (円の半径) 30
base json 中心の座標 {x: 50, y: 200}

※オプションについては github の README をご覧ください。


var sG = new SatellitesGenerator();

let coordinates = sG.generateCoordinate(6, 30, {x: 50, y:200}, {isReverse: true});

console.log(coordinates);

結果

[
    {
        "x": 50,
        "y": 170
    },
    {
        "x": 24.019237886466847,
        "y": 185
    },
    {
        "x": 24.019237886466836,
        "y": 215
    },
    {
        "x": 49.99999999999999,
        "y": 230
    },
    {
        "x": 75.98076211353316,
        "y": 215
    },
    {
        "x": 75.98076211353316,
        "y": 185
    }
]

あとは、x , y を、各要素の left , top にそれぞれ指定すると、環状に並びます。

関数の中身

三角関数の計算をしているだけです。

generateCoordinate(number, radius, base, option = {}) {
    const coordinates = new Array();

    try {
        const per = 360 / number;
        let start = Math.PI/2;
        if (typeof(option.startPos) != 'undefined') {
            switch (option.startPos) {
                case 'right': start = 0; break;
                case 'left': start = Math.PI; break;
                case 'bottom': start = Math.PI*3/4; break;
            }
        }

        let isReverse = false;
        if (typeof(option.isReverse) != 'undefined' && typeof(option.isReverse) == 'boolean' && option.isReverse == true) {
            isReverse = true;
        }

        for (let i = 0; i < number; i++) {
            let rad = 360 - (per * i);
            if (isReverse) {
                rad = per * i;
            }
            coordinates.push({
                x: base.x + radius * Math.cos(Math.PI*rad/180 + start),
                y: base.y + -1 * radius * Math.sin(Math.PI*rad/180 + start)
            });
        }
    } catch (e) {
        console.error(e);
    } finally {
        return coordinates;
    }
}

comments powered by Disqus