Zodiac 1.2

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

実行結果

生成されたコード


      

ソース


zodiac12.html

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

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

実行結果のところには "Zodiac" という id の svg 要素と "code" という id の pre 要素を用意しました。 中身は zodiac12.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="Aries">
          <rect x="139.385" y="84.088" width="16.999" height="102.995" transform="translate(-15.485 252.049) rotate(-78)" style="fill: #404040; stroke-width: 0px;"/>
          <ellipse cx="110.498" cy="81" rx="49" ry="48" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <ellipse cx="32.496" cy="76.997" rx="32.998" ry="17.999" transform="translate(-15.298 8.439) rotate(-12)" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <ellipse cx="244.498" cy="24" rx="15" ry="16" style="fill: none; stroke: #5e4423; stroke-width: 16px;"/>
          <ellipse cx="234.498" cy="106" rx="49" ry="48" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <polygon points="211.698 163.5 195.398 140.1 186.498 149.6 211.698 163.5" style="fill: #404040; stroke-width: 0px;"/>
          <rect x="120.993" y="29.593" width="97.997" height="126.996" transform="translate(46.175 242.197) rotate(-79)" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <rect x="110.219" y="96.205" width="17" height="102.997" transform="translate(-67.433 183.174) rotate(-61.997)" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <rect x="222.5" y="120.005" width="16" height="70" transform="translate(-12.258 290.007) rotate(-62.999)" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <rect x="191.506" y="164.006" width="70.003" height="16.001" transform="translate(-11.447 16.219) rotate(-4)" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <rect x="244.491" y="113.993" width="16" height="70" transform="translate(65.842 375.074) rotate(-81.002)" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <rect x="237.497" y="171.992" width="70.001" height="16" transform="translate(3.536 365.226) rotate(-68.001)" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <ellipse cx="235.498" cy="63.011" rx="24.999" ry="16" transform="translate(51.565 223.006) rotate(-55.998)" style="fill: #696969; stroke: #000; stroke-miterlimit: 4; stroke-width: 4px;"/>
          <ellipse cx="309.498" cy="51" rx="15" ry="16" style="fill: none; stroke: #5e4423; stroke-width: 16px;"/>
          <polygon points="266.098 84.3 277.498 130.1 302.198 54 266.098 84.3" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <circle cx="267.999" cy="50" r="39" style="fill: #696969; stroke-width: 0px;"/>
          <circle cx="302.498" cy="36.8" r="8" style="fill: #5e4423; stroke-width: 0px;"/>
          <circle id="eye1" cx="264.498" cy="61" r="10" style="fill: #000; stroke-width: 0px;"/>
          <line x1="217.498" y1="75" x2="228.498" y2="71" style="fill: none; stroke: #000; stroke-width: 4px;"/>
          <path d="M306.187,58c-1.1,5.4-3.3,10.4-6.3,14.8h0l-15-22.8,21.3,8Z" style="fill: #5e4423; stroke-width: 0px;"/>
          <polygon points="180.698 184.5 164.398 161.1 155.498 170.6 180.698 184.5" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <polygon points="177.698 191.5 161.398 168.1 152.498 177.6 177.698 191.5" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <polygon points="250.498 231.1 269.698 209.9 258.398 203.4 250.498 231.1" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <polygon points="245.198 226.8 266.098 208.3 253.698 199.9 245.198 226.8" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <polygon points="171.698 168.3 194.798 185.2 200.098 173.3 171.698 168.3" style="fill: #5e5e5e; stroke-width: 0px;"/>
          <polygon points="174.698 161.3 197.798 178.2 203.098 166.3 174.698 161.3" style="fill: #5e5e5e; stroke-width: 0px;"/>
        </g>
      </svg>
      <h3>生成されたコード</h3>
      <ul>
        <li>3行目:transform 属性を使い、下記の zodiac12.html のソース(おひつじ)より位置を移動しています。</li>
        <li>31行~:Snap.svg ライブラリで追加した星座の SVG です。</li>
      </ul>
      <pre id="code" class="brush: xml; class-name: 'code'; highlight: [3,31]">
</pre>

zodiac12.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['α Ari'] = {ra: '02 07 10.29', dec: '+23 27 46.0', mag: 2.01, fd: 13};
star['β Ari'] = {ra: '01 54 38.35', dec: '+20 48 29.9', mag: 2.64, fd: 6};
star['41 Ari'] = {ra: '02 49 58.99', dec: '+27 15 38.8', mag: 3.61, fd: 41};
star['δ Ari'] = {ra: '03 11 37.67', dec: '+19 43 36.1', mag: 4.35, fd: 57};
star['39 Ari'] = {ra: '02 47 54.44', dec: '+29 14 50.7', mag: 4.52, fd: 39};
star['γ1 Ari'] = {ra: '01 53 31.77', dec: '+19 17 38.7', mag: 4.70, fd: 5};
star['35 Ari'] = {ra: '02 43 27.11', dec: '+27 42 25.8', mag: 4.65, fd: 35};
star['λ Ari'] = {ra: '01 57 55.78', dec: '+23 35 45.9', mag: 4.79, fd: 9};
star['ζ Ari'] = {ra: '03 14 54.11', dec: '+21 02 40.7', mag: 4.87, fd: 58};
star['14 Ari'] = {ra: '02 09 25.29', dec: '+25 56 23.9', mag: 4.98, fd: 14};
star['κ Ari'] = {ra: '02 06 33.91', dec: '+22 38 54.3', mag: 5.03, fd: 12};
star['ι Ari'] = {ra: '01 57 21.03', dec: '+17 49 03.3', mag: 5.09, fd: 8};
star['τ2 Ari'] = {ra: '03 22 45.27', dec: '+20 44 31.6', mag: 5.10, fd: 63};
star['38 Ari'] = {ra: '02 44 57.51', dec: '+12 26 45.5', mag: 5.18, fd: 38};
star['ε Ari B'] = {ra: '02 59 12.73', dec: '+21 20 25.6', mag: 5.5, fd: 48};
star['η Ari'] = {ra: '02 12 47.98', dec: '+21 12 39.5', mag: 5.23, fd: 17};
star['π Ari'] = {ra: '02 49 17.56', dec: '+17 27 51.6', mag: 5.26, fd: 42};
star['τ1 Ari'] = {ra: '03 21 13.61', dec: '+21 08 49.7', mag: 5.27, fd: 61};
star['33 Ari'] = {ra: '02 40 41.03', dec: '+27 03 39.6', mag: 5.30, fd: 33};
star['ν Ari'] = {ra: '02 38 49.00', dec: '+21 57 41.2', mag: 5.45, fd: 32};
star['52 Ari B'] = {ra: '03 05 26.70', dec: '+25 15 19.0', mag: 7.00, fd: 52};
star['ξ Ari'] = {ra: '02 24 49.04', dec: '+10 36 38.2', mag: 5.48, fd: 24};
star['64 Ari'] = {ra: '03 24 18.46', dec: '+24 43 27.1', mag: 5.50, fd: 64};
star['σ Ari'] = {ra: '02 51 29.57', dec: '+15 04 55.7', mag: 5.52, fd: 43};
star['62 Ari'] = {ra: '03 22 11.89', dec: '+27 36 27.3', mag: 5.55, fd: 62};
star['21 Ari'] = {ra: '02 15 42.83', dec: '+25 02 35.7', mag: 5.57, fd: 21};
star['θ Ari'] = {ra: '02 18 07.55', dec: '+19 54 04.2', mag: 5.58, fd: 22};
star['ρ3 Ari'] = {ra: '02 56 25.98', dec: '+18 01 25.1', mag: 5.58, fd: 46};
star['10 Ari'] = {ra: '02 03 39.26', dec: '+25 56 07.6', mag: 5.64, fd: 10};
star['31 Ari'] = {ra: '02 36 37.75', dec: '+12 26 52.2', mag: 5.64, fd: 31};
star['15 Ari'] = {ra: '02 10 37.54', dec: '+19 30 01.5', mag: 5.68, fd: 15};
star['19 Ari'] = {ra: '02 13 03.25', dec: '+15 16 47.7', mag: 5.72, fd: 19};
star['μ Ari'] = {ra: '02 42 21.92', dec: '+20 00 41.7', mag: 5.74, fd: 34};
star['55 Ari'] = {ra: '03 09 36.73', dec: '+29 04 37.6', mag: 5.74, fd: 55};
star['7 Ari'] = {ra: '01 55 51.03', dec: '+23 34 38.4', mag: 5.76, fd: 7};
star['ρ2 Ari'] = {ra: '02 55 48.50', dec: '+18 19 54.0', mag: 5.76, fd: 45};
star['ο Ari'] = {ra: '02 44 32.97', dec: '+15 18 42.8', mag: 5.78, fd: 37};
star['56 Ari'] = {ra: '03 12 14.24', dec: '+27 15 25.2', mag: 5.78, fd: 56};
star['20 Ari'] = {ra: '02 15 45.94', dec: '+25 46 59.2', mag: 5.79, fd: 20};
star['47 Ari'] = {ra: '02 58 05.08', dec: '+20 40 07.7', mag: 5.80, fd: 47};
star['1 Ari B'] = {ra: '01 50 08.50', dec: '+22 16 33.0', mag: 5.90, fd: 1};
star['40 Ari'] = {ra: '02 48 32.06', dec: '+18 17 01.9', mag: 5.83, fd: 40};
star['4 Ari'] = {ra: '01 48 10.90', dec: '+16 57 20.3', mag: 5.86, fd: 4};
star['16 Ari'] = {ra: '02 11 12.06', dec: '+25 56 13.0', mag: 6.01, fd: 16};
star['49 Ari'] = {ra: '03 01 54.15', dec: '+26 27 44.4', mag: 5.91, fd: 49};
star['59 Ari'] = {ra: '03 19 55.81', dec: '+27 04 16.7', mag: 5.91, fd: 59};
star['54 Ari'] = {ra: '03 08 21.09', dec: '+18 47 42.3', mag: 6.25, fd: 54};
star['29 Ari'] = {ra: '02 32 54.15', dec: '+15 02 04.1', mag: 6.00, fd: 29};
star['11 Ari'] = {ra: '02 06 49.22', dec: '+25 42 16.5', mag: 6.01, fd: 11};
star['66 Ari'] = {ra: '03 28 26.57', dec: '+22 48 15.4', mag: 6.03, fd: 66};
star['65 Ari'] = {ra: '03 24 26.11', dec: '+20 48 12.6', mag: 6.07, fd: 65};
star['53 Ari'] = {ra: '03 07 25.69', dec: '+17 52 47.9', mag: 6.13, fd: 53};
star['26 Ari'] = {ra: '02 30 38.37', dec: '+19 51 19.4', mag: 6.14, fd: 26};
star['60 Ari'] = {ra: '03 20 25.57', dec: '+25 39 46.7', mag: 6.14, fd: 60};
star['27 Ari'] = {ra: '02 30 54.38', dec: '+17 42 14.6', mag: 6.21, fd: 27};
star['85 Cet'] = {ra: '02 42 28.95', dec: '+10 44 30.4', mag: 6.32, fd: 85};
star['36 Ari'] = {ra: '02 44 19.09', dec: '+17 45 50.5', mag: 6.46, fd: 36};
star['30 Ari B'] = {ra: '02 36 57.64', dec: '+24 38 53.1', mag: 7.09, fd: 30};
star['51 Ari'] = {ra: '03 02 25.87', dec: '+26 36 34.7', mag: 6.62, fd: 51};
star['ρ1 Ari'] = {ra: '02 54 55.17', dec: '+17 44 05.3', mag: 7.01, fd: 44};
let edge = [['γ1 Ari', 'β Ari'], ['β Ari', 'α Ari'], ['α Ari', 'ν Ari'], ['ν Ari', 'δ Ari']];
let offsetX, offsetY;
let wrap = true;
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 = 96, dy = 153;
    let g = Snap.select('#Aries');
    g.transform('tlanslate(' + dx + ',' + dy + ')');
    // Get parameters from the zodiac
    offsetX = 0;
    offsetY = 0;
    getMinMax();
    offsetX = -xMin + 130;
    offsetY = -yMin + 140;
    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 500 44)" style="font-family: 'Curlz MT'; font-size: 32px;">Aries</text>
    s.text(500, 44 + 32, 'Aries').attr({fill: 'white', 'font-family': 'Curlz MT', 'font-size': 32});
    //<text transform="matrix(1 0 0 1 500 64)" style="font-family: 'Segoe UI Symbol'; font-size: 96px;">♈</text>
    s.text(500, 64 + 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);
}

参考文献

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