/*
* charts for WeChat small app v1.0
*
* https://github.com/xiaolin3303/wx-charts
* 2016-11-28
*
* Designed and built with all the love of Web
*/
'use strict';
var config = {
yAxisWidth: 15,
yAxisSplit: 5,
xAxisHeight: 15,
xAxisLineHeight: 15,
legendHeight: 15,
yAxisTitleWidth: 15,
padding: 12,
columePadding: 3,
fontSize: 10,
dataPointShape: ['diamond', 'circle', 'triangle', 'rect'],
colors: ['#7cb5ec', '#f7a35c', '#434348', '#90ed7d', '#f15c80', '#8085e9'],
pieChartLinePadding: 25,
pieChartTextPadding: 15,
xAxisTextPadding: 3,
titleColor: '#333333',
titleFontSize: 20,
subtitleColor: '#999999',
subtitleFontSize: 15,
toolTipPadding: 3,
toolTipBackground: '#000000',
toolTipOpacity: 0.7,
toolTipLineHeight: 14,
radarGridCount: 3,
radarLabelTextMargin: 15
};
// Object.assign polyfill
// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
function assign(target, varArgs) {
if (target == null) {
// TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
}
var to = Object(target);
for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];
if (nextSource != null) {
// Skip over if undefined or null
for (var nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
}
var util = {
toFixed: function toFixed(num, limit) {
limit = limit || 2;
if (this.isFloat(num)) {
num = num.toFixed(limit);
}
return num;
},
isFloat: function isFloat(num) {
return num % 1 !== 0;
},
approximatelyEqual: function approximatelyEqual(num1, num2) {
return Math.abs(num1 - num2) < 1e-10;
},
isSameSign: function isSameSign(num1, num2) {
return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2;
},
isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) {
return this.isSameSign(p1.x, p2.x);
},
isCollision: function isCollision(obj1, obj2) {
obj1.end = {};
obj1.end.x = obj1.start.x + obj1.width;
obj1.end.y = obj1.start.y - obj1.height;
obj2.end = {};
obj2.end.x = obj2.start.x + obj2.width;
obj2.end.y = obj2.start.y - obj2.height;
var flag = obj2.start.x > obj1.end.x || obj2.end.x < obj1.start.x || obj2.end.y > obj1.start.y || obj2.start.y < obj1.end.y;
return !flag;
}
};
function findRange(num, type, limit) {
if (isNaN(num)) {
throw new Error('[wxCharts] unvalid series data!');
}
limit = limit || 10;
type = type ? type : 'upper';
var multiple = 1;
while (limit < 1) {
limit *= 10;
multiple *= 10;
}
if (type === 'upper') {
num = Math.ceil(num * multiple);
} else {
num = Math.floor(num * multiple);
}
while (num % limit !== 0) {
if (type === 'upper') {
num++;
} else {
num--;
}
}
return num / multiple;
}
function calRotateTranslate(x, y, h) {
var xv = x;
var yv = h - y;
var transX = xv + (h - yv - xv) / Math.sqrt(2);
transX *= -1;
var transY = (h - yv) * (Math.sqrt(2) - 1) - (h - yv - xv) / Math.sqrt(2);
return {
transX: transX,
transY: transY
};
}
function createCurveControlPoints(points, i) {
var a = 0.2;
var b = 0.2;
var pAx = null;
var pAy = null;
var pBx = null;
var pBy = null;
if (i < 1) {
pAx = points[0].x + (points[1].x - points[0].x) * a;
pAy = points[0].y + (points[1].y - points[0].y) * a;
} else {
pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
}
if (i > points.length - 3) {
var last = points.length - 1;
pBx = points[last].x - (points[last].x - points[last - 1].x) * b;
pBy = points[last].y - (points[last].y - points[last - 1].y) * b;
} else {
pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
}
return {
ctrA: { x: pAx, y: pAy },
ctrB: { x: pBx, y: pBy }
};
}
function convertCoordinateOrigin(x, y, center) {
return {
x: center.x + x,
y: center.y - y
};
}
function avoidCollision(obj, target) {
if (target) {
// is collision test
while (util.isCollision(obj, target)) {
if (obj.start.x > 0) {
obj.start.y--;
} else if (obj.start.x < 0) {
obj.start.y++;
} else {
if (obj.start.y > 0) {
obj.start.y++;
} else {
obj.start.y--;
}
}
}
}
return obj;
}
function fillSeriesColor(series, config) {
var index = 0;
return series.map(function (item) {
if (!item.color) {
item.color = config.colors[index];
index = (index + 1) % config.colors.length;
}
return item;
});
}
function getDataRange(minData, maxData) {
var limit = 0;
var range = maxData - minData;
if (range >= 10000) {
limit = 1000;
} else if (range >= 1000) {
limit = 100;
} else if (range >= 100) {
limit = 10;
} else if (range >= 10) {
limit = 5;
} else if (range >= 1) {
limit = 1;
} else if (range >= 0.1) {
limit = 0.1;
} else {
limit = 0.01;
}
return {
minRange: findRange(minData, 'lower', limit),
maxRange: findRange(maxData, 'upper', limit)
};
}
function measureText(text) {
var fontSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10;
// wx canvas 未实现measureText方法, 此处自行实现
text = String(text);
var text = text.split('');
var width = 0;
text.forEach(function (item) {
if (/[a-zA-Z]/.test(item)) {
width += 7;
} else if (/[0-9]/.test(item)) {
width += 5.5;
} else if (/\./.test(item)) {
width += 2.7;
} else if (/-/.test(item)) {
width += 3.25;
} else if (/[\u4e00-\u9fa5]/.test(item)) {
width += 10;
} else if (/\(|\)/.test(item)) {
width += 3.73;
} else if (/\s/.test(item)) {
width += 2.5;
} else if (/%/.test(item)) {
width += 8;
} else {
width += 10;
}
});
return width * fontSize / 10;
}
function dataCombine(series) {
return series.reduce(function (a, b) {
return (a.data ? a.data : a).concat(b.data);
}, []);
}
function getSeriesDataItem(series, index) {
var data = [];
series.forEach(function (item) {
if (item.data[index] !== null && typeof item.data[index] !== 'undefinded') {
var seriesItem = {};
seriesItem.color = item.color;
seriesItem.name = item.name;
seriesItem.data = item.format ? item.format(item.data[index]) : item.data[index];
data.push(seriesItem);
}
});
return data;
}
function getMaxTextListLength(list) {
var lengthList = list.map(function (item) {
return measureText(item);
});
return Math.max.apply(null, lengthList);
}
function getRadarCoordinateSeries(length) {
var eachAngle = 2 * Math.PI / length;
var CoordinateSeries = [];
for (var i = 0; i < length; i++) {
CoordinateSeries.push(eachAngle