%PDF-1.5 %���� ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY
Server IP : 49.231.201.246 / Your IP : 216.73.216.149 Web Server : Apache/2.4.18 (Ubuntu) System : Linux 246 4.4.0-210-generic #242-Ubuntu SMP Fri Apr 16 09:57:56 UTC 2021 x86_64 User : root ( 0) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /proc/11584/cwd/html/ppaobm/vendor/bower-asset/chartjs/src/scales/ |
Upload File : |
'use strict'; var defaults = require('../core/core.defaults'); var helpers = require('../helpers/index'); var LinearScaleBase = require('./scale.linearbase'); var Ticks = require('../core/core.ticks'); var valueOrDefault = helpers.valueOrDefault; var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault; var resolve = helpers.options.resolve; var defaultConfig = { display: true, // Boolean - Whether to animate scaling the chart from the centre animate: true, position: 'chartArea', angleLines: { display: true, color: 'rgba(0, 0, 0, 0.1)', lineWidth: 1, borderDash: [], borderDashOffset: 0.0 }, gridLines: { circular: false }, // label settings ticks: { // Boolean - Show a backdrop to the scale label showLabelBackdrop: true, // String - The colour of the label backdrop backdropColor: 'rgba(255,255,255,0.75)', // Number - The backdrop padding above & below the label in pixels backdropPaddingY: 2, // Number - The backdrop padding to the side of the label in pixels backdropPaddingX: 2, callback: Ticks.formatters.linear }, pointLabels: { // Boolean - if true, show point labels display: true, // Number - Point label font size in pixels fontSize: 10, // Function - Used to convert point labels callback: function(label) { return label; } } }; function getValueCount(scale) { var opts = scale.options; return opts.angleLines.display || opts.pointLabels.display ? scale.chart.data.labels.length : 0; } function getTickBackdropHeight(opts) { var tickOpts = opts.ticks; if (tickOpts.display && opts.display) { return valueOrDefault(tickOpts.fontSize, defaults.global.defaultFontSize) + tickOpts.backdropPaddingY * 2; } return 0; } function measureLabelSize(ctx, lineHeight, label) { if (helpers.isArray(label)) { return { w: helpers.longestText(ctx, ctx.font, label), h: label.length * lineHeight }; } return { w: ctx.measureText(label).width, h: lineHeight }; } function determineLimits(angle, pos, size, min, max) { if (angle === min || angle === max) { return { start: pos - (size / 2), end: pos + (size / 2) }; } else if (angle < min || angle > max) { return { start: pos - size, end: pos }; } return { start: pos, end: pos + size }; } /** * Helper function to fit a radial linear scale with point labels */ function fitWithPointLabels(scale) { // Right, this is really confusing and there is a lot of maths going on here // The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9 // // Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif // // Solution: // // We assume the radius of the polygon is half the size of the canvas at first // at each index we check if the text overlaps. // // Where it does, we store that angle and that index. // // After finding the largest index and angle we calculate how much we need to remove // from the shape radius to move the point inwards by that x. // // We average the left and right distances to get the maximum shape radius that can fit in the box // along with labels. // // Once we have that, we can find the centre point for the chart, by taking the x text protrusion // on each side, removing that from the size, halving it and adding the left x protrusion width. // // This will mean we have a shape fitted to the canvas, as large as it can be with the labels // and position it in the most space efficient manner // // https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif var plFont = helpers.options._parseFont(scale.options.pointLabels); // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width. // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points var furthestLimits = { l: 0, r: scale.width, t: 0, b: scale.height - scale.paddingTop }; var furthestAngles = {}; var i, textSize, pointPosition; scale.ctx.font = plFont.string; scale._pointLabelSizes = []; var valueCount = getValueCount(scale); for (i = 0; i < valueCount; i++) { pointPosition = scale.getPointPosition(i, scale.drawingArea + 5); textSize = measureLabelSize(scale.ctx, plFont.lineHeight, scale.pointLabels[i] || ''); scale._pointLabelSizes[i] = textSize; // Add quarter circle to make degree 0 mean top of circle var angleRadians = scale.getIndexAngle(i); var angle = helpers.toDegrees(angleRadians) % 360; var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180); var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270); if (hLimits.start < furthestLimits.l) { furthestLimits.l = hLimits.start; furthestAngles.l = angleRadians; } if (hLimits.end > furthestLimits.r) { furthestLimits.r = hLimits.end; furthestAngles.r = angleRadians; } if (vLimits.start < furthestLimits.t) { furthestLimits.t = vLimits.start; furthestAngles.t = angleRadians; } if (vLimits.end > furthestLimits.b) { furthestLimits.b = vLimits.end; furthestAngles.b = angleRadians; } } scale.setReductions(scale.drawingArea, furthestLimits, furthestAngles); } function getTextAlignForAngle(angle) { if (angle === 0 || angle === 180) { return 'center'; } else if (angle < 180) { return 'left'; } return 'right'; } function fillText(ctx, text, position, lineHeight) { var y = position.y + lineHeight / 2; var i, ilen; if (helpers.isArray(text)) { for (i = 0, ilen = text.length; i < ilen; ++i) { ctx.fillText(text[i], position.x, y); y += lineHeight; } } else { ctx.fillText(text, position.x, y); } } function adjustPointPositionForLabelHeight(angle, textSize, position) { if (angle === 90 || angle === 270) { position.y -= (textSize.h / 2); } else if (angle > 270 || angle < 90) { position.y -= textSize.h; } } function drawPointLabels(scale) { var ctx = scale.ctx; var opts = scale.options; var angleLineOpts = opts.angleLines; var gridLineOpts = opts.gridLines; var pointLabelOpts = opts.pointLabels; var lineWidth = valueOrDefault(angleLineOpts.lineWidth, gridLineOpts.lineWidth); var lineColor = valueOrDefault(angleLineOpts.color, gridLineOpts.color); var tickBackdropHeight = getTickBackdropHeight(opts); ctx.save(); ctx.lineWidth = lineWidth; ctx.strokeStyle = lineColor; if (ctx.setLineDash) { ctx.setLineDash(resolve([angleLineOpts.borderDash, gridLineOpts.borderDash, []])); ctx.lineDashOffset = resolve([angleLineOpts.borderDashOffset, gridLineOpts.borderDashOffset, 0.0]); } var outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max); // Point Label Font var plFont = helpers.options._parseFont(pointLabelOpts); ctx.font = plFont.string; ctx.textBaseline = 'middle'; for (var i = getValueCount(scale) - 1; i >= 0; i--) { if (angleLineOpts.display && lineWidth && lineColor) { var outerPosition = scale.getPointPosition(i, outerDistance); ctx.beginPath(); ctx.moveTo(scale.xCenter, scale.yCenter); ctx.lineTo(outerPosition.x, outerPosition.y); ctx.stroke(); } if (pointLabelOpts.display) { // Extra pixels out for some label spacing var extra = (i === 0 ? tickBackdropHeight / 2 : 0); var pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + 5); // Keep this in loop since we may support array properties here var pointLabelFontColor = valueAtIndexOrDefault(pointLabelOpts.fontColor, i, defaults.global.defaultFontColor); ctx.fillStyle = pointLabelFontColor; var angleRadians = scale.getIndexAngle(i); var angle = helpers.toDegrees(angleRadians); ctx.textAlign = getTextAlignForAngle(angle); adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition); fillText(ctx, scale.pointLabels[i] || '', pointLabelPosition, plFont.lineHeight); } } ctx.restore(); } function drawRadiusLine(scale, gridLineOpts, radius, index) { var ctx = scale.ctx; var circular = gridLineOpts.circular; var valueCount = getValueCount(scale); var lineColor = valueAtIndexOrDefault(gridLineOpts.color, index - 1); var lineWidth = valueAtIndexOrDefault(gridLineOpts.lineWidth, index - 1); var pointPosition; if ((!circular && !valueCount) || !lineColor || !lineWidth) { return; } ctx.save(); ctx.strokeStyle = lineColor; ctx.lineWidth = lineWidth; if (ctx.setLineDash) { ctx.setLineDash(gridLineOpts.borderDash || []); ctx.lineDashOffset = gridLineOpts.borderDashOffset || 0.0; } ctx.beginPath(); if (circular) { // Draw circular arcs between the points ctx.arc(scale.xCenter, scale.yCenter, radius, 0, Math.PI * 2); } else { // Draw straight lines connecting each index pointPosition = scale.getPointPosition(0, radius); ctx.moveTo(pointPosition.x, pointPosition.y); for (var i = 1; i < valueCount; i++) { pointPosition = scale.getPointPosition(i, radius); ctx.lineTo(pointPosition.x, pointPosition.y); } } ctx.closePath(); ctx.stroke(); ctx.restore(); } function numberOrZero(param) { return helpers.isNumber(param) ? param : 0; } module.exports = LinearScaleBase.extend({ setDimensions: function() { var me = this; // Set the unconstrained dimension before label rotation me.width = me.maxWidth; me.height = me.maxHeight; me.paddingTop = getTickBackdropHeight(me.options) / 2; me.xCenter = Math.floor(me.width / 2); me.yCenter = Math.floor((me.height - me.paddingTop) / 2); me.drawingArea = Math.min(me.height - me.paddingTop, me.width) / 2; }, determineDataLimits: function() { var me = this; var chart = me.chart; var min = Number.POSITIVE_INFINITY; var max = Number.NEGATIVE_INFINITY; helpers.each(chart.data.datasets, function(dataset, datasetIndex) { if (chart.isDatasetVisible(datasetIndex)) { var meta = chart.getDatasetMeta(datasetIndex); helpers.each(dataset.data, function(rawValue, index) { var value = +me.getRightValue(rawValue); if (isNaN(value) || meta.data[index].hidden) { return; } min = Math.min(value, min); max = Math.max(value, max); }); } }); me.min = (min === Number.POSITIVE_INFINITY ? 0 : min); me.max = (max === Number.NEGATIVE_INFINITY ? 0 : max); // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero me.handleTickRangeOptions(); }, // Returns the maximum number of ticks based on the scale dimension _computeTickLimit: function() { return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options)); }, convertTicksToLabels: function() { var me = this; LinearScaleBase.prototype.convertTicksToLabels.call(me); // Point labels me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me); }, getLabelForIndex: function(index, datasetIndex) { return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); }, fit: function() { var me = this; var opts = me.options; if (opts.display && opts.pointLabels.display) { fitWithPointLabels(me); } else { me.setCenterPoint(0, 0, 0, 0); } }, /** * Set radius reductions and determine new radius and center point * @private */ setReductions: function(largestPossibleRadius, furthestLimits, furthestAngles) { var me = this; var radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l); var radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r); var radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t); var radiusReductionBottom = -Math.max(furthestLimits.b - (me.height - me.paddingTop), 0) / Math.cos(furthestAngles.b); radiusReductionLeft = numberOrZero(radiusReductionLeft); radiusReductionRight = numberOrZero(radiusReductionRight); radiusReductionTop = numberOrZero(radiusReductionTop); radiusReductionBottom = numberOrZero(radiusReductionBottom); me.drawingArea = Math.min( Math.floor(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2), Math.floor(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2)); me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom); }, setCenterPoint: function(leftMovement, rightMovement, topMovement, bottomMovement) { var me = this; var maxRight = me.width - rightMovement - me.drawingArea; var maxLeft = leftMovement + me.drawingArea; var maxTop = topMovement + me.drawingArea; var maxBottom = (me.height - me.paddingTop) - bottomMovement - me.drawingArea; me.xCenter = Math.floor(((maxLeft + maxRight) / 2) + me.left); me.yCenter = Math.floor(((maxTop + maxBottom) / 2) + me.top + me.paddingTop); }, getIndexAngle: function(index) { var angleMultiplier = (Math.PI * 2) / getValueCount(this); var startAngle = this.chart.options && this.chart.options.startAngle ? this.chart.options.startAngle : 0; var startAngleRadians = startAngle * Math.PI * 2 / 360; // Start from the top instead of right, so remove a quarter of the circle return index * angleMultiplier + startAngleRadians; }, getDistanceFromCenterForValue: function(value) { var me = this; if (value === null) { return 0; // null always in center } // Take into account half font size + the yPadding of the top value var scalingFactor = me.drawingArea / (me.max - me.min); if (me.options.ticks.reverse) { return (me.max - value) * scalingFactor; } return (value - me.min) * scalingFactor; }, getPointPosition: function(index, distanceFromCenter) { var me = this; var thisAngle = me.getIndexAngle(index) - (Math.PI / 2); return { x: Math.cos(thisAngle) * distanceFromCenter + me.xCenter, y: Math.sin(thisAngle) * distanceFromCenter + me.yCenter }; }, getPointPositionForValue: function(index, value) { return this.getPointPosition(index, this.getDistanceFromCenterForValue(value)); }, getBasePosition: function() { var me = this; var min = me.min; var max = me.max; return me.getPointPositionForValue(0, me.beginAtZero ? 0 : min < 0 && max < 0 ? max : min > 0 && max > 0 ? min : 0); }, draw: function() { var me = this; var opts = me.options; var gridLineOpts = opts.gridLines; var tickOpts = opts.ticks; if (opts.display) { var ctx = me.ctx; var startAngle = this.getIndexAngle(0); var tickFont = helpers.options._parseFont(tickOpts); if (opts.angleLines.display || opts.pointLabels.display) { drawPointLabels(me); } helpers.each(me.ticks, function(label, index) { // Don't draw a centre value (if it is minimum) if (index > 0 || tickOpts.reverse) { var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]); // Draw circular lines around the scale if (gridLineOpts.display && index !== 0) { drawRadiusLine(me, gridLineOpts, yCenterOffset, index); } if (tickOpts.display) { var tickFontColor = valueOrDefault(tickOpts.fontColor, defaults.global.defaultFontColor); ctx.font = tickFont.string; ctx.save(); ctx.translate(me.xCenter, me.yCenter); ctx.rotate(startAngle); if (tickOpts.showLabelBackdrop) { var labelWidth = ctx.measureText(label).width; ctx.fillStyle = tickOpts.backdropColor; ctx.fillRect( -labelWidth / 2 - tickOpts.backdropPaddingX, -yCenterOffset - tickFont.size / 2 - tickOpts.backdropPaddingY, labelWidth + tickOpts.backdropPaddingX * 2, tickFont.size + tickOpts.backdropPaddingY * 2 ); } ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillStyle = tickFontColor; ctx.fillText(label, 0, -yCenterOffset); ctx.restore(); } } }); } } }); // INTERNAL: static default options, registered in src/index.js module.exports._defaults = defaultConfig;