Skip to content

Instantly share code, notes, and snippets.

@e7h4n
Created January 2, 2014 04:48
Show Gist options
  • Select an option

  • Save e7h4n/8215173 to your computer and use it in GitHub Desktop.

Select an option

Save e7h4n/8215173 to your computer and use it in GitHub Desktop.
/**
* DistributionChart.js, Jul 11, 2013
*
* Copyright 2013 fenbi.com. All rights reserved.
* FENBI.COM PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
/**
* @author zhangyc <zhangyc@fenbi.com>
*/
/*jshint maxparams: 5*/
'use strict';
var raphael = require('../lib/raphael');
var $ = require('../lib/jquery');
var DistributionChart = {
axisFix: {
left: 60,
bottom: 20,
right: 10,
top: 10
},
axisWidth: 4,
axisHeight: 6,
paper: null,
$scoreTip: null,
draw: function (el, mu, sigma, fullMark, score) {
mu = parseFloat(mu);
sigma = parseFloat(sigma);
var paper = DistributionChart.paper || raphael(el);
paper.clear();
DistributionChart.paper = paper;
DistributionChart.drawAxis(fullMark);
var dottes = [{
x: 0,
y: 0
}];
var yList = [];
var total = 0;
for (var x = 1; x < fullMark; x += 1) {
var y = DistributionChart.normDist(fullMark - x, mu, sigma);
var pos = {
x: x / fullMark,
y: y
};
total += y;
dottes.push(pos);
yList.push(pos.y);
}
dottes.push({
x: 1,
y: 0
});
var width = paper.width - DistributionChart.axisFix.left - DistributionChart.axisFix.right;
var height = paper.height - DistributionChart.axisFix.top - DistributionChart.axisFix.bottom;
var yMax = Math.max.apply(Math, yList) * width;
var yFix = width * 0.7 / yMax;
if (!isFinite(yFix)) {
yFix = 1;
}
if (score && score > 0) {
var $container = $(el).parent();
var $el = $(el);
var posFix = {
left: $el.offset().left - $container.offset().left,
top: $el.offset().top - $container.offset().top
};
var userScorePosition = {
left: posFix.left + width * yFix * DistributionChart.normDist(score, mu, sigma) + DistributionChart.axisFix.left,
top: posFix.top + (fullMark - score) / fullMark * height + DistributionChart.axisFix.top
};
if(!DistributionChart.$scoreTip) {
DistributionChart.$scoreTip = $('<div class="distribution-score-tip"></div>').appendTo($container);
}
DistributionChart.$scoreTip.css(userScorePosition).text(score + ' 分');
}
var path = dottes.reduce(function (memo, dot) {
memo.push([
memo.length === 0 ? 'M' : 'L',
yFix * dot.y * width + DistributionChart.axisFix.left,
dot.x * height + DistributionChart.axisFix.top
]);
return memo;
}, []);
path.push('Z');
paper.path(path).attr({
fill: '270.0-#FF947D-#D83C48',
stroke: 'none'
}).glow({
offsetx: 1,
offsety: 1,
width: 4,
color: '#CCC'
});
},
normDist: function (x, mu, sigma) {
if (mu === 0 || sigma === 0) {
return 0;
}
return 1 / (sigma * Math.sqrt(2 * Math.PI)) * Math.exp(-(x - mu) * (x - mu) / (2 * sigma * sigma));
},
drawAxis: function (fullMark) {
var paper = DistributionChart.paper;
if (paper === null) {
return;
}
var paths = [
['M', DistributionChart.axisFix.left, DistributionChart.axisFix.top]
];
/*
* Render axes
* x1 x0 DistributionChart.axisFix.left
* ^ ^ ^
* | | |
* | | | - start point
* | | | /
* ^ ^ ^ /
* y0 <--------> -----<-----<------ <-------> DistributionChart.axisFix.top
* / |
* / |
* | ___ |
* | |
* \ ___ |
* \ U |
* y1 <--------> --->----| |
* | |
* | |
* . .
* . .
* . . - finish point, 'Z' |
* | | / /
* | |/ /
* ----<---| -----<-----...-------------<------| <---------> paper.height - DistributionChart.axisFix.bottom
* / |
* / |
* | |
* | ^
* \ |
* \ |
* ---->---| |--->----...---------| | <---------> y0
* | | | |
* | | | | <---------> y1
* \ / \ /
* \ / \ /
* -->----- --->----
* ^ ^ ^
* | | |
* | | |
* | | |
* | | |
* ^ ^ ^
* x0 x1 paper.width - DistributionChart.axisFix.right
*
*/
var width = paper.width - DistributionChart.axisFix.left - DistributionChart.axisFix.right;
var height = paper.height - DistributionChart.axisFix.top - DistributionChart.axisFix.bottom;
(function () {
var yStops = Math.min(fullMark / 10, 10);
for (var i = 0; i <= yStops; i++) {
var x0 = DistributionChart.axisFix.left - DistributionChart.axisWidth;
var x1 = x0 - DistributionChart.axisHeight;
var y0 = DistributionChart.axisFix.top + i / yStops * height;
var y1 = y0 + DistributionChart.axisWidth;
paper.text(DistributionChart.axisFix.left / 2, (y0 + y1) / 2, fullMark * (yStops - i) / yStops).attr({
fill: '#3A8FFB',
'font-size': 14,
'font-family': 'Arial, Helvetica, sans-serif',
'text-anchor': 'middle'
});
paths = paths.concat([
['L', x0, y0],
['L', x1, y0],
['A', 2, 2, 0, 1, 0, x1, y1],
['L', x0, y1]
]);
}
})();
(function () {
var xStops = 10;
for (var i = 0; i <= xStops; i++) {
var x0 = DistributionChart.axisFix.left - DistributionChart.axisWidth + width * (i / xStops);
var x1 = x0 + DistributionChart.axisWidth;
var y0 = DistributionChart.axisFix.top + height + DistributionChart.axisWidth;
var y1 = y0 + DistributionChart.axisHeight;
var path = [
['L', x0, y1],
['A', 2, 2, 0, 1, 0, x1, y1],
['L', x1, y0]
];
if (i !== 0) {
path.unshift(['L', x0, y0]);
}
paths = paths.concat(path);
}
})();
paths = paths.concat([
['L', paper.width - DistributionChart.axisFix.right, DistributionChart.axisFix.top + height],
['L', DistributionChart.axisFix.left, DistributionChart.axisFix.top + height],
'Z'
]);
var axisPaths = paper.path(paths);
axisPaths.attr({
fill: '#FFF',
stroke: 'none'
});
if (!$.browser.msie || $.browser.version !== '7.0') {
axisPaths.glow({
offsetx: -1,
offsety: 1,
width: 1,
color: '#BBB'
});
axisPaths.glow({
offsetx: 1,
offsety: -1,
width: 3,
opacity: 0.3,
color: '#CCC'
});
}
}
};
module.exports = DistributionChart;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment