From 6bc7e137a9de0055ee8557fe49c528081debff1a Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 7 Apr 2022 13:10:36 -0400 Subject: [PATCH 01/60] add minor tick and grid options to cartesian subplot --- src/plots/cartesian/layout_attributes.js | 311 +++++++++++++---------- test/plot-schema.json | 220 ++++++++++++++++ 2 files changed, 400 insertions(+), 131 deletions(-) diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index 219e2b314e9..3e259e19367 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -12,6 +12,152 @@ var constants = require('./constants'); var HOUR = constants.HOUR_PATTERN; var DAY_OF_WEEK = constants.WEEKDAY_PATTERN; +var tickmode = { + valType: 'enumerated', + values: ['auto', 'linear', 'array'], + editType: 'ticks', + impliedEdits: {tick0: undefined, dtick: undefined}, + description: [ + 'Sets the tick mode for this axis.', + 'If *auto*, the number of ticks is set via `nticks`.', + 'If *linear*, the placement of the ticks is determined by', + 'a starting position `tick0` and a tick step `dtick`', + '(*linear* is the default value if `tick0` and `dtick` are provided).', + 'If *array*, the placement of the ticks is set via `tickvals`', + 'and the tick text is `ticktext`.', + '(*array* is the default value if `tickvals` is provided).' + ].join(' ') +}; + +var nticks = { + valType: 'integer', + min: 0, + dflt: 0, + editType: 'ticks', + description: [ + 'Specifies the maximum number of ticks for the particular axis.', + 'The actual number of ticks will be chosen automatically to be', + 'less than or equal to `nticks`.', + 'Has an effect only if `tickmode` is set to *auto*.' + ].join(' ') +}; + +var tick0 = { + valType: 'any', + editType: 'ticks', + impliedEdits: {tickmode: 'linear'}, + description: [ + 'Sets the placement of the first tick on this axis.', + 'Use with `dtick`.', + 'If the axis `type` is *log*, then you must take the log of your starting tick', + '(e.g. to set the starting tick to 100, set the `tick0` to 2)', + 'except when `dtick`=*L* (see `dtick` for more info).', + 'If the axis `type` is *date*, it should be a date string, like date data.', + 'If the axis `type` is *category*, it should be a number, using the scale where', + 'each category is assigned a serial number from zero in the order it appears.' + ].join(' ') +}; + +var dtick = { + valType: 'any', + editType: 'ticks', + impliedEdits: {tickmode: 'linear'}, + description: [ + 'Sets the step in-between ticks on this axis. Use with `tick0`.', + 'Must be a positive number, or special strings available to *log* and *date* axes.', + 'If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n', + 'is the tick number. For example,', + 'to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1.', + 'To set tick marks at 1, 100, 10000, ... set dtick to 2.', + 'To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433.', + '*log* has several special values; *L*, where `f` is a positive number,', + 'gives ticks linearly spaced in value (but not position).', + 'For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc.', + 'To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5).', + '`tick0` is ignored for *D1* and *D2*.', + 'If the axis `type` is *date*, then you must convert the time to milliseconds.', + 'For example, to set the interval between ticks to one day,', + 'set `dtick` to 86400000.0.', + '*date* also has special values *M* gives ticks spaced by a number of months.', + '`n` must be a positive integer.', + 'To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*.', + 'To set ticks every 4 years, set `dtick` to *M48*' + ].join(' ') +}; + +var tickvals = { + valType: 'data_array', + editType: 'ticks', + description: [ + 'Sets the values at which ticks on this axis appear.', + 'Only has an effect if `tickmode` is set to *array*.', + 'Used with `ticktext`.' + ].join(' ') +}; + +var ticks = { + valType: 'enumerated', + values: ['outside', 'inside', ''], + editType: 'ticks', + description: [ + 'Determines whether ticks are drawn or not.', + 'If **, this axis\' ticks are not drawn.', + 'If *outside* (*inside*), this axis\' are drawn outside (inside)', + 'the axis lines.' + ].join(' ') +}; + +function makeTicklen(minor) { + return { + valType: 'number', + min: 0, + dflt: minor ? 3 : 5, + editType: 'ticks', + description: 'Sets the tick length (in px).' + }; +} + +var tickwidth = { + valType: 'number', + min: 0, + dflt: 1, + editType: 'ticks', + description: 'Sets the tick width (in px).' +}; + +var tickcolor = { + valType: 'color', + dflt: colorAttrs.defaultLine, + editType: 'ticks', + description: 'Sets the tick color.' +}; + +var gridcolor = { + valType: 'color', + dflt: colorAttrs.lightLine, + editType: 'ticks', + description: 'Sets the color of the grid lines.' +}; + +var gridwidth = { + valType: 'number', + min: 0, + dflt: 1, + editType: 'ticks', + description: 'Sets the width (in px) of the grid lines.' +}; + +var griddash = extendFlat({}, dash, {editType: 'ticks'}); + +var showgrid = { + valType: 'boolean', + editType: 'ticks', + description: [ + 'Determines whether or not grid lines are drawn.', + 'If *true*, the grid lines are drawn at every tick mark.' + ].join(' ') +}; + module.exports = { visible: { valType: 'boolean', @@ -343,75 +489,10 @@ module.exports = { }), // ticks - tickmode: { - valType: 'enumerated', - values: ['auto', 'linear', 'array'], - editType: 'ticks', - impliedEdits: {tick0: undefined, dtick: undefined}, - description: [ - 'Sets the tick mode for this axis.', - 'If *auto*, the number of ticks is set via `nticks`.', - 'If *linear*, the placement of the ticks is determined by', - 'a starting position `tick0` and a tick step `dtick`', - '(*linear* is the default value if `tick0` and `dtick` are provided).', - 'If *array*, the placement of the ticks is set via `tickvals`', - 'and the tick text is `ticktext`.', - '(*array* is the default value if `tickvals` is provided).' - ].join(' ') - }, - nticks: { - valType: 'integer', - min: 0, - dflt: 0, - editType: 'ticks', - description: [ - 'Specifies the maximum number of ticks for the particular axis.', - 'The actual number of ticks will be chosen automatically to be', - 'less than or equal to `nticks`.', - 'Has an effect only if `tickmode` is set to *auto*.' - ].join(' ') - }, - tick0: { - valType: 'any', - editType: 'ticks', - impliedEdits: {tickmode: 'linear'}, - description: [ - 'Sets the placement of the first tick on this axis.', - 'Use with `dtick`.', - 'If the axis `type` is *log*, then you must take the log of your starting tick', - '(e.g. to set the starting tick to 100, set the `tick0` to 2)', - 'except when `dtick`=*L* (see `dtick` for more info).', - 'If the axis `type` is *date*, it should be a date string, like date data.', - 'If the axis `type` is *category*, it should be a number, using the scale where', - 'each category is assigned a serial number from zero in the order it appears.' - ].join(' ') - }, - dtick: { - valType: 'any', - editType: 'ticks', - impliedEdits: {tickmode: 'linear'}, - description: [ - 'Sets the step in-between ticks on this axis. Use with `tick0`.', - 'Must be a positive number, or special strings available to *log* and *date* axes.', - 'If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n', - 'is the tick number. For example,', - 'to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1.', - 'To set tick marks at 1, 100, 10000, ... set dtick to 2.', - 'To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433.', - '*log* has several special values; *L*, where `f` is a positive number,', - 'gives ticks linearly spaced in value (but not position).', - 'For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc.', - 'To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5).', - '`tick0` is ignored for *D1* and *D2*.', - 'If the axis `type` is *date*, then you must convert the time to milliseconds.', - 'For example, to set the interval between ticks to one day,', - 'set `dtick` to 86400000.0.', - '*date* also has special values *M* gives ticks spaced by a number of months.', - '`n` must be a positive integer.', - 'To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*.', - 'To set ticks every 4 years, set `dtick` to *M48*' - ].join(' ') - }, + tickmode: tickmode, + nticks: nticks, + tick0: tick0, + dtick: dtick, ticklabelstep: { valType: 'integer', min: 1, @@ -426,15 +507,7 @@ module.exports = { 'Not implemented for axes with `type` *log* or *multicategory*, or when `tickmode` is *array*.' ].join(' ') }, - tickvals: { - valType: 'data_array', - editType: 'ticks', - description: [ - 'Sets the values at which ticks on this axis appear.', - 'Only has an effect if `tickmode` is set to *array*.', - 'Used with `ticktext`.' - ].join(' ') - }, + tickvals: tickvals, ticktext: { valType: 'data_array', editType: 'ticks', @@ -444,17 +517,7 @@ module.exports = { 'Used with `tickvals`.' ].join(' ') }, - ticks: { - valType: 'enumerated', - values: ['outside', 'inside', ''], - editType: 'ticks', - description: [ - 'Determines whether ticks are drawn or not.', - 'If **, this axis\' ticks are not drawn.', - 'If *outside* (*inside*), this axis\' are drawn outside (inside)', - 'the axis lines.' - ].join(' ') - }, + ticks: ticks, tickson: { valType: 'enumerated', values: ['labels', 'boundaries'], @@ -537,26 +600,9 @@ module.exports = { 'on all shared-axes subplots.' ].join(' ') }, - ticklen: { - valType: 'number', - min: 0, - dflt: 5, - editType: 'ticks', - description: 'Sets the tick length (in px).' - }, - tickwidth: { - valType: 'number', - min: 0, - dflt: 1, - editType: 'ticks', - description: 'Sets the tick width (in px).' - }, - tickcolor: { - valType: 'color', - dflt: colorAttrs.defaultLine, - editType: 'ticks', - description: 'Sets the tick color.' - }, + ticklen: makeTicklen(), + tickwidth: tickwidth, + tickcolor: tickcolor, showticklabels: { valType: 'boolean', dflt: true, @@ -776,28 +822,11 @@ module.exports = { editType: 'ticks+layoutstyle', description: 'Sets the width (in px) of the axis line.' }, - showgrid: { - valType: 'boolean', - editType: 'ticks', - description: [ - 'Determines whether or not grid lines are drawn.', - 'If *true*, the grid lines are drawn at every tick mark.' - ].join(' ') - }, - gridcolor: { - valType: 'color', - dflt: colorAttrs.lightLine, - editType: 'ticks', - description: 'Sets the color of the grid lines.' - }, - gridwidth: { - valType: 'number', - min: 0, - dflt: 1, - editType: 'ticks', - description: 'Sets the width (in px) of the grid lines.' - }, - griddash: extendFlat({}, dash, {editType: 'ticks'}), + showgrid: showgrid, + gridcolor: gridcolor, + gridwidth: gridwidth, + griddash: griddash, + zeroline: { valType: 'boolean', editType: 'ticks', @@ -899,6 +928,26 @@ module.exports = { 'axis will be visible.' ].join(' ') }, + + minor: { + tickmode: tickmode, + nticks: nticks, + tick0: tick0, + dtick: dtick, + tickvals: tickvals, + ticks: ticks, + ticklen: makeTicklen('minor'), + tickwidth: tickwidth, + tickcolor: tickcolor, + + gridcolor: gridcolor, + gridwidth: gridwidth, + griddash: griddash, + showgrid: showgrid, + + editType: 'ticks' + }, + layer: { valType: 'enumerated', values: ['above traces', 'below traces'], diff --git a/test/plot-schema.json b/test/plot-schema.json index a27fa752f29..68155278d42 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -9963,6 +9963,116 @@ "min": 0, "valType": "number" }, + "minor": { + "dtick": { + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*", + "editType": "ticks", + "impliedEdits": { + "tickmode": "linear" + }, + "valType": "any" + }, + "editType": "ticks", + "gridcolor": { + "description": "Sets the color of the grid lines.", + "dflt": "#eee", + "editType": "ticks", + "valType": "color" + }, + "griddash": { + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*).", + "dflt": "solid", + "editType": "ticks", + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ] + }, + "gridwidth": { + "description": "Sets the width (in px) of the grid lines.", + "dflt": 1, + "editType": "ticks", + "min": 0, + "valType": "number" + }, + "nticks": { + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*.", + "dflt": 0, + "editType": "ticks", + "min": 0, + "valType": "integer" + }, + "role": "object", + "showgrid": { + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark.", + "editType": "ticks", + "valType": "boolean" + }, + "tick0": { + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears.", + "editType": "ticks", + "impliedEdits": { + "tickmode": "linear" + }, + "valType": "any" + }, + "tickcolor": { + "description": "Sets the tick color.", + "dflt": "#444", + "editType": "ticks", + "valType": "color" + }, + "ticklen": { + "description": "Sets the tick length (in px).", + "dflt": 3, + "editType": "ticks", + "min": 0, + "valType": "number" + }, + "tickmode": { + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided).", + "editType": "ticks", + "impliedEdits": {}, + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ] + }, + "ticks": { + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "editType": "ticks", + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ] + }, + "tickvals": { + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "editType": "ticks", + "valType": "data_array" + }, + "tickvalssrc": { + "description": "Sets the source reference on Chart Studio Cloud for `tickvals`.", + "editType": "none", + "valType": "string" + }, + "tickwidth": { + "description": "Sets the tick width (in px).", + "dflt": 1, + "editType": "ticks", + "min": 0, + "valType": "number" + } + }, "mirror": { "description": "Determines if the axis lines or/and ticks are mirrored to the opposite side of the plotting area. If *true*, the axis lines are mirrored. If *ticks*, the axis lines and ticks are mirrored. If *false*, mirroring is disable. If *all*, axis lines are mirrored on all shared-axes subplots. If *allticks*, axis lines and ticks are mirrored on all shared-axes subplots.", "dflt": false, @@ -11095,6 +11205,116 @@ "min": 0, "valType": "number" }, + "minor": { + "dtick": { + "description": "Sets the step in-between ticks on this axis. Use with `tick0`. Must be a positive number, or special strings available to *log* and *date* axes. If the axis `type` is *log*, then ticks are set every 10^(n*dtick) where n is the tick number. For example, to set a tick mark at 1, 10, 100, 1000, ... set dtick to 1. To set tick marks at 1, 100, 10000, ... set dtick to 2. To set tick marks at 1, 5, 25, 125, 625, 3125, ... set dtick to log_10(5), or 0.69897000433. *log* has several special values; *L*, where `f` is a positive number, gives ticks linearly spaced in value (but not position). For example `tick0` = 0.1, `dtick` = *L0.5* will put ticks at 0.1, 0.6, 1.1, 1.6 etc. To show powers of 10 plus small digits between, use *D1* (all digits) or *D2* (only 2 and 5). `tick0` is ignored for *D1* and *D2*. If the axis `type` is *date*, then you must convert the time to milliseconds. For example, to set the interval between ticks to one day, set `dtick` to 86400000.0. *date* also has special values *M* gives ticks spaced by a number of months. `n` must be a positive integer. To set ticks on the 15th of every third month, set `tick0` to *2000-01-15* and `dtick` to *M3*. To set ticks every 4 years, set `dtick` to *M48*", + "editType": "ticks", + "impliedEdits": { + "tickmode": "linear" + }, + "valType": "any" + }, + "editType": "ticks", + "gridcolor": { + "description": "Sets the color of the grid lines.", + "dflt": "#eee", + "editType": "ticks", + "valType": "color" + }, + "griddash": { + "description": "Sets the dash style of lines. Set to a dash type string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*).", + "dflt": "solid", + "editType": "ticks", + "valType": "string", + "values": [ + "solid", + "dot", + "dash", + "longdash", + "dashdot", + "longdashdot" + ] + }, + "gridwidth": { + "description": "Sets the width (in px) of the grid lines.", + "dflt": 1, + "editType": "ticks", + "min": 0, + "valType": "number" + }, + "nticks": { + "description": "Specifies the maximum number of ticks for the particular axis. The actual number of ticks will be chosen automatically to be less than or equal to `nticks`. Has an effect only if `tickmode` is set to *auto*.", + "dflt": 0, + "editType": "ticks", + "min": 0, + "valType": "integer" + }, + "role": "object", + "showgrid": { + "description": "Determines whether or not grid lines are drawn. If *true*, the grid lines are drawn at every tick mark.", + "editType": "ticks", + "valType": "boolean" + }, + "tick0": { + "description": "Sets the placement of the first tick on this axis. Use with `dtick`. If the axis `type` is *log*, then you must take the log of your starting tick (e.g. to set the starting tick to 100, set the `tick0` to 2) except when `dtick`=*L* (see `dtick` for more info). If the axis `type` is *date*, it should be a date string, like date data. If the axis `type` is *category*, it should be a number, using the scale where each category is assigned a serial number from zero in the order it appears.", + "editType": "ticks", + "impliedEdits": { + "tickmode": "linear" + }, + "valType": "any" + }, + "tickcolor": { + "description": "Sets the tick color.", + "dflt": "#444", + "editType": "ticks", + "valType": "color" + }, + "ticklen": { + "description": "Sets the tick length (in px).", + "dflt": 3, + "editType": "ticks", + "min": 0, + "valType": "number" + }, + "tickmode": { + "description": "Sets the tick mode for this axis. If *auto*, the number of ticks is set via `nticks`. If *linear*, the placement of the ticks is determined by a starting position `tick0` and a tick step `dtick` (*linear* is the default value if `tick0` and `dtick` are provided). If *array*, the placement of the ticks is set via `tickvals` and the tick text is `ticktext`. (*array* is the default value if `tickvals` is provided).", + "editType": "ticks", + "impliedEdits": {}, + "valType": "enumerated", + "values": [ + "auto", + "linear", + "array" + ] + }, + "ticks": { + "description": "Determines whether ticks are drawn or not. If **, this axis' ticks are not drawn. If *outside* (*inside*), this axis' are drawn outside (inside) the axis lines.", + "editType": "ticks", + "valType": "enumerated", + "values": [ + "outside", + "inside", + "" + ] + }, + "tickvals": { + "description": "Sets the values at which ticks on this axis appear. Only has an effect if `tickmode` is set to *array*. Used with `ticktext`.", + "editType": "ticks", + "valType": "data_array" + }, + "tickvalssrc": { + "description": "Sets the source reference on Chart Studio Cloud for `tickvals`.", + "editType": "none", + "valType": "string" + }, + "tickwidth": { + "description": "Sets the tick width (in px).", + "dflt": 1, + "editType": "ticks", + "min": 0, + "valType": "number" + } + }, "mirror": { "description": "Determines if the axis lines or/and ticks are mirrored to the opposite side of the plotting area. If *true*, the axis lines are mirrored. If *ticks*, the axis lines and ticks are mirrored. If *false*, mirroring is disable. If *all*, axis lines are mirrored on all shared-axes subplots. If *allticks*, axis lines and ticks are mirrored on all shared-axes subplots.", "dflt": false, From 08c61f7a67a3a32f3a4a5f0edc825fd0b8d4ca80 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 7 Apr 2022 13:11:32 -0400 Subject: [PATCH 02/60] supply deafults for minor ticks and grids --- src/plots/cartesian/axis_defaults.js | 21 ++++++++++++++++ src/plots/cartesian/layout_defaults.js | 1 + src/plots/cartesian/line_grid_defaults.js | 28 ++++++++++++++++++--- src/plots/cartesian/tick_mark_defaults.js | 20 +++++++++------ src/plots/cartesian/tick_value_defaults.js | 29 ++++++++++++++-------- 5 files changed, 78 insertions(+), 21 deletions(-) diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index 434b076a845..8156467815c 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -4,6 +4,7 @@ var isNumeric = require('fast-isnumeric'); var Registry = require('../../registry'); var Lib = require('../../lib'); +var Template = require('../../plot_api/plot_template'); var handleArrayContainerDefaults = require('../array_container_defaults'); @@ -121,16 +122,36 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, color: dfltFontColor }); + // major ticks handleTickValueDefaults(containerIn, containerOut, coerce, axType); + + var hasMinor = options.hasMinor; + if(hasMinor) { + // minor ticks + Template.newContainer(containerOut, 'minor'); + handleTickValueDefaults(containerIn, containerOut, coerce, axType, { isMinor: true }); + } + handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options); + + // major and minor ticks handleTickMarkDefaults(containerIn, containerOut, coerce, options); + if(hasMinor) { + var keepIsMinor = options.isMinor; + options.isMinor = true; + handleTickMarkDefaults(containerIn, containerOut, coerce, options); + options.isMinor = keepIsMinor; + } + handleLineGridDefaults(containerIn, containerOut, coerce, { dfltColor: dfltColor, bgColor: options.bgColor, showGrid: options.showGrid, + hasMinor: hasMinor, attributes: layoutAttributes }); + // mirror if(containerOut.showline || containerOut.ticks) coerce('mirror'); if(options.automargin) coerce('automargin'); diff --git a/src/plots/cartesian/layout_defaults.js b/src/plots/cartesian/layout_defaults.js index dc703752eb7..c24a7c34f1a 100644 --- a/src/plots/cartesian/layout_defaults.js +++ b/src/plots/cartesian/layout_defaults.js @@ -229,6 +229,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { )); var defaultOptions = { + hasMinor: true, letter: axLetter, font: layoutOut.font, outerTicks: outerTicks[axName], diff --git a/src/plots/cartesian/line_grid_defaults.js b/src/plots/cartesian/line_grid_defaults.js index fe04c508c8f..aa9d0090437 100644 --- a/src/plots/cartesian/line_grid_defaults.js +++ b/src/plots/cartesian/line_grid_defaults.js @@ -1,7 +1,7 @@ 'use strict'; var colorMix = require('tinycolor2').mix; -var lightFraction = require('../../components/color/attributes').lightFraction; +var colorAttrs = require('../../components/color/attributes'); var Lib = require('../../lib'); /** @@ -32,11 +32,15 @@ module.exports = function handleLineGridDefaults(containerIn, containerOut, coer delete containerOut.linewidth; } - var gridColorDflt = colorMix(dfltColor, opts.bgColor, opts.blend || lightFraction).toRgbString(); + var gridColorDflt = colorMix(dfltColor, opts.bgColor, opts.blend || colorAttrs.lightFraction).toRgbString(); var gridColor = coerce2('gridcolor', gridColorDflt); var gridWidth = coerce2('gridwidth'); var gridDash = coerce2('griddash'); - var showGridLines = coerce('showgrid', opts.showGrid || !!gridColor || !!gridWidth || !!gridDash); + var showGridLines = coerce('showgrid', opts.showGrid || + !!gridColor || + !!gridWidth || + !!gridDash + ); if(!showGridLines) { delete containerOut.gridcolor; @@ -44,6 +48,24 @@ module.exports = function handleLineGridDefaults(containerIn, containerOut, coer delete containerOut.griddash; } + if(opts.hasMinor) { + var minorGridColorDflt = colorMix(gridColor || gridColorDflt, opts.bgColor).toRgbString(); + var minorGridColor = coerce2('minor.gridcolor', minorGridColorDflt); + var minorGridWidth = coerce2('minor.gridwidth'); + var minorGridDash = coerce2('minor.griddash'); + var minorShowGridLines = coerce('minor.showgrid', + !!minorGridColor || + !!minorGridWidth || + !!minorGridDash + ); + + if(!minorShowGridLines) { + delete containerOut.minor.gridcolor; + delete containerOut.minor.gridwidth; + delete containerOut.minor.griddash; + } + } + if(!opts.noZeroLine) { var zeroLineColor = coerce2('zerolinecolor', dfltColor); var zeroLineWidth = coerce2('zerolinewidth'); diff --git a/src/plots/cartesian/tick_mark_defaults.js b/src/plots/cartesian/tick_mark_defaults.js index 6a76c37142b..71990313b85 100644 --- a/src/plots/cartesian/tick_mark_defaults.js +++ b/src/plots/cartesian/tick_mark_defaults.js @@ -9,14 +9,20 @@ var layoutAttributes = require('./layout_attributes'); * options: inherits outerTicks from axes.handleAxisDefaults */ module.exports = function handleTickMarkDefaults(containerIn, containerOut, coerce, options) { - var tickLen = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'ticklen'); - var tickWidth = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'tickwidth'); - var tickColor = Lib.coerce2(containerIn, containerOut, layoutAttributes, 'tickcolor', containerOut.color); - var showTicks = coerce('ticks', (options.outerTicks || tickLen || tickWidth || tickColor) ? 'outside' : ''); + var isMinor = options.isMinor; + var cIn = isMinor ? containerIn.minor || {} : containerIn; + var cOut = isMinor ? containerOut.minor : containerOut; + var lAttr = isMinor ? layoutAttributes.minor : layoutAttributes; + var prefix = isMinor ? 'minor.' : ''; + + var tickLen = Lib.coerce2(cIn, cOut, lAttr, 'ticklen'); + var tickWidth = Lib.coerce2(cIn, cOut, lAttr, 'tickwidth'); + var tickColor = Lib.coerce2(cIn, cOut, lAttr, 'tickcolor', cOut.color); + var showTicks = coerce(prefix + 'ticks', ((!isMinor && options.outerTicks) || tickLen || tickWidth || tickColor) ? 'outside' : ''); if(!showTicks) { - delete containerOut.ticklen; - delete containerOut.tickwidth; - delete containerOut.tickcolor; + delete cOut.ticklen; + delete cOut.tickwidth; + delete cOut.tickcolor; } }; diff --git a/src/plots/cartesian/tick_value_defaults.js b/src/plots/cartesian/tick_value_defaults.js index 1b6a06902b3..e6ffb8f6a5d 100644 --- a/src/plots/cartesian/tick_value_defaults.js +++ b/src/plots/cartesian/tick_value_defaults.js @@ -3,12 +3,18 @@ var cleanTicks = require('./clean_ticks'); var isArrayOrTypedArray = require('../../lib').isArrayOrTypedArray; -module.exports = function handleTickValueDefaults(containerIn, containerOut, coerce, axType) { +module.exports = function handleTickValueDefaults(containerIn, containerOut, coerce, axType, opts) { + if(!opts) opts = {}; + var isMinor = opts.isMinor; + var cIn = isMinor ? containerIn.minor || {} : containerIn; + var cOut = isMinor ? containerOut.minor : containerOut; + var prefix = isMinor ? 'minor.' : ''; + function readInput(attr) { - var v = containerIn[attr]; + var v = cIn[attr]; return ( v !== undefined - ) ? v : (containerOut._template || {})[attr]; + ) ? v : (cOut._template || {})[attr]; } var _tick0 = readInput('tick0'); @@ -18,20 +24,21 @@ module.exports = function handleTickValueDefaults(containerIn, containerOut, coe var tickmodeDefault = isArrayOrTypedArray(_tickvals) ? 'array' : _dtick ? 'linear' : 'auto'; - var tickmode = coerce('tickmode', tickmodeDefault); + var tickmode = coerce(prefix + 'tickmode', tickmodeDefault); - if(tickmode === 'auto') coerce('nticks'); - else if(tickmode === 'linear') { + if(tickmode === 'auto') { + coerce(prefix + 'nticks'); + } else if(tickmode === 'linear') { // dtick is usually a positive number, but there are some // special strings available for log or date axes // tick0 also has special logic - var dtick = containerOut.dtick = cleanTicks.dtick( + var dtick = cOut.dtick = cleanTicks.dtick( _dtick, axType); - containerOut.tick0 = cleanTicks.tick0( + cOut.tick0 = cleanTicks.tick0( _tick0, axType, containerOut.calendar, dtick); } else if(axType !== 'multicategory') { - var tickvals = coerce('tickvals'); - if(tickvals === undefined) containerOut.tickmode = 'auto'; - else coerce('ticktext'); + var tickvals = coerce(prefix + 'tickvals'); + if(tickvals === undefined) cOut.tickmode = 'auto'; + else if(!isMinor) coerce('ticktext'); } }; From eaa8e71d47dd3de65ea688841f04f2431afdd880 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 7 Apr 2022 13:12:04 -0400 Subject: [PATCH 03/60] draw minor ticks and grid lines --- src/plots/cartesian/axes.js | 353 +++++++++++++++++++++++++++--------- 1 file changed, 270 insertions(+), 83 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 0b5389d3716..55f621d8564 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -839,7 +839,8 @@ axes.calcTicks = function calcTicks(ax, opts) { var maxTicks = Math.max(1000, ax._length || 0); var tickVals = []; - var xPrevious = null; + var minorTickVals = []; + var prevX = null; var dTick; if(numDtick) { @@ -860,7 +861,9 @@ axes.calcTicks = function calcTicks(ax, opts) { ) / dTick) - 1; for(; - (axrev) ? (x >= endTick) : (x <= endTick); + axrev ? + (x >= endTick) : + (x <= endTick); x = axes.tickIncrement(x, ax.dtick, axrev, ax.calendar) ) { id++; @@ -874,24 +877,112 @@ axes.calcTicks = function calcTicks(ax, opts) { // prevent infinite loops - no more than one tick per pixel, // and make sure each value is different from the previous - if(tickVals.length > maxTicks || x === xPrevious) break; - xPrevious = x; + if(tickVals.length > maxTicks || x === prevX) break; + prevX = x; + + var obj = { value: x }; - var minor = false; if(isDLog && (x !== (x | 0))) { - minor = true; + obj.simpleLabel = true; } - var obj = { - minor: minor, - value: x - }; - if(ticklabelstep > 1 && id % ticklabelstep) { obj.skipLabel = true; } tickVals.push(obj); + + if(ax.minor && ( + ax.minor.ticks || + ax.minor.showgrid + )) { + var minorDtick = ax.minor.dtick; + + if(!minorDtick) { + var mockAxis = Lib.extendFlat({}, ax.minor, { + r2l: ax.r2l, + type: ax.type, + range: ax.range, + calendar: ax.calendar + }); + + var minorRoughDtick = 1; + if(ax._roughDTick) { + minorRoughDtick = ax._roughDTick / ( + ax.type === 'log' ? 5 : + ax.type === 'date' ? 3 : + ax.type === 'linear' ? 4 : 2 + ); + } + + axes.autoTicks(mockAxis, minorRoughDtick, true); + + minorDtick = mockAxis.dtick; + var majorDtick = ax.dtick; + + var haveM = ax.type === 'date' && + typeof majorDtick === 'string' && majorDtick.charAt(0) === 'M' && + typeof minorDtick === 'string' && minorDtick.charAt(0) === 'M'; + + if(haveM) { + // without M + majorDtick = majorDtick.slice(1); + minorDtick = minorDtick.slice(1); + } + + var ratio = minorDtick / majorDtick; + if( + ratio === 2 / 5 || + ratio === 2 / 7 + ) { + minorDtick /= 2; + } + + if(haveM) { + // with M + majorDtick = 'M' + majorDtick; + minorDtick = 'M' + minorDtick; + } + } + + var nextTick = axes.tickIncrement(x, ax.dtick, axrev, ax.calendar); + var prevTick = tickVals.length > 1 ? x : + axes.tickIncrement(x, ax.dtick, !axrev, ax.calendar); + + var canOverlap = ( + (ax.minor.ticks === 'inside' && ax.ticks === 'outside') || + (ax.minor.ticks === 'outside' && ax.ticks === 'inside') + ); + + var minorX = prevTick; + if(!canOverlap) { + minorX = axes.tickIncrement(prevTick, minorDtick, axrev, ax.calendar); + } + + var prevMinorX = null; + for(; + axrev ? + (minorX > nextTick) : + (minorX < nextTick); + minorX = axes.tickIncrement(minorX, minorDtick, axrev, ax.calendar) + ) { + // prevent infinite loops - no more than one tick per pixel, + // and make sure each value is different from the previous + if(minorTickVals.length > maxTicks || minorX === prevMinorX) break; + prevMinorX = minorX; + + if( + minorX >= minRange && + minorX <= maxRange && + (canOverlap || minorX !== x) + ) { + minorTickVals.push({ + value: minorX, + minor: true + }); + } + } + } } if(isPeriod) positionPeriodTicks(tickVals, ax, ax._definedDelta); @@ -950,38 +1041,49 @@ axes.calcTicks = function calcTicks(ax, opts) { ax._prevDateHead = lastVisibleHead; }; + tickVals = tickVals.concat(minorTickVals); + var ticksOut = []; + var minorTicks = []; var t, p; for(i = 0; i < tickVals.length; i++) { var _minor = tickVals[i].minor; var _value = tickVals[i].value; - lastVisibleHead = ax._prevDateHead; + if(_minor) { + minorTicks.push({ + x: _value, + minor: true + }); + } else { + lastVisibleHead = ax._prevDateHead; - t = axes.tickText( - ax, - _value, - false, // hover - _minor // noSuffixPrefix - ); + t = axes.tickText( + ax, + _value, + false, // hover + tickVals[i].simpleLabel // noSuffixPrefix + ); - p = tickVals[i].periodX; - if(p !== undefined) { - t.periodX = p; - if(p > maxRange || p < minRange) { // hide label if outside the range - if(p > maxRange) t.periodX = maxRange; - if(p < minRange) t.periodX = minRange; + p = tickVals[i].periodX; + if(p !== undefined) { + t.periodX = p; + if(p > maxRange || p < minRange) { // hide label if outside the range + if(p > maxRange) t.periodX = maxRange; + if(p < minRange) t.periodX = minRange; + hideLabel(t); + } + } + + if(tickVals[i].skipLabel) { hideLabel(t); } - } - if(tickVals[i].skipLabel) { - hideLabel(t); + ticksOut.push(t); } - - ticksOut.push(t); } + ticksOut = ticksOut.concat(minorTicks); ax._inCalcTicks = false; @@ -994,18 +1096,10 @@ axes.calcTicks = function calcTicks(ax, opts) { }; function arrayTicks(ax) { - var vals = ax.tickvals; - var text = ax.ticktext; - var ticksOut = new Array(vals.length); var rng = Lib.simpleMap(ax.range, ax.r2l); var exRng = expandRange(rng); var tickMin = Math.min(exRng[0], exRng[1]); var tickMax = Math.max(exRng[0], exRng[1]); - var j = 0; - - // without a text array, just format the given values as any other ticks - // except with more precision to the numbers - if(!Array.isArray(text)) text = []; // make sure showing ticks doesn't accidentally add new categories // TODO multicategory, if we allow ticktext / tickvals @@ -1017,17 +1111,36 @@ function arrayTicks(ax) { ax.dtick = 'L' + Math.pow(10, Math.floor(Math.min(ax.range[0], ax.range[1])) - 1); } - for(var i = 0; i < vals.length; i++) { - var vali = tickVal2l(vals[i]); - if(vali > tickMin && vali < tickMax) { - if(text[i] === undefined) ticksOut[j] = axes.tickText(ax, vali); - else ticksOut[j] = tickTextObj(ax, vali, String(text[i])); - j++; + var ticksOut = []; + for(var isMinor = 0; isMinor <= 1; isMinor++) { + if(isMinor && !ax.minor) continue; + var vals = !isMinor ? ax.tickvals : ax.minor.tickvals; + var text = !isMinor ? ax.ticktext : []; + + if(!vals) continue; + + + // without a text array, just format the given values as any other ticks + // except with more precision to the numbers + if(!Array.isArray(text)) text = []; + + for(var i = 0; i < vals.length; i++) { + var vali = tickVal2l(vals[i]); + if(vali > tickMin && vali < tickMax) { + var obj = text[i] === undefined ? + axes.tickText(ax, vali) : + tickTextObj(ax, vali, String(text[i])); + + if(isMinor) { + obj.minor = true; + obj.text = ''; + } + + ticksOut.push(obj); + } } } - if(j < vals.length) ticksOut.splice(j, vals.length - j); - if(ax.rangebreaks) { // remove ticks falling inside rangebreaks ticksOut = ticksOut.filter(function(d) { @@ -1070,7 +1183,7 @@ function roundDTick(roughDTick, base, roundingSet) { // log with linear ticks: L# where # is the linear tick spacing // log showing powers plus some intermediates: // D1 shows all digits, D2 shows 2 and 5 -axes.autoTicks = function(ax, roughDTick) { +axes.autoTicks = function(ax, roughDTick, isMinor) { var base; function getBase(v) { @@ -1092,7 +1205,7 @@ axes.autoTicks = function(ax, roughDTick) { roughDTick /= ONEAVGMONTH; ax.dtick = 'M' + roundDTick(roughDTick, 1, roundBase24); } else if(roughX2 > ONEDAY) { - ax.dtick = roundDTick(roughDTick, ONEDAY, ax._hasDayOfWeekBreaks ? [1, 2, 7, 14] : roundDays); + ax.dtick = roundDTick(roughDTick, ONEDAY, isMinor ? [1] : ax._hasDayOfWeekBreaks ? [1, 2, 7, 14] : roundDays); // get week ticks on sunday // this will also move the base tick off 2000-01-01 if dtick is // 2 or 3 days... but that's a weird enough case that we'll ignore it. @@ -2173,21 +2286,32 @@ axes.drawOne = function(gd, ax, opts) { } } - var tickSigns = axes.getTickSigns(ax); - var tickPath; - if(ax.ticks) { - var mainTickPath; - var mirrorTickPath; - var fullTickPath; - mainTickPath = axes.makeTickPath(ax, mainLinePosition, tickSigns[2]); + var majorTickSigns = axes.getTickSigns(ax); + var minorTickSigns = axes.getTickSigns(ax, 'minor'); + + if(ax.ticks || (ax.minor && ax.minor.ticks)) { + var majorTickPath = axes.makeTickPath(ax, mainLinePosition, majorTickSigns[2]); + var minorTickPath = axes.makeTickPath(ax, mainLinePosition, minorTickSigns[2], { minor: true }); + + var mirrorMajorTickPath; + var mirrorMinorTickPath; + + var fullMajorTickPath; + var fullMinorTickPath; + if(ax._anchorAxis && ax.mirror && ax.mirror !== true) { - mirrorTickPath = axes.makeTickPath(ax, mainMirrorPosition, tickSigns[3]); - fullTickPath = mainTickPath + mirrorTickPath; + mirrorMajorTickPath = axes.makeTickPath(ax, mainMirrorPosition, majorTickSigns[3]); + mirrorMinorTickPath = axes.makeTickPath(ax, mainMirrorPosition, minorTickSigns[3], { minor: true }); + + fullMajorTickPath = majorTickPath + mirrorMajorTickPath; + fullMinorTickPath = minorTickPath + mirrorMinorTickPath; } else { - mirrorTickPath = ''; - fullTickPath = mainTickPath; + mirrorMajorTickPath = ''; + mirrorMinorTickPath = ''; + fullMajorTickPath = majorTickPath; + fullMinorTickPath = minorTickPath; } if(ax.showdividers && outsideTicks && ax.tickson === 'boundaries') { @@ -2196,10 +2320,12 @@ axes.drawOne = function(gd, ax, opts) { dividerLookup[dividerVals[i].x] = 1; } tickPath = function(d) { - return dividerLookup[d.x] ? mirrorTickPath : fullTickPath; + return dividerLookup[d.x] ? mirrorMajorTickPath : fullMajorTickPath; }; } else { - tickPath = fullTickPath; + tickPath = function(d) { + return d.minor ? fullMinorTickPath : fullMajorTickPath; + }; } } @@ -2218,8 +2344,20 @@ axes.drawOne = function(gd, ax, opts) { plotinfo = fullLayout._plots[sp]; // [bottom or left, top or right], free and main are handled above var linepositions = ax._linepositions[sp] || []; - var spTickPath = axes.makeTickPath(ax, linepositions[0], tickSigns[0]) + - axes.makeTickPath(ax, linepositions[1], tickSigns[1]); + + var p0 = linepositions[0]; + var p1 = linepositions[1]; + var isMinor = linepositions[2]; + + var spTickPath = + axes.makeTickPath(ax, p0, + isMinor ? majorTickSigns[0] : minorTickSigns[0], + { minor: isMinor } + ) + + axes.makeTickPath(ax, p1, + isMinor ? majorTickSigns[1] : minorTickSigns[1], + { minor: isMinor } + ); axes.drawTicks(gd, ax, { vals: tickVals, @@ -2260,23 +2398,23 @@ axes.drawOne = function(gd, ax, opts) { repositionOnUpdate: true, secondary: true, transFn: transTickFn, - labelFns: axes.makeLabelFns(ax, mainLinePosition + standoff * tickSigns[4]) + labelFns: axes.makeLabelFns(ax, mainLinePosition + standoff * majorTickSigns[4]) }); }); seq.push(function() { - ax._depth = tickSigns[4] * (getLabelLevelBbox('tick2')[ax.side] - mainLinePosition); + ax._depth = majorTickSigns[4] * (getLabelLevelBbox('tick2')[ax.side] - mainLinePosition); return drawDividers(gd, ax, { vals: dividerVals, layer: mainAxLayer, - path: axes.makeTickPath(ax, mainLinePosition, tickSigns[4], ax._depth), + path: axes.makeTickPath(ax, mainLinePosition, majorTickSigns[4], { len: ax._depth }), transFn: transTickFn }); }); } else if(ax.title.hasOwnProperty('standoff')) { seq.push(function() { - ax._depth = tickSigns[4] * (getLabelLevelBbox()[ax.side] - mainLinePosition); + ax._depth = majorTickSigns[4] * (getLabelLevelBbox()[ax.side] - mainLinePosition); }); } @@ -2517,13 +2655,15 @@ function calcLabelLevelBbox(ax, cls) { * - [3]: sign for ticks mirroring 'ax.side' * - [4]: sign of arrow starting at axis pointing towards margin */ -axes.getTickSigns = function(ax) { +axes.getTickSigns = function(ax, minor) { var axLetter = ax._id.charAt(0); var sideOpposite = {x: 'top', y: 'right'}[axLetter]; var main = ax.side === sideOpposite ? 1 : -1; var out = [-1, 1, main, -main]; // then we flip if outside XOR y axis - if((ax.ticks !== 'inside') === (axLetter === 'x')) { + + var ticks = minor ? ax.minor.ticks : ax.ticks; + if((ticks !== 'inside') === (axLetter === 'x')) { out = out.map(function(v) { return -v; }); } // independent of `ticks`; do not flip this one @@ -2627,11 +2767,15 @@ function getTickLabelUV(ax) { * - {number} linewidth * @param {number} shift along direction of ticklen * @param {1 or -1} sgn tick sign - * @param {number (optional)} len tick length + * @param {object} opts + * - {number (optional)} len tick length * @return {string} */ -axes.makeTickPath = function(ax, shift, sgn, len) { - len = len !== undefined ? len : ax.ticklen; +axes.makeTickPath = function(ax, shift, sgn, opts) { + if(!opts) opts = {}; + var minor = opts.minor; + var len = opts.len !== undefined ? opts.len : + minor ? ax.minor.ticklen : ax.ticklen; var axLetter = ax._id.charAt(0); var pad = (ax.linewidth || 1) / 2; @@ -2838,10 +2982,20 @@ axes.drawTicks = function(gd, ax, opts) { var cls = ax._id + 'tick'; - var vals = opts.vals.filter(function(e) { return !e.noTick; }); + var vals = [] + .concat(ax.minor && ax.minor.ticks ? + // minor vals + opts.vals.filter(function(d) { return d.minor && !d.noTick; }) : + [] + ) + .concat(ax.ticks ? + // major vals + opts.vals.filter(function(d) { return !d.minor && !d.noTick; }) : + [] + ); var ticks = opts.layer.selectAll('path.' + cls) - .data(ax.ticks ? vals : [], tickDataFn); + .data(vals, tickDataFn); ticks.exit().remove(); @@ -2849,8 +3003,16 @@ axes.drawTicks = function(gd, ax, opts) { .classed(cls, 1) .classed('ticks', 1) .classed('crisp', opts.crisp !== false) - .call(Color.stroke, ax.tickcolor) - .style('stroke-width', Drawing.crispRound(gd, ax.tickwidth, 1) + 'px') + .each(function(d) { + return Color.stroke(d3.select(this), d.minor ? ax.minor.tickcolor : ax.tickcolor); + }) + .style('stroke-width', function(d) { + return Drawing.crispRound( + gd, + d.minor ? ax.minor.tickwidth : ax.tickwidth, + 1 + ) + 'px'; + }) .attr('d', opts.path) .style('display', null); // visible @@ -2885,11 +3047,21 @@ axes.drawGrid = function(gd, ax, opts) { opts = opts || {}; var cls = ax._id + 'grid'; - var vals = opts.vals; + + var vals = [] + .concat(ax.minor && ax.minor.showgrid ? + // minor vals + opts.vals.filter(function(d) { return d.minor; }) : + [] + ) + .concat(ax.showgrid ? + // major vals + opts.vals.filter(function(d) { return !d.minor; }) : + [] + ); + var counterAx = opts.counterAxis; - if(ax.showgrid === false) { - vals = []; - } else if(counterAx && axes.shouldShowZeroLine(gd, ax, counterAx)) { + if(counterAx && axes.shouldShowZeroLine(gd, ax, counterAx)) { var isArrayMode = ax.tickmode === 'array'; for(var i = 0; i < vals.length; i++) { var xi = vals[i].x; @@ -2917,9 +3089,24 @@ axes.drawGrid = function(gd, ax, opts) { grid.attr('transform', opts.transFn) .attr('d', opts.path) - .call(Color.stroke, ax.gridcolor || '#ddd') - .style('stroke-dasharray', Drawing.dashStyle(ax.griddash, ax.gridwidth)) - .style('stroke-width', ax._gw + 'px') + .each(function(d) { + return Color.stroke(d3.select(this), d.minor ? + ax.minor.gridcolor : + (ax.gridcolor || '#ddd') + ); + }) + .style('stroke-dasharray', function(d) { + return Drawing.dashStyle( + d.minor ? ax.minor.griddash : ax.griddash, + d.minor ? ax.minor.gridwidth : ax.gridwidth + ); + }) + .style('stroke-width', function(d) { + return (d.minor ? + Drawing.crispRound(gd, ax.minor.gridwidth, 1) : + ax._gw + ) + 'px'; + }) .style('display', null); // visible hideCounterAxisInsideTickLabels(ax, [GRID_PATH]); @@ -3009,7 +3196,7 @@ axes.drawLabels = function(gd, ax, opts) { var axLetter = axId.charAt(0); var cls = opts.cls || axId + 'tick'; - var vals = opts.vals.filter(function(e) { return e.text; }); + var vals = opts.vals.filter(function(d) { return d.text; }); var labelFns = opts.labelFns; var tickAngle = opts.secondary ? 0 : ax.tickangle; From 64576fceb2d8064dbe92a0b2aeec677ed6e08fb3 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 7 Apr 2022 13:12:54 -0400 Subject: [PATCH 04/60] minor image test 11 --- test/image/baselines/11.png | Bin 28060 -> 30896 bytes test/image/mocks/11.json | 1 + 2 files changed, 1 insertion(+) diff --git a/test/image/baselines/11.png b/test/image/baselines/11.png index dcdd4a2ca6caa684b37416b16b44c0e00d8b5405..a6adeaaeed5020ce2127c3f9cf14b6d6da4102ba 100644 GIT binary patch literal 30896 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

)&U8TfbnN{y=D%7)QsH%+H}2j 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 literal 28060 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 diff --git a/test/image/mocks/11.json b/test/image/mocks/11.json index b2091806455..dc6197eb91d 100644 --- a/test/image/mocks/11.json +++ b/test/image/mocks/11.json @@ -176,6 +176,7 @@ "autorange": true }, "yaxis": { + "minor": { "showgrid": true }, "title": { "text": "Length", "font": { From 58958ff179fc50c3bfea65b9bbd719a9d782c4f5 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 7 Apr 2022 13:13:04 -0400 Subject: [PATCH 05/60] minor image test 14 --- test/image/baselines/14.png | Bin 55621 -> 60569 bytes test/image/mocks/14.json | 1 + 2 files changed, 1 insertion(+) diff --git a/test/image/baselines/14.png b/test/image/baselines/14.png index a8bf354b7c3efc9bd9d77d0a01976880d63506ad..b9139fda662b4bd4f21b187a916bbfd1cfd98f0d 100644 GIT binary patch literal 60569 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