JavaScript
语言:
JaveScriptBabelCoffeeScript
确定
var canvas = Snap('#svg-canvas');
var card = $('#svg-canvas');
var intro = $('.intro')
var trainedData = [];
var centerDot;
var drawBox;
var drawing = [];
var drawPath = canvas.path().attr({
fill: "none",
stroke: "#ff0000",
strokeWidth: 3,
strokeDasharray: '5 5'
});
var canvasBox = canvas.node.getBoundingClientRect();
var TYPES = {
heart: { type: 'heart', path: Snap.select('#heart'), item: $('#heart')},
house: { type: 'house', path: Snap.select('#house'), item: $('#house')},
moon: { type: 'moon', path: Snap.select('#moon'), item: $('#moon')},
star: { type: 'star', path: Snap.select('#star'), item: $('#star')},
zigzag: { type: 'zigzag', path: Snap.select('#zigzag'), item: $('#zigzag')},
}
var keys = _.keys(TYPES);
init();
reset();
card.on('mousedown', startDrawing);
function init()
{
// train with starting shapes
for(var i = 0; i < keys.length; i++)
{
var t = TYPES[keys[i]];
train(t.type, t.path);
t.item.bind('click', { type: keys[i] },function(e)
{
var data = e.data;
train(data.type);
reset();
TYPES[data.type].path.attr({
fill: '#ddffdd',
stroke: "#00dd00",
strokeWidth: 2
})
})
}
}
function train(type, path)
{
if(!path) path = drawPath;
trainedData.push({type: type, breakdown: getLineBreakdown(path)});
}
function getLineBreakdown(path)
{
var numberChunks = 200;
var breakdown = [];
var pathLength = Snap.path.getTotalLength( path );
var chunkLength = pathLength / numberChunks;
// get center point
var bbox = path.node.getBoundingClientRect();
var center = {
x: (bbox.left + bbox.width/2) - canvasBox.left,
y: (bbox.top + bbox.height/2) - canvasBox.top
};
// get lengths
for(var i = 0; i < numberChunks; i++)
{
var chunk = path.getPointAtLength( chunkLength * i );
var a = center.x - chunk.x;
var b = center.y - chunk.y;
var c = Math.sqrt( a*a + b*b );
breakdown.push(c);
}
//console.log(breakdown)
return breakdown;
}
function getClosestMatch(breakdown)
{
console.log('============');
var closest = {score: 0, shape: null};
var results = {};
for(var i = 0; i < trainedData.length; i++)
{
if(!results[trainedData[i].type]) results[trainedData[i].type] = [];
var score = Math.abs(getPearsonsCorrelation(breakdown, trainedData[i].breakdown));
results[trainedData[i].type].push(score)
//console.log(trainedData[i].type + ': ' + score)
if(score > closest.score) closest = {score: score, shape: trainedData[i]};
}
return closest;
}
function updateDrawLine()
{
drawPath.attr('d',"M" + drawing.join(' '))
}
function reset()
{
for(var i = 0; i < keys.length; i++)
{
TYPES[keys[i]].path.attr({
fill: '#ddd',
stroke: "#00dd00",
strokeWidth: 0
})
}
}
function startDrawing(e)
{
intro.addClass('hidden');
if(e.offsetY > 60)
{
reset();
drawing = [e.offsetX + ',' + e.offsetY];
card.on('mousemove', draw);
card.on('mouseup', stopDrawing);
}
}
function draw(e)
{
drawing.push(e.offsetX + ',' + e.offsetY);
updateDrawLine();
}
function stopDrawing(e)
{
card.off('mousemove', draw);
card.off('mouseup', stopDrawing);
// get center
var bbox = drawPath.node.getBoundingClientRect();
var center = {
x: (bbox.left + bbox.width/2) - canvasBox.left,
y: (bbox.top + bbox.height/2) - canvasBox.top
};
// //draw center
// if(centerDot) centerDot.remove();
// centerDot = canvas.heart(center.x, center.y, 4).attr({
// fill: "red"
// });
// if(drawBox) drawBox.remove();
// drawBox = canvas.rect(bbox.left - canvasBox.left, bbox.top - canvasBox.top, bbox.width, bbox.height).attr({
// fill: "none",
// stroke: "#444",
// strokeWidth: 1,
// strokeDasharray: '3 3'
// });
var closest = getClosestMatch(getLineBreakdown(drawPath));
console.log(closest.score)
if(closest.shape)
{
console.log(closest.shape.type.toUpperCase());
TYPES[closest.shape.type].path.attr({
fill: '#6666bb',
stroke: "#006600",
strokeWidth: 0,
})
}
else
{
console.log('unknown'.toUpperCase());
}
}
function getPearsonsCorrelation (x, y)
{
var shortestArrayLength = 0;
if (x.length == y.length)
{
shortestArrayLength = x.length;
}
else if (x.length > y.length)
{
shortestArrayLength = y.length;
console.error('x has more items in it, the last ' + (x.length - shortestArrayLength) + ' item(s) will be ignored');
}
else
{
shortestArrayLength = x.length;
console.error('y has more items in it, the last ' + (y.length - shortestArrayLength) + ' item(s) will be ignored');
}
var xy = [];
var x2 = [];
var y2 = [];
for (var i = 0; i < shortestArrayLength; i++)
{
xy.push(x[i] * y[i]);
x2.push(x[i] * x[i]);
y2.push(y[i] * y[i]);
}
var sum_x = 0;
var sum_y = 0;
var sum_xy = 0;
var sum_x2 = 0;
var sum_y2 = 0;
for (var i = 0; i < shortestArrayLength; i++)
{
sum_x += x[i];
sum_y += y[i];
sum_xy += xy[i];
sum_x2 += x2[i];
sum_y2 += y2[i];
}
var step1 = (shortestArrayLength * sum_xy) - (sum_x * sum_y);
var step2 = (shortestArrayLength * sum_x2) - (sum_x * sum_x);
var step3 = (shortestArrayLength * sum_y2) - (sum_y * sum_y);
var step4 = Math.sqrt(step2 * step3);
var answer = step1 / step4;
return answer;
}
function sum(arr)
{
var sum = 0;
for( var i = 0; i < arr.length; i++ ){
sum += arr[i];
}
return sum;
}