Zodiac 0.3

星座のプログラムを作り変えました。今回は7月の星座ということで、かに座です。 今回も Snap.svg を使いました。カニが瞬きするアニメを追加してみました。

実行結果

生成されたコード


ソース


zodiac03.html

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

<script type="text/javascript" src="js/snap.svg-min.js"></script>
<script type="text/javascript" src="js/zodiac03.js"></script>

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

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

<h2>実行結果</h2>
<svg id="Zodiac" xmlns="http://www.w3.org/2000/svg" width="640" height="400"> <!-- viewBox="0 0 287.664 288.817" -->
<rect x="0" y="0" width="640" height="400" style="fill:#111"/>
<g id="Cancer">
    <ellipse cx="126.966" cy="123.23" rx="62" ry="89" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <circle id="eye1" cx="67.966" cy="98.23" r="9" style="fill: #3d1313; stroke: #000; stroke-width: 2px;"/>
    <circle id="eye2" cx="69.966" cy="144.23" r="9" style="fill: #3d1313; stroke: #000; stroke-width: 2px;"/>
    <rect x="79.851" y="10.323" width="21" height="25" transform="translate(49.242 106.454) rotate(-78)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="101.966" y="19.23" width="20" height="22" transform="translate(43.619 123.925) rotate(-69)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="53.966" y="199.23" width="27" height="20" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <rect x="75.238" y="197.149" width="22" height="17" transform="translate(-98.092 80.146) rotate(-33)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="109.515 6.337 120.705 42.292 133.066 35.719 109.515 6.337" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="135.223 2.54 142.593 39.468 155.573 34.224 135.223 2.54" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="158.611 10.764 160.77 48.359 174.354 44.972 158.611 10.764" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="178.15 23.451 177.024 61.091 190.852 58.901 178.15 23.451" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="103.9 240.152 130.393 213.392 118.787 205.564 103.9 240.152" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="127.9 239.152 154.393 212.392 142.787 204.564 127.9 239.152" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="142.9 241.152 169.393 214.392 157.787 206.564 142.9 241.152" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="161.9 228.152 188.393 201.392 176.787 193.564 161.9 228.152" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="43.051 103.073 75.426 122.306 80.214 109.15 43.051 103.073" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <polygon points="42.064 131.111 78.599 134.31 77.135 120.386 42.064 131.111" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="132.044" y="67.223" width="12" height="31" transform="translate(-11.241 22.613) rotate(-9)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="145.966" y="64.23" width="12" height="31" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <rect x="162.966" y="74.23" width="12" height="31" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <rect x="164.379" y="95.722" width="31" height="12" transform="translate(48.466 261.204) rotate(-80)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="117.405" y="160.726" width="31" height="12" transform="translate(-48.776 278.321) rotate(-83)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="140.966" y="152.23" width="12" height="31" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <rect x="158.035" y="150.225" width="12" height="31" transform="translate(-21.468 24.442) rotate(-8)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="172.044" y="140.223" width="12" height="31" transform="translate(-22.169 29.769) rotate(-9)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="125.153" y="38.193" width="12" height="31" transform="translate(-10.564 53.04) rotate(-22)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="144.044" y="36.223" width="12" height="31" transform="translate(-6.244 24.109) rotate(-9)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="162.966" y="45.23" width="12" height="31" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <rect x="177.966" y="57.23" width="12" height="31" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <rect x="112.362" y="190.719" width="31" height="12" transform="translate(-91.142 280.886) rotate(-78)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="140.966" y="184.23" width="12" height="31" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <rect x="149.405" y="191.726" width="31" height="12" transform="translate(-51.444 337.305) rotate(-83)" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <rect x="174.966" y="171.23" width="12" height="31" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <ellipse cx="130.966" cy="122.23" rx="56" ry="33" style="fill: #661f1f; stroke: #000; stroke-width: 2px;"/>
    <path d="m59.933,57.2c-5.43,5.43-11.16,9.99-16.81,13.53l11.34-43.08L6.893,74.8c-8.21-9.85.11-32.54,19.1-51.54C45.523,3.73,68.953-4.5,78.323,4.87c9.37,9.38,1.14,32.8-18.39,52.33Z" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
    <path d="m43.723,221.73c-12.08,3.93-28.93-14.6-37.63-41.39-8.19-25.19-6.26-48.72,4.05-54.69l25.31,64.79-3.41-56.8c6.9,7.49,13.39,18.93,17.8,32.48,8.7,26.79,5.96,51.69-6.12,55.61Z" style="fill: #661f1f; stroke: #000; stroke-miterlimit: 4; stroke-width: 2px;"/>
</g>
</svg>
<h3>生成されたコード</h3>
<pre id="code" class="brush: xml; class-name: 'code'">
</pre>

zodiac03.js

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

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

/* Initialize stars in Cancer
 * return star[] - array of stars
 * index: Flamsteed designation
 * RA (Right ascension), Dec (Declination), Mag (Apparent magnitude)
 */
var star = {};
star[17] = {name: 'β Cnc', ra: '08 16 30.95', dec: '+09 11 08.4', mag: 3.53};
star[47] = {name: 'δ Cnc', ra: '08 44 41.11', dec: '+18 09 17.5', mag: 3.94};
star[48] = {name: 'ι Cnc A', ra: '08 46 41.83', dec: '+28 45 36.0', mag: 4.03};
star[65] = {name: 'α Cnc', ra: '08 58 29.20', dec: '+11 51 28.0', mag: 4.26};
star[43] = {name: 'γ Cnc', ra: '08 43 17.21', dec: '+21 28 06.9', mag: 4.66};
star[16] = {name: 'ζ Cnc', ra: '08 12 12.71', dec: '+17 38 53.3', mag: 4.67};
star[8] = {name: '8 Cnc', ra: '08 05 04.51', dec: '+13 07 06.1', mag: 5.14};
star[18] = {name: 'χ Cnc', ra: '08 20 03.87', dec: '+27 13 07.0', mag: 5.14};
star[77] = {name: 'ξ Cnc', ra: '09 09 21.53', dec: '+22 02 43.6', mag: 5.16};
star[62] = {name: 'ο1 Cnc', ra: '08 57 14.91', dec: '+15 19 21.8', mag: 5.22};
star[58] = {name: 'ρ2 Cnc', ra: '08 55 39.69', dec: '+27 55 39.2', mag: 5.23};
star[64] = {name: 'σ3 Cnc', ra: '08 59 32.68', dec: '+32 25 07.1', mag: 5.23};
star[76] = {name: 'κ Cnc', ra: '09 07 44.82', dec: '+10 40 05.6', mag: 5.23};
star[10] = {name: 'μ2 Cnc', ra: '08 07 45.84', dec: '+21 34 55.1', mag: 5.30};
star[31] = {name: 'θ Cnc', ra: '08 31 35.77', dec: '+18 05 40.4', mag: 5.33};
star[33] = {name: 'η Cnc', ra: '08 32 42.52', dec: '+20 26 28.6', mag: 5.33};
star[82] = {name: '82 Cnc', ra: '09 15 13.88', dec: '+14 56 29.5', mag: 5.36};
star[57] = {name: '57 Cnc', ra: '08 54 14.70', dec: '+30 34 45.0', mag: 5.40};
star[72] = {name: 'τ Cnc', ra: '09 08 00.07', dec: '+29 39 15.2', mag: 5.42};
star[60] = {name: '60 Cnc', ra: '08 55 55.56', dec: '+11 37 33.8', mag: 5.44};
star[59] = {name: 'σ2 Cnc', ra: '08 56 56.63', dec: '+32 54 38.1', mag: 5.44};
star[69] = {name: 'ν Cnc', ra: '09 02 44.27', dec: '+24 27 10.6', mag: 5.45};
star[27] = {name: '27 Cnc', ra: '08 26 43.95', dec: '+12 39 17.5', mag: 5.56};
star[22] = {name: 'φ1 Cnc', ra: '08 26 27.73', dec: '+27 53 37.9', mag: 5.58};
star[3] = {name: '3 LMi', ra: '08 39 56.35', dec: '+32 43 38.2', mag: 6.71};
star[15] = {name: '15 Cnc', ra: '08 13 08.87', dec: '+29 39 23.7', mag: 5.62};
star[45] = {name: '45 Cnc', ra: '08 43 12.34', dec: '+12 40 51.1', mag: 5.62};
star[49] = {name: '49 Cnc', ra: '08 44 45.04', dec: '+10 04 54.2', mag: 5.63};
star[51] = {name: 'σ1 Cnc', ra: '08 52 34.62', dec: '+32 28 26.8', mag: 5.67};
star[63] = {name: 'ο2 Cnc', ra: '08 57 35.16', dec: '+15 34 52.4', mag: 5.68};
star[30] = {name: 'υ1 Cnc', ra: '08 31 30.57', dec: '+24 04 52.4', mag: 5.71};
star[14] = {name: 'ψ2 Cnc', ra: '08 10 27.23', dec: '+25 30 29.4', mag: 5.73};
star[1] = {name: '1 LMi', ra: '08 38 19.00', dec: '+32 48 07.3', mag: 5.96};
star[2] = {name: '2 LMi', ra: '08 39 31.87', dec: '+32 30 56.2', mag: 6.69};
star[50] = {name: '50 Cnc', ra: '08 46 56.06', dec: '+12 06 36.3', mag: 5.89};
star[66] = {name: '66 Cnc', ra: '09 01 24.13', dec: '+32 15 08.3', mag: 5.89};
star[19] = {name: 'λ Cnc', ra: '08 20 32.15', dec: '+24 01 20.5', mag: 5.92};
star[36] = {name: '36 Cnc', ra: '08 37 05.79', dec: '+09 39 20.1', mag: 5.92};
star[20] = {name: '20 Cnc', ra: '08 23 21.87', dec: '+18 19 56.2', mag: 5.94};
star[29] = {name: '29 Cnc', ra: '08 28 37.35', dec: '+14 12 39.1', mag: 5.94};
star[75] = {name: '75 Cnc', ra: '09 08 47.42', dec: '+26 37 48.0', mag: 5.95};
star[55] = {name: '55 Cnc', ra: '08 52 36.13', dec: '+28 19 53.0', mag: 5.96};
star[9] = {name: 'μ1 Cnc', ra: '08 06 18.40', dec: '+22 38 07.8', mag: 5.97};
star[5] = {name: '5 Cnc', ra: '08 01 30.29', dec: '+16 27 19.2', mag: 5.99};
star[79] = {name: '79 Cnc', ra: '09 10 20.86', dec: '+21 59 47.1', mag: 6.04};
star[28] = {name: '28 Cnc', ra: '08 28 36.80', dec: '+24 08 42.2', mag: 6.05};
star[67] = {name: '67 Cnc', ra: '09 01 48.88', dec: '+27 54 10.0', mag: 6.07};
star[21] = {name: '21 Cnc', ra: '08 23 55.21', dec: '+10 37 55.6', mag: 6.11};
star[25] = {name: '25 Cnc', ra: '08 25 49.99', dec: '+17 02 47.9', mag: 6.11};
star[46] = {name: '46 Cnc', ra: '08 45 21.42', dec: '+30 41 51.9', mag: 6.12};
star[23] = {name: 'φ2 Cnc B', ra: '08 26 47.00', dec: '+26 56 07.0', mag: 6.19};
star[4] = {name: '4 Cnc', ra: '08 01 43.77', dec: '+25 05 22.0', mag: 6.32};
star[12] = {name: '12 Cnc', ra: '08 08 42.44', dec: '+13 38 27.4', mag: 6.25};
star[53] = {name: '53 Cnc', ra: '08 52 28.60', dec: '+28 15 33.0', mag: 6.25};
star[61] = {name: '61 Cnc', ra: '08 57 58.63', dec: '+30 14 01.5', mag: 6.25};
star[41] = {name: 'ε Cnc', ra: '08 40 27.03', dec: '+19 32 41.4', mag: 6.29};
star[32] = {name: 'υ2 Cnc', ra: '08 33 00.14', dec: '+24 05 05.7', mag: 6.35};
star[54] = {name: '54 Cnc', ra: '08 51 01.53', dec: '+15 21 01.7', mag: 6.36};
star[39] = {name: '39 Cnc', ra: '08 40 06.44', dec: '+20 00 28.1', mag: 6.39};
star[13] = {name: 'ψ1 Cnc', ra: '08 10 13.12', dec: '+25 50 40.4', mag: 6.44};
star[34] = {name: '34 Cnc', ra: '08 32 39.87', dec: '+10 03 57.7', mag: 6.48};
star[81] = {name: '81 Cnc', ra: '09 12 17.87', dec: '+14 59 43.6', mag: 6.49};
star[24] = {name: '24 Cnc B', ra: '08 26 40.10', dec: '+24 32 07.0', mag: 7.81};
star[37] = {name: '37 Cnc', ra: '08 38 05.19', dec: '+09 34 28.7', mag: 6.54};
star[35] = {name: '35 Cnc', ra: '08 35 19.47', dec: '+19 35 24.3', mag: 6.55};
star[40] = {name: '40 Cnc', ra: '08 40 11.47', dec: '+19 58 16.2', mag: 6.61};
star[83] = {name: '83 Cnc', ra: '09 18 58.91', dec: '+17 42 20.4', mag: 6.61};
star[38] = {name: '38 Cnc', ra: '08 39 42.68', dec: '+19 46 42.5', mag: 6.66};
star[70] = {name: '70 Cnc', ra: '09 04 09.87', dec: '+27 53 53.9', mag: 6.67};
star[42] = {name: '42 Cnc', ra: '08 40 43.23', dec: '+19 43 09.6', mag: 6.83};
star[7] = {name: '7 Cnc', ra: '08 03 50.48', dec: '+22 04 14.9', mag: 6.84};
star[80] = {name: '80 Cnc', ra: '09 11 56.93', dec: '+18 02 39.0', mag: 6.87};
star[78] = {name: '78 Cnc', ra: '09 09 02.31', dec: '+17 28 10.7', mag: 7.18};
star[52] = {name: '52 Cnc', ra: '08 51 10.83', dec: '+15 59 57.8', mag: 7.38};
star[44] = {name: '44 Cnc', ra: '08 43 08.36', dec: '+18 09 02.0', mag: 8.03};
star[71] = {name: '71 Cnc', ra: '09 05 45.52', dec: '+17 23 24.5', mag: 8.10};
var edge = [[48, 43], [43, 47], [47, 65], [47, 17]];
var offsetX, offsetY;
var wrap = true;
var decMin, decMax;
var raMin = 0;
var raMax;
var xMin, xMax;
var yMin, yMax;
var eye = [];

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

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

/**
 * 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', width: 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', width: 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) {
    var 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.;
    var 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
    var dx = 280, dy = 80;
    var g = Snap.select('#Cancer');
    g.transform('tlanslate(' + dx + ',' + dy + ')');
    // Get parameters from the zodiac
    offsetX = 0;
    offsetY = 0;
    getMinMax();
    offsetX = -xMin - 440;
    offsetY = -yMin + 100;
    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', width: 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 76 240)" class="st0 st1 st2">Cancer</text>
    s.text(76, 240 + 32, 'Cancer').attr({fill: 'white', 'font-family': 'Curlz MT', 'font-size': 32});
    //<text transform="matrix(1 0 0 1 70 270)" class="st0 st3 st4">♋</text>
    s.text(70, 270 + 96, '♋').attr({fill: 'white', 'font-family': 'Segoe UI Symbol', 'font-size': 96});
    // Get generated SVG code
    var svgText = s.toString();
    // Show the code with additional new lines
    var codeNode = document.getElementById('code');
    codeNode.textContent = svgText.replace(/><([^/])/g, '>\n<$1');
    setInterval(closeEyes, delay);
}

参考文献

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