Last active
August 29, 2015 14:16
-
-
Save daohodac/a67ce178b770683017d0 to your computer and use it in GitHub Desktop.
a game to learn multiply tables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
text { | |
text-anchor: middle; | |
font-family: verdana; | |
} | |
.selX { | |
fill: #e6550d; | |
} | |
.selY { | |
fill: #e6550d; | |
} | |
</style> | |
<body></body> | |
<script src="http://d3js.org/d3.v3.js"></script> | |
<script> | |
function getWindowSize() { | |
var winW = 630, winH = 460; | |
if (document.body && document.body.offsetWidth) { | |
winW = document.body.offsetWidth; | |
winH = document.body.offsetHeight; | |
} | |
if (document.compatMode==='CSS1Compat' && | |
document.documentElement && | |
document.documentElement.offsetWidth ) { | |
winW = document.documentElement.offsetWidth; | |
winH = document.documentElement.offsetHeight; | |
} | |
if (window.innerWidth && window.innerHeight) { | |
winW = window.innerWidth; | |
winH = window.innerHeight; | |
} | |
return [winW, winH]; | |
} | |
function fullsize() { | |
var winSize = getWindowSize(); | |
return Math.min(winSize[0], winSize[1]); | |
} | |
//the size of the canvas | |
var size = fullsize(); | |
//the size of each tile | |
var square = size/11; | |
//init the tiles | |
var data = []; | |
var maxInt = 10; | |
for (var i = 1; i < maxInt; i++) { | |
for (var j = i; j < maxInt; j++) { | |
data.push({a:i, b:j, ongoing:false, found: false}); | |
} | |
} | |
var foundScale = d3.scale.linear() | |
.domain(d3.scale.ordinal() | |
.domain(d3.range(4)) | |
.rangeRoundPoints([0, 81]).range() | |
) | |
.range(["#dadaeb", "#bcbddc", "#9e9ac8", "#756bb1"]); | |
var opScale = d3.scale.linear() | |
.domain(d3.scale.ordinal() | |
.domain(d3.range(4)) | |
.rangeRoundPoints([0, 10]).range() | |
) | |
.range(["#d9d9d9", "#bdbdbd", "#969696", "#636363"]); | |
data=shuffle(data); | |
foundCount = 0; | |
data[data.length-1].ongoing=true; | |
var toFind = data[data.length-1].a*data[data.length-1].b; | |
//some margins | |
var margin = {top: 0, right: 0, bottom: 0, left: 0}; | |
//scale to nicely reorder the tiles | |
var x = d3.scale.ordinal().rangeBands([0, size-margin.left]), | |
y = d3.scale.ordinal().rangeBands([0, size-margin.top]); | |
x.domain(d3.range(maxInt)); | |
y.domain(d3.range(maxInt)); | |
//a scale for the shuffle. | |
var randScale = d3.scale.linear(); | |
randScale.domain([0, 1]).range([square*2,size-square*2]); | |
//function to shuffle the tiles | |
function shuffle(o){ //v1.0 | |
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); | |
return o; | |
}; | |
function randomPos(d) { | |
return 'translate('+randScale(Math.random())+', '+randScale(Math.random())+') rotate('+(Math.random()*90-45)+')'; | |
}; | |
function finalPos(d) { | |
return 'translate('+x(d.a)+','+y(d.b)+')'; | |
}; | |
//create the SVG | |
var svg = d3.select("body").append("svg") | |
.attr("width", size) | |
.attr("height", size); | |
var tileGroup = svg.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
var colorizeTile = function(d) { | |
this | |
.transition() | |
.duration(function(d) {return Math.random()*1000;}) | |
.attr("transform", function(d) { | |
if (d.found) { | |
return finalPos(d); | |
} else { | |
return randomPos(d); | |
}}) | |
.attr("opacity", function(d) { | |
if (d.found && foundCount<data.length) { | |
return 0; | |
} else { | |
return 1; | |
} | |
}) | |
.select('rect') | |
.attr("fill", function(d) { | |
if (d.found) { | |
return foundScale(d.a*d.b); | |
} else if (d.ongoing) { | |
return "#e6550d"; | |
} else { | |
return "#aec7e8"; | |
} | |
}) | |
}; | |
var createRect = function(sel, klass, color, transform, txt) { | |
var tile = sel.append('g') | |
.attr("transform", transform) | |
.classed(klass, true); | |
tile.append("rect") | |
.attr("fill", color) | |
.attr("width", square) | |
.attr("height",square); | |
tile.append('text') | |
.text(txt) | |
.attr('alignment-baseline', 'middle') | |
.attr("text-anchor", "middle") | |
.attr("fill", "white") | |
.attr("font-size", (square*.75)+"px") | |
.attr('x', square/2) | |
.attr('y', square/2); | |
return tile; | |
} | |
var createTile = function(sel) { | |
var tile = createRect(sel, "tile", | |
"black", | |
randomPos, | |
function(d) { return d.a*d.b;}); | |
tile.classed("toFind", function(d) { | |
return d.ongoing; | |
}).call(colorizeTile) | |
} | |
var createXOperand = function(sel) { | |
var tile = createRect(sel,"opX", | |
function(d) {return opScale(d)}, | |
function(d) { | |
return 'translate(0, '+y(d)+')'; | |
}, | |
function(d) { return d;}); | |
tile.on('click', function(d) { | |
selX = d3.select(this); | |
d3.selectAll(".selX").classed("selX", false); | |
selX.select('rect').classed("selX", true); | |
validate(); | |
}); | |
} | |
var createYOperand = function(sel) { | |
var tile = createRect(sel,"opY", | |
function(d) {return opScale(d)}, | |
function(d) { | |
return 'translate('+x(d)+', 0)'; | |
}, | |
function(d) { return d;}); | |
tile.on('click', function(d) { | |
selY = d3.select(this); | |
d3.selectAll(".selY").classed("selY", false); | |
selY.select('rect').classed("selY", true); | |
validate(); | |
}); | |
} | |
//append the operands | |
svg.selectAll("#operands") | |
.data(d3.range(maxInt)) | |
.enter().call(createXOperand).call(createYOperand); | |
//create the tiles | |
var tiles = tileGroup.selectAll(".tile") | |
.data(data) | |
.enter().call(createTile) | |
var validate = function() { | |
var comp = selX.data()[0]*selY.data()[0]; | |
if (comp === toFind) { | |
congrats(); | |
} else { | |
nonono(); | |
} | |
} | |
var nonono = function() { | |
d3.select(".toFind").transition().duration(function(d) {return Math.random()*3000;}).attr("transform", randomPos); | |
d3.selectAll(".tile").call(colorizeTile); | |
} | |
var congrats = function() { | |
selX.classed("selX", false); | |
selY.classed("selY", false); | |
d3.select(".toFind").classed("toFind", false) | |
.transition().attr("transform", finalPos) | |
.select('rect').attr("fill", "green"); | |
data[data.length-foundCount-1].ongoing=false; | |
data[data.length-foundCount-1].found=true; | |
foundCount++; | |
if (data.length-foundCount-1>=0) { | |
data[data.length-foundCount-1].ongoing=true; | |
toFind = data[data.length-foundCount-1].a*data[data.length-foundCount-1].b; | |
} | |
//d3.selectAll(".tile").select('rect').attr('fill', colorizeTile) | |
d3.selectAll(".tile").call(colorizeTile); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment