Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add borderDash options to arc element #11127

Merged
merged 1 commit into from
Feb 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/charts/doughnut.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ The doughnut/pie chart allows a number of properties to be specified for each da
| [`backgroundColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
| [`borderAlign`](#border-alignment) | `'center'`\|`'inner'` | Yes | Yes | `'center'`
| [`borderColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'#fff'`
| [`borderDash`](#styling) | `number[]` | Yes | - | `[]`
| [`borderDashOffset`](#styling) | `number` | Yes | - | `0.0`
| [`borderJoinStyle`](#styling) | `'round'`\|`'bevel'`\|`'miter'` | Yes | Yes | `undefined`
| [`borderRadius`](#border-radius) | `number`\|`object` | Yes | Yes | `0`
| [`borderWidth`](#styling) | `number` | Yes | Yes | `2`
Expand All @@ -113,6 +115,8 @@ The doughnut/pie chart allows a number of properties to be specified for each da
| [`data`](#data-structure) | `number[]` | - | - | **required**
| [`hoverBackgroundColor`](#interactions) | [`Color`](../general/colors.md) | Yes | Yes | `undefined`
| [`hoverBorderColor`](#interactions) | [`Color`](../general/colors.md) | Yes | Yes | `undefined`
| [`hoverBorderDash`](#interactions) | `number[]` | Yes | - | `undefined`
| [`hoverBorderDashOffset`](#interactions) | `number` | Yes | - | `undefined`
| [`hoverBorderJoinStyle`](#interactions) | `'round'`\|`'bevel'`\|`'miter'` | Yes | Yes | `undefined`
| [`hoverBorderWidth`](#interactions) | `number` | Yes | Yes | `undefined`
| [`hoverOffset`](#interactions) | `number` | Yes | Yes | `0`
Expand All @@ -139,6 +143,8 @@ The style of each arc can be controlled with the following properties:
| ---- | ----
| `backgroundColor` | arc background color.
| `borderColor` | arc border color.
| `borderDash` | arc border length and spacing of dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash).
| `borderDashOffset` | arc border offset for line dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
| `borderJoinStyle` | arc border join style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin).
| `borderWidth` | arc border width (in pixels).
| `offset` | arc offset (in pixels).
Expand Down Expand Up @@ -168,6 +174,8 @@ The interaction with each arc can be controlled with the following properties:
| ---- | -----------
| `hoverBackgroundColor` | arc background color when hovered.
| `hoverBorderColor` | arc border color when hovered.
| `hoverBorderDash` | arc border length and spacing of dashes when hovered. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash).
| `hoverBorderDashOffset` | arc border offset for line dashes when hovered. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
| `hoverBorderJoinStyle` | arc border join style when hovered. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin).
| `hoverBorderWidth` | arc border width when hovered (in pixels).
| `hoverOffset` | arc offset when hovered (in pixels).
Expand Down
8 changes: 8 additions & 0 deletions docs/charts/polar.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,16 @@ The following options can be included in a polar area chart dataset to configure
| [`backgroundColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'rgba(0, 0, 0, 0.1)'`
| [`borderAlign`](#border-alignment) | `'center'`\|`'inner'` | Yes | Yes | `'center'`
| [`borderColor`](#styling) | [`Color`](../general/colors.md) | Yes | Yes | `'#fff'`
| [`borderDash`](#styling) | `number[]` | Yes | - | `[]`
| [`borderDashOffset`](#styling) | `number` | Yes | - | `0.0`
| [`borderJoinStyle`](#styling) | `'round'`\|`'bevel'`\|`'miter'` | Yes | Yes | `undefined`
| [`borderWidth`](#styling) | `number` | Yes | Yes | `2`
| [`clip`](#general) | `number`\|`object`\|`false` | - | - | `undefined`
| [`data`](#data-structure) | `number[]` | - | - | **required**
| [`hoverBackgroundColor`](#interactions) | [`Color`](../general/colors.md) | Yes | Yes | `undefined`
| [`hoverBorderColor`](#interactions) | [`Color`](../general/colors.md) | Yes | Yes | `undefined`
| [`hoverBorderDash`](#interactions) | `number[]` | Yes | - | `undefined`
| [`hoverBorderDashOffset`](#interactions) | `number` | Yes | - | `undefined`
| [`hoverBorderJoinStyle`](#interactions) | `'round'`\|`'bevel'`\|`'miter'` | Yes | Yes | `undefined`
| [`hoverBorderWidth`](#interactions) | `number` | Yes | Yes | `undefined`
| [`circular`](#styling) | `boolean` | Yes | Yes | `true`
Expand All @@ -84,6 +88,8 @@ The style of each arc can be controlled with the following properties:
| ---- | ----
| `backgroundColor` | arc background color.
| `borderColor` | arc border color.
| `borderDash` | arc border length and spacing of dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash).
| `borderDashOffset` | arc border offset for line dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
| `borderJoinStyle` | arc border join style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin).
| `borderWidth` | arc border width (in pixels).
| `circular` | By default the Arc is curved. If `circular: false` the Arc will be flat.
Expand All @@ -107,6 +113,8 @@ The interaction with each arc can be controlled with the following properties:
| ---- | -----------
| `hoverBackgroundColor` | arc background color when hovered.
| `hoverBorderColor` | arc border color when hovered.
| `hoverBorderDash` | arc border length and spacing of dashes when hovered. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash).
| `hoverBorderDashOffset` | arc border offset for line dashes when hovered. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
| `hoverBorderJoinStyle` | arc border join style when hovered. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin).
| `hoverBorderWidth` | arc border width when hovered (in pixels).

Expand Down
2 changes: 2 additions & 0 deletions docs/configuration/elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ Namespace: `options.elements.arc`, global arc options: `Chart.defaults.elements.
| `backgroundColor` | [`Color`](/general/colors.md) | `Chart.defaults.backgroundColor` | Arc fill color.
| `borderAlign` | `'center'`\|`'inner'` | `'center'` | Arc stroke alignment.
| `borderColor` | [`Color`](/general/colors.md) | `'#fff'` | Arc stroke color.
| `borderDash` | `number[]` | `[]` | Arc line dash. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash).
| `borderDashOffset` | `number` | `0.0` | Arc line dash offset. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
| `borderJoinStyle` | `'round'`\|`'bevel'`\|`'miter'` | `'bevel'`\|`'round'` | Line join style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin). The default is `'round'` when `borderAlign` is `'inner'`
| `borderWidth`| `number` | `2` | Arc stroke width.
| `circular` | `boolean` | `true` | By default the Arc is curved. If `circular: false` the Arc will be flat
2 changes: 1 addition & 1 deletion src/controllers/controller.doughnut.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export default class DoughnutController extends DatasetController {

static descriptors = {
_scriptable: (name) => name !== 'spacing',
_indexable: (name) => name !== 'spacing',
_indexable: (name) => name !== 'spacing' && !name.startsWith('borderDash') && !name.startsWith('hoverBorderDash'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why startsWith? and probably does not need hoverBorderDash, as its returned as borderDash when hovered.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kurkle I used startsWith to manage also borderDashOffset at the say way of borderDah because the 2 options are strictly related.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably does not need hoverBorderDash, as its returned as borderDash when hovered.

It seems you're right. I was convinced that the indexable policy is ignored for hover if not specified but it doesn't seem so. I'll submit another PR to remove it.

};

/**
Expand Down
12 changes: 11 additions & 1 deletion src/elements/element.arc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,16 @@ function drawBorder(
circular: boolean,
) {
const {fullCircles, startAngle, circumference, options} = element;
const {borderWidth, borderJoinStyle} = options;
const {borderWidth, borderJoinStyle, borderDash, borderDashOffset} = options;
const inner = options.borderAlign === 'inner';

if (!borderWidth) {
return;
}

ctx.setLineDash(borderDash || []);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You set the defat to an empty array so this check is not necessary then right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that was my doubt as well. But I have seen in the other parts of code, everytime this check is done for borderDash because setLineDash fails if not an array, I guess. Therefore not clear to me if it's not correct on the other parts or if better to leave this check anyway :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LeeLenaleee don't ask me why because I don't have the answer now (I checked this morning without success) but it seems that the donut options doesn't fallback to element ones therefore if you set borderDash: null in dataset config (and you don't have those check), you have an issue. This weird behavior was already recognized I guess because the _indexable about spacing option was added to the controller instead of the element. If you agree, I can pend more time to go in deep why the donut doesn't fallback to the arc element (maybe in another PR)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LeeLenaleee I have checked more in deep and the descriptors are working well. I wasn't aware that the resolver uses the descriptors of the default of the controller (and not in cascade as I was thinking) therefore it's working as designed.

About the point of your review, I can confirm that if you set borderDash: null, you have an error (but fallback works correctly if you set to undefined).
The check where null is passed as defined is here:

if (defined(value)) {

The define function checks if the value is undefined but with null argument returns true. Probably the define function could be remove, using instead isNullOrUndef. WDYT?

In my opinion, but I can be wrong, it would be better to maintain that check anyway in the meanwhile. But feel free to disagree ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Null is considered a valid value for configuration while undefined is considered not defined and thus fallback. Falling back from null would be a breaking change, extending to all unknown use cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kurkle yes!

EDIT: this is why I would suggest to stay as is, in this PR .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kind of agree with @LeeLenaleee, but the behaviour should be changed everywhere to be consistent, so maybe do at v5 as a breaking change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kurkle @LeeLenaleee @etimberg I think we agreed to change for v5. Nevertheless let me outline that there are other options/situation which should be addressed, similar to this one, I guess. Maybe you are already aware but let me make an example.

The doughnut controller is setting spacing options in the default, set to 0. doing that, the spacing option of the element is ignored, therefore having a following chart config

{
  type: 'doughnut',
  data: {
    labels: [0, 1, 2, 3, 4, 5],
    datasets: [
      {
        data: [0, 2, 4, null, 6, 8],
        cutout: 200
      }]
  },
  options: {
    elements: {
      arc: {
        spacing: 30
      }
    }
  }
}

the spacing: 30 is ignored in the cutout/maxsize calculation because it uses 0 (controller defaults) instead of 30. This is happening because the dataset options are not using the fallback in the update phase of the controller and when you have to use options of data element during the update of the controller, you must check against a default or replicate the options definition, ignoring the element config value/defaults. @kurkle I think we have already talked about that in the treemap controller.

ctx.lineDashOffset = borderDashOffset;

if (inner) {
ctx.lineWidth = borderWidth * 2;
ctx.lineJoin = borderJoinStyle || 'round';
Expand Down Expand Up @@ -264,6 +267,8 @@ export default class ArcElement extends Element<ArcProps, ArcOptions> {
static defaults = {
borderAlign: 'center',
borderColor: '#fff',
borderDash: [],
borderDashOffset: 0,
borderJoinStyle: undefined,
borderRadius: 0,
borderWidth: 2,
Expand All @@ -277,6 +282,11 @@ export default class ArcElement extends Element<ArcProps, ArcOptions> {
backgroundColor: 'backgroundColor'
};

static descriptors = {
_scriptable: true,
_indexable: (name) => name !== 'borderDash'
};

circumference: number;
endAngle: number;
fullCircles: number;
Expand Down
13 changes: 12 additions & 1 deletion src/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1700,7 +1700,16 @@ export interface ArcOptions extends CommonElementOptions {
* Arc stroke alignment.
*/
borderAlign: 'center' | 'inner';

/**
* Line dash. See MDN.
* @default []
*/
borderDash: number[];
/**
* Line dash offset. See MDN.
* @default 0.0
*/
borderDashOffset: number;
/**
* Line join style. See MDN. Default is 'round' when `borderAlign` is 'inner', else 'bevel'.
*/
Expand Down Expand Up @@ -1730,6 +1739,8 @@ export interface ArcOptions extends CommonElementOptions {
}

export interface ArcHoverOptions extends CommonHoverOptions {
hoverBorderDash: number[];
hoverBorderDashOffset: number;
hoverOffset: number;
}

Expand Down
34 changes: 34 additions & 0 deletions test/fixtures/controller.doughnut/borderDash/scriptable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module.exports = {
config: {
type: 'doughnut',
data: {
labels: [0, 1, 2, 3, 4, 5],
datasets: [
{
// option in element (fallback)
data: [5, 2, 4, 7, 6, 8]
}
]
},
options: {
elements: {
arc: {
backgroundColor: 'transparent',
borderColor: 'black',
borderWidth: 1,
borderDash: function(ctx) {
var value = (ctx.dataIndex || 0) % 2;
return value === 0 ? [3, 3] : [];
}

}
},
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions test/fixtures/controller.doughnut/borderDash/value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module.exports = {
config: {
type: 'polarArea',
data: {
labels: [0, 1, 2, 3, 4, 5],
datasets: [
{
// option in dataset
data: [5, 2, 4, 7, 6, 8],
borderAlign: 'inner',
borderColor: 'black'
},
]
},
options: {
elements: {
arc: {
backgroundColor: 'transparent',
borderWidth: 1,
borderDash: [3, 3]
}
},
scales: {
r: {
display: false
}
}
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions test/fixtures/controller.polarArea/borderDash/scriptable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module.exports = {
config: {
type: 'polarArea',
data: {
labels: [0, 1, 2, 3, 4, 5],
datasets: [
{
// option in dataset
data: [5, 2, 4, 7, 6, 8]
}
]
},
options: {
elements: {
arc: {
backgroundColor: 'transparent',
borderColor: 'black',
borderWidth: 1,
borderDash: function(ctx) {
var value = (ctx.dataIndex || 0) % 2;
return value === 0 ? [3, 3] : [];
}
}
},
scales: {
r: {
display: false
}
}
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions test/fixtures/controller.polarArea/borderDash/value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module.exports = {
config: {
type: 'polarArea',
data: {
labels: [0, 1, 2, 3, 4, 5],
datasets: [
{
// option in dataset
data: [5, 2, 4, 7, 6, 8],
borderAlign: 'inner',
borderColor: 'black'
},
]
},
options: {
elements: {
arc: {
backgroundColor: 'transparent',
borderWidth: 1,
borderDash: [3, 3]
}
},
scales: {
r: {
display: false
}
}
}
},
options: {
canvas: {
height: 256,
width: 512
}
}
};
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.