Skip to content

Commit 9ecc800

Browse files
authored
Fix drawing of lines with points out of chartArea (#414)
* Fix drawing of lines with points out of chartArea * CC * Revert "CC" This reverts commit 8b9caf3.
1 parent 5febbbb commit 9ecc800

File tree

12 files changed

+233
-17
lines changed

12 files changed

+233
-17
lines changed

src/helpers.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,9 @@ import {isFinite} from 'chart.js/helpers';
33
const PI = Math.PI;
44
const HALF_PI = PI / 2;
55

6-
function inArea(scale, pixel) {
7-
const area = scale.chart.chartArea;
8-
return scale.isHorizontal()
9-
? pixel >= area.left && pixel <= area.right
10-
: pixel >= area.top && pixel <= area.bottom;
11-
}
12-
136
export function scaleValue(scale, value, fallback) {
147
value = typeof value === 'number' ? value : scale.parse(value);
15-
value = isFinite(value) ? scale.getPixelForValue(value) : fallback;
16-
return inArea(scale, value) ? value : fallback;
8+
return isFinite(value) ? scale.getPixelForValue(value) : fallback;
179
}
1810

1911
/**

src/types/line.js

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,32 @@ const interpolateX = (y, p1, p2) => pointInLine(p1, p2, Math.abs((y - p1.y) / (p
1212
const interpolateY = (x, p1, p2) => pointInLine(p1, p2, Math.abs((x - p1.x) / (p2.x - p1.x))).y;
1313
const toPercent = (s) => typeof s === 'string' && s.endsWith('%') && parseFloat(s) / 100;
1414

15+
function limitPointToArea({x, y}, p2, {top, right, bottom, left}) {
16+
if (x < left) {
17+
y = p2.x < left ? NaN : interpolateY(left, {x, y}, p2);
18+
x = left;
19+
}
20+
if (x > right) {
21+
y = p2.x > right ? NaN : interpolateY(right, {x, y}, p2);
22+
x = right;
23+
}
24+
if (y < top) {
25+
x = p2.y < top ? NaN : interpolateX(top, {x, y}, p2);
26+
y = top;
27+
}
28+
if (y > bottom) {
29+
x = p2.y > bottom ? NaN : interpolateX(bottom, {x, y}, p2);
30+
y = bottom;
31+
}
32+
return {x, y};
33+
}
34+
35+
function limitLineToArea(p1, p2, area) {
36+
const {x, y} = limitPointToArea(p1, p2, area);
37+
const {x: x2, y: y2} = limitPointToArea(p2, p1, area);
38+
return {x, y, x2, y2, width: Math.abs(x2 - x), height: Math.abs(y2 - y)};
39+
}
40+
1541
export default class LineAnnotation extends Element {
1642
intersects(x, y, epsilon) {
1743
epsilon = epsilon || 0.001;
@@ -112,14 +138,7 @@ export default class LineAnnotation extends Element {
112138
y2 = scaleValue(yScale, options.yMax, y2);
113139
}
114140
}
115-
return {
116-
x,
117-
y,
118-
x2,
119-
y2,
120-
width: x2 - x,
121-
height: y2 - y
122-
};
141+
return limitLineToArea({x, y}, {x: x2, y: y2}, chart.chartArea);
123142
}
124143
}
125144

test/fixtures/box/partial-range.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module.exports = {
2+
config: {
3+
type: 'line',
4+
data: {
5+
datasets: [{
6+
data: [10, 20, 30, 0, 55],
7+
}],
8+
labels: ['A', 'B', 'C', 'D', 'E']
9+
},
10+
options: {
11+
scales: {
12+
y: {
13+
max: 60
14+
},
15+
},
16+
plugins: {
17+
legend: false,
18+
annotation: {
19+
annotations: {
20+
annotation1: {
21+
type: 'box',
22+
backgroundColor: 'rgba(255, 99, 132, 0.25)',
23+
borderWidth: 3,
24+
borderColor: 'black',
25+
xMin: 'B',
26+
xMax: 'C',
27+
yMin: 20,
28+
yMax: 700,
29+
}
30+
}
31+
}
32+
},
33+
}
34+
},
35+
options: {
36+
spriteText: true,
37+
}
38+
};
23.6 KB
Loading
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module.exports = {
2+
config: {
3+
type: 'line',
4+
data: {
5+
datasets: [{
6+
data: [10, 20, 30, 0, 55],
7+
}],
8+
labels: ['A', 'B', 'C', 'D', 'E']
9+
},
10+
options: {
11+
scales: {
12+
y: {
13+
max: 60
14+
},
15+
},
16+
plugins: {
17+
legend: false,
18+
annotation: {
19+
annotations: {
20+
annotation1: {
21+
type: 'ellipse',
22+
backgroundColor: 'rgba(255, 99, 132, 0.25)',
23+
borderWidth: 3,
24+
borderColor: 'black',
25+
xMin: 'B',
26+
xMax: 'C',
27+
yMin: 20,
28+
yMax: 700,
29+
}
30+
}
31+
}
32+
},
33+
}
34+
},
35+
options: {
36+
spriteText: true,
37+
}
38+
};
33.9 KB
Loading
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module.exports = {
2+
config: {
3+
type: 'line',
4+
options: {
5+
scales: {
6+
x: {type: 'linear', min: 0, max: 10},
7+
y: {type: 'linear', min: 0, max: 10, reverse: true}
8+
},
9+
plugins: {
10+
legend: false,
11+
annotation: {
12+
annotations: [
13+
{
14+
type: 'line',
15+
xMin: 3,
16+
xMax: 5,
17+
yMin: 11,
18+
yMax: 8,
19+
borderColor: 'blue'
20+
},
21+
{
22+
type: 'line',
23+
xMin: 5,
24+
xMax: 5,
25+
yMin: 8,
26+
yMax: 11,
27+
borderColor: 'purple'
28+
},
29+
{
30+
type: 'line',
31+
xMin: 5,
32+
xMax: 7,
33+
yMin: 8,
34+
yMax: 11,
35+
borderColor: 'red'
36+
}
37+
]
38+
}
39+
},
40+
}
41+
},
42+
options: {
43+
spriteText: true,
44+
}
45+
};
22.3 KB
Loading

test/fixtures/line/direction.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
module.exports = {
2+
config: {
3+
type: 'line',
4+
options: {
5+
scales: {
6+
x: {type: 'linear', min: 0, max: 10},
7+
y: {type: 'linear', min: 0, max: 10}
8+
},
9+
plugins: {
10+
legend: false,
11+
annotation: {
12+
annotations: [
13+
{
14+
type: 'line',
15+
xMin: 3,
16+
xMax: 5,
17+
yMin: 11,
18+
yMax: 8,
19+
borderColor: 'blue'
20+
},
21+
{
22+
type: 'line',
23+
xMin: 5,
24+
xMax: 5,
25+
yMin: 8,
26+
yMax: 11,
27+
borderColor: 'purple'
28+
},
29+
{
30+
type: 'line',
31+
xMin: 5,
32+
xMax: 7,
33+
yMin: 8,
34+
yMax: 11,
35+
borderColor: 'red'
36+
}
37+
]
38+
}
39+
},
40+
}
41+
},
42+
options: {
43+
spriteText: true,
44+
}
45+
};

test/fixtures/line/direction.png

22.3 KB
Loading

0 commit comments

Comments
 (0)