AdventCalendar

by MKGaru

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-debug.js"></script>
<script src="https://mbest.github.io/knockout.punches/knockout.punches.js"></script>
<script src="https://rawgit.com/SteveSanderson/knockout-es5/master/dist/knockout-es5.js"></script>
<script src="https://rawgit.com/LeaVerou/prefixfree/gh-pages/prefixfree.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sugar/1.4.1/sugar-full.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Fredericka+the+Great&amp;.css">
<span>数字をクリックしてね</span>

<h1>Advent Calendar</h1>
<div class="cupboard">
    <div class="backpanel"></div>
    <table>
        <tbody data-bind="template:{foreach: weeks,as:'week'}">
            <tr data-bind="foreach:week">
                <td>
                    <div class="cell">
                        <div class="box {{done?'done':'active'}}">
                            <div class="front"><span data-bind="on.click:done=true">{{date.format('{d}')}}</span></div>
                            <div class="back"></div>
                            <div class="left"></div>
                            <div class="right" data-bind="style:{'background-position':($index()*20)+'% '+($parentContext.$index()*20)+'%'}"></div>
                            <div class="bottom"><span>{{note}}</span></div>
                        </div>
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
</div>

SCSS

*{
    user-select:none;
}
h1{
    font-family: 'Fredericka the Great', cursive;
    margin: 0;
    margin-top:1em;
    width: 300px;
    text-align: center;
    color: green;
    text-shadow: 2px 2px gray;
}
.cupboard{
    position:absolute;
    left:10px;
    width: 300px;
    transform-style: preserve-3d;
    perspective: 1500px;
    perspective-origin: 50% 0;
    transform: rotateX(0deg);
    .backpanel{
        position:absolute;
        height:100%;
        width:100%;
        left:0;right:0;
        top:0;bottom:0;
        transform: translateZ(-51px);
        background: #664444;
    }
    .cell{
        
    } 
    th,td{
        border:solid 2px darkslategrey;
    }
}

.box{
    width: 50px;
    height: 50px;
    top: 0px;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    transform-style: preserve-3d;
    transform: translateZ(100px);
    transform-origin: 25px 0px -25px;
    transition: transform ease-out 500ms;
    
    //animation: rotateY 5s linear infinite;
    transform: rotateY(180deg);
    &.active{
        transform: rotateY(0deg);
        //animation: pull-push 5s ease-in infinite;
    }
    &.done{
        animation: pull-push 3s ease-in 1;
        transform: rotateY(-90deg);
    }
    
    .front,
    .back,
    .left,
    .right,
    .bottom{
        width: 50px;
        height: 50px;
        position: absolute;
        top: 0px;
        bottom: 0;
        left: 0;
        right: 0;
        margin: auto;
        text-align: center;
        line-height: 50px;
        opacity: 0.8;
        border: solid 1px brown;
        background: url(https://yabumi.cc/15142c3178cd66b98092f9a6.png);
        &>span{
            display:block;
        }
    }
    .front{
        transform: translateZ(0px);
        &>span{
            background:rgba(red,0.75);
            cursor:pointer;
            color: white;
            font-size:30px;
            font-family: 'Fredericka the Great', cursive;
            font-weight:bold;
        }
    }
 ...

JavaScript

function Day(date){
    this.note = '';
    this.done = false;
    this.date = date;
    ko.track(this);
}
function AdventCalendar(){
    var calendar = this;
    calendar.date = new Date();
    calendar.days = Date
        .range("12/1","12/25")
        .every('date')
        .map(function(date){
        	return new Day(date);
    	});
    calendar.weeks = Number
        .range(0,24)
        .every(5)
        .map(function(day){
        	return calendar.days.from(day).first(5)
    	});
    calendar.days
        .filter(function(day){
        	return day.date.isBefore(calendar.date)
    	})
    	.forEach(function(day){
        	day.done = true;
    	});
    
    ko.track(calendar);
}
var calendar = new AdventCalendar();
ko.punches.enableAll();
ko.applyBindings(calendar);