Zodiac 0.9

星座のプログラムを作り変えました。1月の星座ということで、やぎ座です。 今回も Snap.svg を使いました。

実行結果

生成されたコード


ソース


zodiac09.html

Snap.svg ライブラリと JavaScript のソースファイルを指定します。

<script src="js/snap.svg-min.js"></script>
<script src="js/zodiac09.js"></script>

実行結果のところには "Zodiac" という id の svg 要素と "code" という id の pre 要素を用意しました。 中身は zodiac09.js の中で更新、追加しています。

今回の svg 要素でも Adobe Illustrator で作成したやぎの絵をそのまま貼り付けています。 Illustrator のレイヤーが g 要素として出力され、元の絵は左上に位置していて、まだ、 transform 属性が指定されていません。

<h2>実行結果</h2>
<svg id="Zodiac" xmlns="http://www.w3.org/2000/svg" width="640" height="400">
    <rect x="0" y="0" width="640" height="400" style="fill:#111"/>
    <g id="Capricornus">
        <polygon style="fill:#99745F;" points="155.7,232.4 145.7,261.4 181.5,244.9"/>
        <polygon style="fill:#99745F;" points="273.7,275.7 303.1,284.9 285.6,249.5"/>
        <path style="fill:#C3C19D;" d="M248.8,151.9l-46.7-4.5c0.1-1.4,0.4-2.8,0.6-4.2c5-26.2,29.8-43.7,55.1-38.9L248.8,151.9z"/>
        <line style="fill:none;stroke:#C3C19D;stroke-width:16;" x1="291" y1="221.7" x2="225.2" y2="178.6"/>
        <ellipse transform="matrix(0.9987 -5.056244e-02 5.056244e-02 0.9987 -8.4941 8.8209)" style="fill:#C3C19D;" cx="170.1" cy="172.3" rx="87" ry="49.2"/>
        <polygon style="fill:#99745F;" points="228.9,23.6 251.5,104.8 270.7,97.8"/>
        <polygon style="fill:#99745F;" points="265.7,15.8 282.2,98.3 301.9,92.6"/>
        <polygon style="fill:#DDDBB3;" points="302.6,91.7 302.6,190 279.1,190 271.8,174.6 268.3,176.2 274.8,190 249.4,190 249.4,91.7"/>
        <line style="fill:none;stroke:#C3C19D;stroke-width:16;" x1="287.5" y1="215.1" x2="286.1" y2="265.6"/>
        <line style="fill:none;stroke:#C3C19D;stroke-width:16;" x1="231.3" y1="258.7" x2="205.9" y2="181"/>
        <line style="fill:none;stroke:#C3C19D;stroke-width:16;" x1="224.5" y1="252.4" x2="164.9" y2="245.5"/>
        <polygon style="fill:#80B9FF;" points="104,173.2 109.7,78 23.4,119"/>
        <ellipse id="eye1" cx="280.8" cy="129.4" rx="8.5" ry="9.1"/>
        <polygon style="fill:#DDDBB3;" points="224.7,105.7 257,95.2 212.5,74.6"/>
        <polygon style="fill:#DDDBB3;" points="315.6,113 332.2,84.7 284.5,97.6"/>
        <polygon style="fill:#DDDBB3;" points="257.4,230 265.5,186.7 249.8,186.5"/>
        <line style="fill:none;stroke:#000000;stroke-width:4;" x1="273.5" y1="129.4" x2="288.1" y2="129.4"/>
        <polygon style="fill:#80B9FF;" points="138.2,215.4 140.9,240.4 145.4,234.6 150.9,237.1 154,231.1 163.7,233 147.5,212.1"/>
        <polygon style="fill:#354E80;" points="58.6,157.4 117.7,134.8 119.3,214 80.1,204.6"/>
        <path style="fill:#3E5A94;" d="M138.2,209.4c0,30.9-26,56-58.1,56s-58.1-25-58.1-56c0-26.8,19.5-49.2,45.5-54.7l16.6,48.8H84
            c-4.7,0-8.5,4.1-8.5,9.2c0,5,3.8,9.1,8.5,9.1s8.5-4.1,8.5-9.1c0-2.4-0.9-4.6-2.3-6.3l0,0L73,155.6l-0.6-1.7l-0.8-2.3l35.2-16.8
            l19.1,40.2C133.6,184.5,138.2,196.4,138.2,209.4z"/>
        <polygon style="fill:#3E5A94;" points="63.1,105.6 89.9,151.7 87.1,153.2"/>
        <polygon style="fill:#3E5A94;" points="75.7,97.3 93.4,147.6 90.4,148.6"/>
        <polygon style="fill:#3E5A94;" points="48.4,116.3 88.9,150.9 86.9,153.3"/>
        <polygon style="fill:#3E5A94;" points="91.8,93.5 97.6,146.4 94.5,146.8"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="69,207 63.3,219 58.8,206.5 53.7,218.5 50.6,206.1 
            44.4,218.1 41.5,205.7 34.8,217.6 32.3,205.2"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="77.6,222 89.7,227.4 77.3,232.2 89.5,237 77.1,240.4 
            89.2,246.3 76.9,249.6 89,255.9 76.6,258.8"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="70.6,219 74.6,231.7 62.8,225.6 67.3,237.9 56.6,230.9 
            60.2,243.9 49.6,236.8 52.9,250 42.6,242.7"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="93,218.5 98.1,206.2 103.2,218.5 107.7,206.2 
            111.4,218.5 117,206.2 120.6,218.5 126.6,206.2 129.8,218.5"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="94.4,205.9 94.4,192.6 103.9,202 103.3,188.9 
            111.4,198.8 111.9,185.4 119.9,195.3 120.8,181.7 128.4,191.8"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="86.5,221.4 98.9,216.7 93.6,228.9 105.5,223.7 
            99.2,234.8 111.9,230.4 105.5,241.4 118.6,237.4 111.9,248.1"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="81.5,195.2 68.2,195.6 77.3,185.9 64.3,186.8 
            73.9,178.4 60.5,178.3 70.2,170 56.5,169.6 66.4,161.6"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="87.9,189.5 87.9,176.2 97.4,185.6 96.8,172.5 
            104.9,182.5 105.4,169 113.4,178.9 114.3,165.3 121.9,175.4"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="79.7,170 79.7,156.7 89.1,166.1 88.6,153 96.7,162.9 
            97.1,149.4 105.1,159.4 106,145.8 113.6,155.9"/>
        <polyline style="fill:none;stroke:#2E436E;stroke-miterlimit:10;" points="72.7,199.6 60.7,205.4 65.1,192.8 53.5,199 59,187.4 
            46.6,192.8 52.1,181.3 39.4,186.4 45.2,175.1"/>
    </g>
</svg>
<h3>生成されたコード</h3>
<ul>
	<li>3行目:transform 属性を使い、下記の zodiac09.html のソース(やぎ)より位置を移動しています。</li>
    <li>51行~:Snap.svg ライブラリで追加した星座の SVG です。</li>
</ul>
<pre id="code" class="brush: xml; class-name: 'code'; highlight: [3,51]">
</pre>

zodiac09.js

やぎ座の星座を表示するプログラムです。 元々 HTML に記載されていたやぎの絵を移動し、座標や星座を重ねています。

const width = 640;
const height = 400;
const delay = 3000; // [ms]
const blink = 300;  // [ms]
let s;              // for Snap

/* Initialize stars in Capricornus
 * return star[] - array of stars
 * index: Name
 * RA (Right ascension), Dec (Declination), Mag (Apparent magnitude),
 * FD (Flamsteed designation)
 */
let star = {};
star['δ Cap'] = {ra: '21 47 02.29', dec: '-16 07 35.6', mag: 2.85, fd: 49};
star['β1 Cap'] = {ra: '20 21 00.65', dec: '-14 46 53.0', mag: 3.05, fd: 9};
star['α2 Cap'] = {ra: '20 18 03.22', dec: '-12 32 41.5', mag: 3.58, fd: 6};
star['γ Cap'] = {ra: '21 40 05.34', dec: '-16 39 44.1', mag: 3.69, fd: 40};
star['ζ Cap'] = {ra: '21 26 40.03', dec: '-22 24 41.0', mag: 3.77, fd: 34};
star['θ Cap'] = {ra: '21 05 56.78', dec: '-17 13 57.8', mag: 4.08, fd: 23};
star['ω Cap'] = {ra: '20 51 49.30', dec: '-26 55 08.9', mag: 4.12, fd: 18};
star['ψ Cap'] = {ra: '20 46 05.77', dec: '-25 16 13.9', mag: 4.13, fd: 16};
star['ι Cap'] = {ra: '21 22 14.78', dec: '-16 50 04.4', mag: 4.27, fd: 32};
star['α1 Cap'] = {ra: '20 17 38.86', dec: '-12 30 29.6', mag: 4.30, fd: 5};
star['24 Cap'] = {ra: '21 07 07.69', dec: '-25 00 20.7', mag: 4.49, fd: 24};
star['36 Cap'] = {ra: '21 28 43.32', dec: '-21 48 25.8', mag: 4.50, fd: 36};
star['ε Cap'] = {ra: '21 37 04.82', dec: '-19 27 57.6', mag: 4.51, fd: 39};
star['κ Cap'] = {ra: '21 42 39.42', dec: '-18 51 58.7', mag: 4.72, fd: 43};
star['ν Cap'] = {ra: '20 20 39.81', dec: '-12 45 32.6', mag: 4.77, fd: 8};
star['ρ Cap'] = {ra: '20 28 51.62', dec: '-17 48 49.2', mag: 4.77, fd: 11};
star['η Cap'] = {ra: '21 04 24.32', dec: '-19 51 17.8', mag: 4.82, fd: 22};
star['μ Cap'] = {ra: '21 53 17.58', dec: '-13 33 06.5', mag: 5.07, fd: 51};
star['π Cap'] = {ra: '20 27 19.20', dec: '-18 12 42.1', mag: 5.08, fd: 10};
star['46 Cap'] = {ra: '21 45 00.25', dec: '-09 04 56.7', mag: 5.10, fd: 46};
star['υ Cap'] = {ra: '20 40 02.96', dec: '-18 08 19.0', mag: 5.15, fd: 15};
star['42 Cap'] = {ra: '21 41 32.93', dec: '-14 02 48.7', mag: 5.16, fd: 42};
star['φ Cap'] = {ra: '21 15 37.89', dec: '-20 39 06.1', mag: 5.17, fd: 28};
star['τ2 Cap'] = {ra: '20 39 16.32', dec: '-14 57 17.0', mag: 5.24, fd: 14};
star['41 Cap'] = {ra: '21 42 00.64', dec: '-23 15 45.5', mag: 5.24, fd: 41};
star['σ Cap'] = {ra: '20 19 23.60', dec: '-19 07 06.6', mag: 5.28, fd: 7};
star['χ Cap'] = {ra: '21 08 33.61', dec: '-21 11 36.7', mag: 5.30, fd: 25};
star['29 Cap'] = {ra: '21 15 44.83', dec: '-15 10 17.4', mag: 5.31, fd: 29};
star['33 Cap'] = {ra: '21 24 09.60', dec: '-20 51 05.6', mag: 5.38, fd: 33};
star['30 Cap'] = {ra: '21 17 57.28', dec: '-17 59 06.5', mag: 5.40, fd: 30};
star['λ Cap'] = {ra: '21 46 32.08', dec: '-11 21 57.4', mag: 5.57, fd: 48};
star['37 Cap'] = {ra: '21 34 51.07', dec: '-20 05 03.8', mag: 5.70, fd: 37};
star['19 Cap'] = {ra: '20 54 47.85', dec: '-17 55 22.3', mag: 5.78, fd: 19};
star['35 Cap'] = {ra: '21 27 14.83', dec: '-21 11 46.1', mag: 5.78, fd: 35};
star['ξ2 Cap'] = {ra: '20 12 25.76', dec: '-12 37 01.3', mag: 5.84, fd: 2};
star['4 Cap'] = {ra: '20 18 01.38', dec: '-21 48 35.6', mag: 5.86, fd: 4};
star['44 Cap'] = {ra: '21 43 04.40', dec: '-14 23 59.1', mag: 5.88, fd: 44};
star['17 Cap'] = {ra: '20 46 09.97', dec: '-21 30 50.4', mag: 5.91, fd: 17};
star['ο Cap B'] = {ra: '20 29 52.58', dec: '-18 35 10.2', mag: 6.74, fd: 12};
star['45 Cap'] = {ra: '21 44 00.98', dec: '-14 44 57.8', mag: 5.96, fd: 45};
star['47 Cap'] = {ra: '21 46 16.26', dec: '-09 16 33.4', mag: 6.00, fd: 47};
star['21 Cap'] = {ra: '21 00 51.78', dec: '-17 31 51.1', mag: 6.07, fd: 21};
star['27 Cap'] = {ra: '21 09 32.93', dec: '-20 33 22.8', mag: 6.25, fd: 27};
star['20 Cap'] = {ra: '20 59 36.13', dec: '-19 02 06.8', mag: 6.26, fd: 20};
star['3 Cap'] = {ra: '20 16 22.80', dec: '-12 20 13.5', mag: 6.30, fd: 3};
star['ξ1 Cap'] = {ra: '20 11 57.90', dec: '-12 23 32.5', mag: 6.34, fd: 1};
star['τ1 Cap'] = {ra: '20 37 21.16', dec: '-15 08 50.0', mag: 6.76, fd: 13};
star['50 Cap'] = {ra: '21 46 42.09', dec: '-11 41 52.2', mag: 7.01, fd: 50};
star['31 Cap'] = {ra: '21 18 15.64', dec: '-17 27 44.2', mag: 7.07, fd: 31};
let edge = [['α2 Cap', 'β1 Cap'], ['β1 Cap', 'ψ Cap'], ['ψ Cap', 'ω Cap'], ['ω Cap', 'ζ Cap'], ['ζ Cap', 'δ Cap'], ['δ Cap', 'γ Cap'], ['γ Cap', 'ι Cap'], ['ι Cap', 'θ Cap'], ['θ Cap', 'β1 Cap']];
let offsetX, offsetY;
let wrap = false;
let decMin, decMax;
let raMin = 0;
let raMax;
let xMin, xMax;
let yMin, yMax;
let eye = [];
const nEyes = 1;

/**
 * closeEyes function
 * @since 0.3
 */
const closeEyes = function() {
    for (i = 1; i <= nEyes; i++) {
        eye[i] = Snap.select('#eye' + i);
        eye[i].attr({opacity: 0.1});
    }
    setTimeout(openEyes, blink);
}

/**
 * openEyes function
 * @since 0.3
 */
const openEyes = function() {
    for (i = 1; i <= nEyes; i++) {
        eye[i] = Snap.select('#eye' + i);
        eye[i].attr({opacity: 1.0});
    }
}

/**
 * drawGrids function
 * @since 0.1
 */
const drawGrids = function() {
    dec = 0;
    y1 = 0;
    y2 = height;
    for (ra = raMin; ra <= raMax; ra++) {
        xy = raDec2xy(String(ra), String(dec));
        s.line(xy[0], y1, xy[0], y2).attr({stroke: 'dimgray', strokeWidth: 1});
        raTxt = ra;
        if (wrap & (raTxt < 0)) {
            raTxt += 24;
        }
        s.text(xy[0], 5 + 12, raTxt + 'h').attr({fill: 'dimgray', 'font-size': 12});
    }
    x1 = 0;
    x2 = width;
    for (dec = decMin; dec <= decMax + 10; dec += 10) {
        if (dec > 0) {
            strDec = '+' + dec;
        } else {
            strDec = String(dec);
        }
        xy = raDec2xy(String(ra), strDec);
        s.line(x1, xy[1], x2, xy[1]).attr({stroke: 'dimgray', strokeWidth: 1});
        s.text(x1, xy[1] + 12, strDec).attr({fill: 'dimgray', 'font-size': 12});
    }
}

/**
 * getMinMax function - Get minimum and maximum coordinates
 * @since 0.1
 * return decMin - minimum declination
 * return decMax - maximum declination
 * return raMin - minimum right ascension
 * return raMax - maximum right ascension
 * return xMin - minimum x coordinate
 * return xMax - maximum x coordinate
 * return yMin - minimum y coordinate
 * return yMax - maximum y coordinate
 */
const getMinMax = function() {
    first = true;
    Object.keys(star).forEach(function(key) {
        ra = star[key].ra;
        dec = star[key].dec;
        xy = raDec2xy(ra, dec);
        ra1 = Number(ra.substring(0, 2));
        if (wrap & (12 < ra1)) {
            ra1 -= 24;
        }
        if (first) {
            raMin = ra1;
            decMin = Number(dec.substring(0, 3));
            raMax = ra1;
            decMax = Number(dec.substring(0, 3));
            xMin = xy[0];
            yMin = xy[1];
            xMax = xy[0];
            yMax = xy[1];
            first = false;
        } else {
            raMin = Math.min(ra1, raMin);
            decMin = Math.min(dec.substring(0, 3), decMin);
            raMax = Math.max(ra1, raMax);
            decMax = Math.max(dec.substring(0, 3), decMax);
            xMin = Math.min(xy[0], xMin);
            yMin = Math.min(xy[1], yMin);
            xMax = Math.max(xy[0], xMax);
            yMax = Math.max(xy[1], yMax);
        }
    });
    decMin = Math.floor(decMin / 10) * 10;
    raMax = raMax + 1;
    decMax = decMax + 1;
}

/**
 * raDec2xy function - Convert ra, dec to x, y
 * @since 0.1
 * @param ra - right ascension
 * @param dec - declination
 * @return [x, y] - coordinates in graphics window
 */
const raDec2xy = function(ra, dec) {
    let x = Number(ra.substring(0, 2));
    if (wrap & (12 < x)) {
      x -= 24;
    }
    x = x + ra.substring(3, 5) / 60.;
    x = x + ra.substring(6, 11) / 3600.;
    x = offsetX - (x - raMin) * 3600. / 24.;
    let y = Number(dec.substring(1, 3));
    y = y + dec.substring(4, 6) / 60.;
    y = y + dec.substring(7, 12) / 3600.;
    y = y * (dec.substring(0, 1) + '1');
    y = offsetY - y * 3600. / 360.;
    return [x, y];
}

/**
 * onload function
 * @since 0.3
 */
window.onload = function() {
    // Get svg element
    s = Snap('#Zodiac');
    // Move g elements
    let dx = 130, dy = 50;
    let g = Snap.select('#Capricornus');
    g.transform('tlanslate(' + dx + ',' + dy + ')');
    // Get parameters from the zodiac
    offsetX = 0;
    offsetY = 0;
    getMinMax();
    offsetX = -xMin - 2800;
    offsetY = -yMin + 120;
    drawGrids();
    // Draw edges in the zodiac
    for (i = 0; i < edge.length; i++) {
        e = edge[i];
        ra = star[e[0]].ra;
        dec = star[e[0]].dec;
        xy = raDec2xy(ra, dec);
        x1 = xy[0];
        y1 = xy[1];
        ra = star[e[1]].ra;
        dec = star[e[1]].dec;
        xy = raDec2xy(ra, dec);
        x2 = xy[0];
        y2 = xy[1];
        //<line x1="" y1="" x2="" y2="" stroke="darkgray"/>
        s.line(x1, y1, x2, y2).attr({stroke: 'darkgray', strokeWidth: 1});
    }
    // Draw stars in the zodiac
    Object.keys(star).forEach(function(key) {
        ra = star[key].ra;
        dec = star[key].dec;
        xy = raDec2xy(ra, dec);
        cx = xy[0];
        cy = xy[1];
        mag = star[key].mag;
        r = 6 / mag;
        //<ellipse cx="" cy="" rx="" ry="" fill="white"/>
        s.ellipse(cx, cy, r, r).attr({fill: 'white'});
    });
    //<text transform="matrix(1 0 0 1 480 240)" style="font-family: 'Curlz MT'; font-size: 32px;">Capricornus</text>
    s.text(480, 240 + 32, 'Capricornus').attr({fill: 'white', 'font-family': 'Curlz MT', 'font-size': 32});
    //<text transform="matrix(1 0 0 1 510 260)" style="font-family: 'Segoe UI Symbol'; font-size: 96px;">♑</text>
    s.text(510, 260 + 96, '♑').attr({fill: 'white', 'font-family': 'Segoe UI Symbol', 'font-size': 96});
    // Get generated SVG code
    let svgText = s.toString();
    // Show the code with additional new lines
    let codeNode = document.getElementById('code');
    codeNode.textContent = svgText.replace(/><([^/])/g, '>\n<$1');
    setInterval(closeEyes, delay);
}

参考文献

このプログラムは以下の情報またはソフトウェアを参照しています。