rveciana - calendar-race-canvas

Calendar race: canvas

Open raw page in new tab

Representation of the different speed of the Gregorian and Hijri calendars.

The date conversion is taken from this StackOverflow question

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; 
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    }
    svg { width:100%; height: 100% }
  </style>
</head>
<body>
  <div id="graph"></div>
  The Islamic Calendar (or Hijri Calendar) started at 622 AD. Its years are based on the lunar calendar, shorter than the solar calendar, so it will catch the Gregorian Calendar. 
  <script>
    var duration = 3000;
    var delay = 1500;
    var width = 600;
    var margin = 30;
    
    var GregorianYear = (new Date()).getFullYear();
        var HijriYear = Math.round((GregorianYear - 622) * (33 / 32));
    
    var colors = ["#faa", "#afa"];

    var scaleToday = d3.scale.linear()
        .domain([0, GregorianYear])
        .range([0, width]);
    
    var endDate = 20526;
    var scaleEnd = d3.scale.linear()
            .domain([0, endDate])
            .range([0, width]);
    
    var data = [{"name":"Gregorian","startDate": 691, "today": GregorianYear, "endDate": endDate},
               {"name":"Hijri","startDate": 0, "today": HijriYear, "endDate": endDate}];


    var canvas = d3.select("#graph").append("canvas")
        .attr("width", 1000)
        .attr("height", 400);

    var context = canvas.node().getContext("2d");

    d3.transition()
        .duration(duration)
        .ease("linear")
        .tween("zoom", function() {
            return function(t) {
                draw_graph(t, scaleToday, scaleToday, "startDate", "today");    
            }
        })
        .each("end", function() {
            d3.transition()
            .delay(delay)
            .duration(duration)
            .ease("linear")
            .tween("zoom", function() {
                return function(t) {
                    draw_graph(t, scaleToday, scaleEnd, "today", "today");    
                }
            })
            .each("end", function() {
                d3.transition()
                .delay(delay)
                .duration(duration)
                .ease("linear")
                .tween("zoom", function() {
                    return function(t) {
                        draw_graph(t, scaleEnd, scaleEnd, "today", "endDate");    
                    }
                });
            });
        });


    function draw_graph(progress, scaleIni, scaleEnd, ini, end){
        context.clearRect(0, 0, 1000, 400);
        data.forEach(function(d, i){
            var curr_year = d[ini]*(1-progress) + progress*d[end];
            var curr_width = scaleIni(curr_year)*(1-progress) + progress * scaleEnd(curr_year);
           
            context.fillStyle = colors[i];
            context.fillRect(margin, 
                        margin + i*(30 + margin),
                        curr_width,
                        30);
            context.fillStyle = "#000";
            context.font="15px Helvetica";
            context.fillText(Math.round(curr_year), 
                            margin + 10 + curr_width,
                            50 + i*(30 + margin));

        });
    }
    
    /*
    var svg = d3.select("#graph").append("svg");
        
    var bars = svg.selectAll(".calbar")
            .data(data)
            .enter()
            .append("rect")
            .attr("class","calbar")
            .attr("fill", function(d,i){return colors[i];})
            .attr("x", margin)
            .attr("y", function(d,i){return margin + i*(30 + margin);})
            .attr("height", 30)
            .attr("width", function(d){return scaleToday(d.startDate);})
            .transition()
            .delay(delay)
            .duration(duration)
            .attr("width", function(d){return scaleToday(d.today);})
            .transition()
            .delay(2*delay + duration)
            .duration(duration)
            .attr("width", function(d){return scaleEnd(d.today);})
            .transition()
            .delay(3*delay + 2*duration)
            .duration(duration)
            .attr("width", function(d){return scaleEnd(endDate);});
         
    
    var labels = svg.selectAll(".label")
            .data(data)
            .enter()
        .append("text")
            .attr("class","label")
            .attr("x", function(d){return margin + 10 + scaleToday(d.startDate);})
            .attr("y", function(d,i){return 50 + i*(30 + margin);})
            .attr("text-anchor","start")
            .text(function(d){return d.startDate;})
            .transition()
            .delay(delay)
            .duration(duration)
            .attr("x", function(d){return margin + 10 + scaleToday(d.today);})
            .tween("text", function(d) {
            var i = d3.interpolate(this.textContent, d.today),
                prec = (d + "").split("."),
                round = (prec.length > 1) ? Math.pow(10, prec[1].length) : 1;

            return function(t) {
                this.textContent = Math.round(i(t) * round) / round;
            };
            })
            .transition()
            .delay(2*delay + duration)
            .duration(duration)
            .attr("x", function(d){return margin + 10 + scaleEnd(d.today);})
            .transition()
            .delay(3*delay + 2*duration)
            .duration(duration)
            .attr("x", function(d){return margin + 10 + scaleEnd(endDate);})
            .tween("text", function(d) {
            var i = d3.interpolate(this.textContent, endDate),
                prec = (d + "").split("."),
                round = (prec.length > 1) ? Math.pow(10, prec[1].length) : 1;

            return function(t) {
                this.textContent = Math.round(i(t) * round) / round;
            };
            });
    
     var names = svg.selectAll(".name")
            .data(data)
            .enter()
        .append("text")
            .attr("class","label")
            .attr("x", 2*margin)
            .attr("y", function(d,i){return 30 + i*(30 + margin);})
            .attr("text-anchor","start")
            .text(function(d){return d.name;});  */
  </script>
</body>