2016年12月19日月曜日

開発環境

素数夜曲 (吉田 武 (著)、東海大学出版会)の付録D(女王陛下のLISP)、D.9(行列で蝶を愛でる)、D.9.2(不可能を描く)を JavaScript で取り組んでみる。

コード(Emacs)

HTML5

<div id="graph0"></div>
<label for="speed0">速度(ms): </label>
<input id="speed0" type="number" min="1" value="500">
<label for="color0">色: </label>
<input id="color0" type="color" value="#ff0000">
<label for="step0">滑らかさ: </label>
<input id="step0" type="number" min="1" step="1" value="24">
<button id="draw0">描画</button>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.6/d3.min.js" integrity="sha256-5idA201uSwHAROtCops7codXJ0vja+6wbBrZdQ6ETQc=" crossorigin="anonymous"></script>
<script src="sample12.js"></script>

JavaScript

let div_graph = document.querySelector('#graph0'),
    input_speed = document.querySelector('#speed0'),
    input_color = document.querySelector('#color0'),
    input_step = document.querySelector('#step0'),
    button = document.querySelector('#draw0'),
    svg,
    width = 600,
    height = 600,
    tm;

let xscale = d3.scaleLinear()
    .domain([-5, 5])
    .range([0, 600]);
let yscale = d3.scaleLinear()
    .domain([-5, 5])
    .range([600, 0]);
let range = (start, end, step) => {
    let result = [];

    for (let i = start; i < end; i += step) {
        result.push(i);
    }
    return result;
};
let butterfly = (t) => {
    let r = Math.pow(Math.E, Math.sin(t)) - 2 * Math.cos(4 * t) + Math.pow(Math.sin(t / 12), 5);

    return [r * Math.cos(t), r * Math.sin(t)];
};
let getPoints = (i) => {
    return range(0, 24 * Math.PI + 0.1, Math.PI / i).map(butterfly);
};
let draw = (i) => {
    let points = getPoints(i),
        color = input_color.value;

    div_graph.innerHTML = '';
    svg = d3.select('#graph0')
        .append('svg')
        .attr('width', width)
        .attr('height', height);

    svg.selectAll('line')
        .data(points.slice(0, -1))
        .enter()
        .append('line')
        .attr('x1', (d) => xscale(d[0]))
        .attr('y1', (d) => yscale(d[1]))
        .attr('x2', (d, i) => xscale(points[i + 1][0]))
        .attr('y2', (d, i) => yscale(points[i + 1][1]))
        .attr('stroke', color);
};
let animate = () => {
    let i = 1,
        speed = parseInt(input_speed.value, 10),
        step = parseInt(input_step.value, 10);
    
    tm = setInterval(
        () => {
            draw(i);
            i += 1;
            if (i > step) {
                clearInterval(tm);
            }
        }, speed);
};

button.onclick = () => {
    clearInterval(tm);
    animate();
};

animate();

0 コメント:

コメントを投稿