Skip to content

Commit

Permalink
Changed minor and major tick configuration options. Changed ticks sto…
Browse files Browse the repository at this point in the history
…rage to array of strings.
  • Loading branch information
andrew.hurskiy committed Jun 8, 2017
1 parent 5bd9cb6 commit 05cf849
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 93 deletions.
15 changes: 14 additions & 1 deletion docs/axes/styling.md
Expand Up @@ -35,9 +35,22 @@ The tick configuration is nested under the scale configuration in the `ticks` ke
| `fontSize` | `Number` | `12` | Font size for the tick labels.
| `fontStyle` | `String` | `'normal'` | Font style for the tick labels, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).
| `reverse` | `Boolean` | `false` | Reverses order of tick labels.
| `minor` | `object` | `{}` | Minor ticks configuration. Ommited options are inherited from options above.
| `major` | `object` | `{}` | Major ticks configuration. Ommited options are inherited from options above.

## Minor Tick Configuration
The minorTick configuration is nested under the ticks configuration in the `minor` key. It defines options for the minor tick marks that are generated by the axis. Omitted options are inherited from `ticks` configuration.

| Name | Type | Default | Description
| -----| ---- | --------| -----------
| `callback` | `Function` | | Returns the string representation of the tick value as it should be displayed on the chart. See [callback](../axes/labelling.md#creating-custom-tick-formats).
| `fontColor` | Color | `'#666'` | Font color for tick labels.
| `fontFamily` | `String` | `"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"` | Font family for the tick labels, follows CSS font-family options.
| `fontSize` | `Number` | `12` | Font size for the tick labels.
| `fontStyle` | `String` | `'normal'` | Font style for the tick labels, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit).

## Major Tick Configuration
The majorTick configuration is nested under the scale configuration in the `majorTicks` key. It defines options for the major tick marks that are generated by the axis. Omitted options are onherited from `ticks` configuration.
The majorTick configuration is nested under the ticks configuration in the `major` key. It defines options for the major tick marks that are generated by the axis. Omitted options are inherited from `ticks` configuration.

| Name | Type | Default | Description
| -----| ---- | --------| -----------
Expand Down
2 changes: 1 addition & 1 deletion samples/scales/time/line-point-data.html
Expand Up @@ -73,7 +73,7 @@
x: newDate(5),
y: randomScalingFactor()
}]
}]
}],
},
options: {
responsive: true,
Expand Down
1 change: 1 addition & 0 deletions src/core/core.controller.js
Expand Up @@ -265,6 +265,7 @@ module.exports = function(Chart) {
});

scales[scale.id] = scale;
scale.mergeTicksOptions();

// TODO(SB): I think we should be able to remove this custom case (options.scale)
// and consider it as a regular scale part of the "scales"" map only! This would
Expand Down
48 changes: 39 additions & 9 deletions src/core/core.scale.js
Expand Up @@ -48,7 +48,9 @@ module.exports = function(Chart) {
autoSkipPadding: 0,
labelOffset: 0,
// We pass through arrays to be rendered as multiline labels, we convert Others to strings here.
callback: Chart.Ticks.formatters.values
callback: Chart.Ticks.formatters.values,
minor: {},
major: {}
}
};

Expand Down Expand Up @@ -94,6 +96,28 @@ module.exports = function(Chart) {
// Any function defined here is inherited by all scale types.
// Any function can be extended by the scale type

mergeTicksOptions: function() {
if (this.options.ticks.minor === false) {
this.options.ticks.minor = {
display: false
};
}
if (this.options.ticks.major === false) {
this.options.ticks.major = {
display: false
};
}
for (var key in this.options.ticks) {
if (key !== 'major' && key !== 'minor') {
if (typeof this.options.ticks.minor[key] === 'undefined') {
this.options.ticks.minor[key] = this.options.ticks[key];
}
if (typeof this.options.ticks.major[key] === 'undefined') {
this.options.ticks.major[key] = this.options.ticks[key];
}
}
}
},
beforeUpdate: function() {
helpers.callback(this.options.beforeUpdate, [this]);
},
Expand Down Expand Up @@ -486,8 +510,8 @@ module.exports = function(Chart) {

var context = me.ctx;
var globalDefaults = Chart.defaults.global;
var optionTicks = options.ticks;
var optionMajorTicks = options.majorTicks ? options.majorTicks : optionTicks;
var optionTicks = options.ticks.minor;
var optionMajorTicks = options.ticks.major ? options.ticks.major : optionTicks;
var gridLines = options.gridLines;
var scaleLabel = options.scaleLabel;

Expand Down Expand Up @@ -547,8 +571,7 @@ module.exports = function(Chart) {
var yTickStart = options.position === 'bottom' ? me.top : me.bottom - tl;
var yTickEnd = options.position === 'bottom' ? me.top + tl : me.bottom;

helpers.each(me.ticks, function(tick, index) {
var label = typeof tick === 'object' && typeof tick.value !== 'undefined' ? tick.value : tick;
helpers.each(me.ticks, function(label, index) {
// If the callback returned a null or undefined value, do not draw this line
if (label === undefined || label === null) {
return;
Expand Down Expand Up @@ -629,6 +652,11 @@ module.exports = function(Chart) {
ty1 = ty2 = y1 = y2 = yLineValue;
}

var major = false;
if (typeof me.majorTicksIndexes !== 'undefined') {
major = me.majorTicksIndexes.indexOf(index) !== -1;
}

itemsToDraw.push({
tx1: tx1,
ty1: ty1,
Expand All @@ -646,7 +674,9 @@ module.exports = function(Chart) {
glBorderDashOffset: borderDashOffset,
rotation: -1 * labelRotationRadians,
label: label,
major: tick.major === true,
tickOptions: major ? optionMajorTicks : optionTicks,
font: major ? majorTickFont.font : tickFont.font,
color: major ? majorTickFontColor : tickFontColor,
textBaseline: textBaseline,
textAlign: textAlign
});
Expand Down Expand Up @@ -679,13 +709,13 @@ module.exports = function(Chart) {
context.restore();
}

if (optionTicks.display) {
if (itemToDraw.tickOptions.display) {
// Make sure we draw text in the correct color and font
context.save();
context.translate(itemToDraw.labelX, itemToDraw.labelY);
context.rotate(itemToDraw.rotation);
context.font = itemToDraw.major ? majorTickFont.font : tickFont.font;
context.fillStyle = itemToDraw.major ? majorTickFontColor : tickFontColor;
context.font = itemToDraw.font;
context.fillStyle = itemToDraw.color;
context.textBaseline = itemToDraw.textBaseline;
context.textAlign = itemToDraw.textAlign;

Expand Down
19 changes: 19 additions & 0 deletions src/helpers/helpers.time.js
Expand Up @@ -215,6 +215,25 @@ module.exports = function(Chart) {
min: niceMin,
max: niceMax
});
},

/**
* return array of major ticks indexes
* @function getMajorTicksIndexes
* @param ticks {Number[]} ticks array to process
* @param majorUnit {String} unit of major tick
* @return {Number[]} array of major ticks indexes
*/
getMajorTicksIndexes: function(ticks, majorUnit) {
var majorTicksIndexes = [];
if (majorUnit) {
for (var i = 0; i < ticks.length; i++) {
if (ticks[i] === moment(ticks[i]).startOf(majorUnit).valueOf()) {
majorTicksIndexes.push(i);
}
}
}
return majorTicksIndexes;
}

};
Expand Down
48 changes: 10 additions & 38 deletions src/scales/scale.time.js
Expand Up @@ -36,19 +36,6 @@ module.exports = function(Chart) {
},
ticks: {
autoSkip: false
},
majorTicks: {
beginAtZero: false,
minRotation: 0,
maxRotation: 50,
mirror: false,
padding: 0,
reverse: false,
display: true,
autoSkip: true,
autoSkipPadding: 0,
labelOffset: 0,
callback: Chart.Ticks.formatters.values
}
};

Expand All @@ -58,17 +45,8 @@ module.exports = function(Chart) {
throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com');
}

this.mergeTicksOptions();

Chart.Scale.prototype.initialize.call(this);
},
mergeTicksOptions: function() {
for (var key in this.options.ticks) {
if (typeof this.options.majorTicks[key] === 'undefined') {
this.options.majorTicks[key] = this.options.ticks[key];
}
}
},
determineDataLimits: function() {
var me = this;
var timeOpts = me.options.time;
Expand Down Expand Up @@ -167,6 +145,7 @@ module.exports = function(Chart) {
me.majorUnit = majorUnit;

var stepSize = timeOpts.stepSize || timeHelpers.determineStepSize(minTimestamp || dataMin, maxTimestamp || dataMax, unit, maxTicks);

me.ticks = timeHelpers.generateTicks({
maxTicks: maxTicks,
min: minTimestamp,
Expand All @@ -180,6 +159,8 @@ module.exports = function(Chart) {
max: dataMax
});

me.majorTicksIndexes = timeHelpers.getMajorTicksIndexes(me.ticks, me.majorUnit);

// At this point, we need to update our max and min given the tick values since we have expanded the
// range of the scale
me.max = helpers.max(me.ticks);
Expand All @@ -205,33 +186,23 @@ module.exports = function(Chart) {
// Function to format an individual tick mark
tickFormatFunction: function(tick, index, ticks) {
var formattedTick;
var tickClone = tick.clone();
var tickTimestamp = tick.valueOf();
var major = false;
var tickOpts;
if (this.majorUnit && this.majorDisplayFormat && tickTimestamp === tickClone.startOf(this.majorUnit).valueOf()) {
if (this.majorUnit && this.majorDisplayFormat && this.majorTicksIndexes.indexOf(index) !== -1) {
// format as senior unit
formattedTick = tick.format(this.majorDisplayFormat);
tickOpts = this.options.majorTicks;
major = true;
tickOpts = this.options.ticks.major;
} else {
// format as base unit
formattedTick = tick.format(this.displayFormat);
tickOpts = this.options.ticks;
tickOpts = this.options.ticks.minor;
}

var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback);

if (callback) {
return {
value: callback(formattedTick, index, ticks),
major: major
};
return callback(formattedTick, index, ticks);
}
return {
value: formattedTick,
major: major
};
return formattedTick;
},
convertTicksToLabels: function() {
var me = this;
Expand Down Expand Up @@ -293,13 +264,14 @@ module.exports = function(Chart) {
var cosRotation = Math.cos(helpers.toRadians(ticks.maxRotation));
var sinRotation = Math.sin(helpers.toRadians(ticks.maxRotation));
var tickFontSize = helpers.getValueOrDefault(ticks.fontSize, Chart.defaults.global.defaultFontSize);

return (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation);
},
getLabelCapacity: function(exampleTime) {
var me = this;

me.displayFormat = me.options.time.displayFormats.millisecond; // Pick the longest format for guestimation
var exampleLabel = me.tickFormatFunction(moment(exampleTime), 0, []).value;
var exampleLabel = me.tickFormatFunction(moment(exampleTime), 0, []);
var tickLabelWidth = me.getLabelWidth(exampleLabel);

var innerWidth = me.isHorizontal() ? me.width : me.height;
Expand Down
4 changes: 4 additions & 0 deletions test/specs/core.helpers.tests.js
Expand Up @@ -215,6 +215,8 @@ describe('Core helper tests', function() {
autoSkip: true,
autoSkipPadding: 0,
labelOffset: 0,
minor: { },
major: { }
},
type: 'linear'
}, {
Expand Down Expand Up @@ -253,6 +255,8 @@ describe('Core helper tests', function() {
autoSkip: true,
autoSkipPadding: 0,
labelOffset: 0,
minor: { },
major: { }
},
type: 'linear'
}]
Expand Down
4 changes: 3 additions & 1 deletion test/specs/scale.category.tests.js
Expand Up @@ -44,7 +44,9 @@ describe('Category scale tests', function() {
callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
autoSkip: true,
autoSkipPadding: 0,
labelOffset: 0
labelOffset: 0,
minor: { },
major: { }
}
});

Expand Down
4 changes: 3 additions & 1 deletion test/specs/scale.linear.tests.js
Expand Up @@ -42,7 +42,9 @@ describe('Linear Scale', function() {
callback: defaultConfig.ticks.callback, // make this work nicer, then check below
autoSkip: true,
autoSkipPadding: 0,
labelOffset: 0
labelOffset: 0,
minor: { },
major: { }
}
});

Expand Down
4 changes: 3 additions & 1 deletion test/specs/scale.logarithmic.tests.js
Expand Up @@ -41,7 +41,9 @@ describe('Logarithmic Scale tests', function() {
callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
autoSkip: true,
autoSkipPadding: 0,
labelOffset: 0
labelOffset: 0,
minor: { },
major: { }
},
});

Expand Down
4 changes: 3 additions & 1 deletion test/specs/scale.radialLinear.tests.js
Expand Up @@ -58,7 +58,9 @@ describe('Test the radial linear scale', function() {
callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
autoSkip: true,
autoSkipPadding: 0,
labelOffset: 0
labelOffset: 0,
minor: { },
major: { }
},
});

Expand Down

0 comments on commit 05cf849

Please sign in to comment.