@luceosports/play-rendering 1.9.40 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/play-rendering.js +3 -3
- package/dist/play-rendering.js.map +1 -1
- package/package.json +1 -1
- package/src/assets/shapes/cone.svg +23 -0
- package/src/layers/ShapeLayer.js +20 -0
- package/src/layers/shape/base/InternalShapeLayer.js +37 -0
- package/src/layers/shape/index.js +11 -0
- package/src/layers/shape/layers/CircleShapeLayer.js +18 -0
- package/src/layers/shape/layers/ConeShapeLayer.js +20 -0
- package/src/layers/shape/layers/SquareShapeLayer.js +20 -0
- package/src/layers/shape/layers/TriangleShapeLayer.js +31 -0
- package/src/models/Frame.js +11 -1
- package/src/models/Play.js +4 -1
- package/src/shapesConfig.js +6 -0
package/package.json
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
4
|
+
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
5
|
+
width="978px" height="952px" viewBox="0 0 978 952" enable-background="new 0 0 978 952" xml:space="preserve">
|
|
6
|
+
<path d="M520.289,1.967c-1.615,4.413-14.747,7.465-31.096,7.465c-16.88,0-30.314-4.884-31.217-8.822l-76.571,214.588h-0.018
|
|
7
|
+
c0.037,17,48.295,30.526,107.535,30.526c59.236,0,107.535-13.084,107.535-29.72v-0.005L520.289,1.967z"/>
|
|
8
|
+
<path d="M897.207,691.268l-148.072-45.49l34.283,96.421h-0.003c-0.099,46-131.985,82.708-294.66,82.708
|
|
9
|
+
c-162.679,0-294.562-36.708-294.663-82.708h0.055l34.278-96.406L80.652,691.284C-6.557,718.129-27.55,764.646,41.001,795.37
|
|
10
|
+
l282.491,126.619c89.181,39.971,241.994,40.025,331.121,0.096l282.621-126.606C1005.879,764.728,984.701,718.146,897.207,691.268z"
|
|
11
|
+
/>
|
|
12
|
+
<g>
|
|
13
|
+
<path fill="#FFFFFF" d="M596.449,216.188c-0.355,16.547-48.509,29.536-107.526,29.536c-58.484,0-106.26-13.184-107.505-29.877
|
|
14
|
+
L249.672,586.135c-0.006-0.015-0.015-0.028-0.021-0.042l-55.505,156.105h-0.055c0.101,46,131.984,82.708,294.663,82.708
|
|
15
|
+
c162.675,0,294.562-36.708,294.66-82.708h0.003h0.04L596.449,216.188z"/>
|
|
16
|
+
<path fill="#FFFFFF" d="M457.995,0.666l0.002-0.056l-0.011,0.03C457.988,0.649,457.992,0.658,457.995,0.666z"/>
|
|
17
|
+
</g>
|
|
18
|
+
<g>
|
|
19
|
+
<path d="M655.997,381.461c-4.879,11.841-21.986,22.058-50.218,29.847c-31.25,8.622-72.838,13.37-117.103,13.37
|
|
20
|
+
c-44.28,0-85.87-4.857-117.109-13.678c-27.324-7.715-44.232-17.743-49.711-29.335l-69.411,194.533h-0.043
|
|
21
|
+
c0.08,35,106.409,66.121,236.528,66.121c130.117,0,236.528-29.668,236.528-66.207v-0.012L655.997,381.461z"/>
|
|
22
|
+
</g>
|
|
23
|
+
</svg>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const _ = require('lodash');
|
|
2
|
+
const BaseLayer = require('./base/BaseLayer');
|
|
3
|
+
const shapeLayers = require('./shape');
|
|
4
|
+
|
|
5
|
+
class ShapeLayer extends BaseLayer {
|
|
6
|
+
apply() {
|
|
7
|
+
this.ctx.save();
|
|
8
|
+
|
|
9
|
+
this.playData.shapes.forEach(shape => {
|
|
10
|
+
const layerKey = `${_.capitalize(shape.type)}ShapeLayer`;
|
|
11
|
+
if (shapeLayers[layerKey]) {
|
|
12
|
+
new shapeLayers[layerKey](this, shape).apply();
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
this.ctx.restore();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = ShapeLayer;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const InternalBaseLayer = require('../../base/InternalBaseLayer');
|
|
2
|
+
|
|
3
|
+
class InternalShapeLayer extends InternalBaseLayer {
|
|
4
|
+
constructor(parentLayer, shape) {
|
|
5
|
+
super(parentLayer);
|
|
6
|
+
this.shape = shape;
|
|
7
|
+
this.playData = parentLayer.playData;
|
|
8
|
+
this.courtTypeConstants = parentLayer.courtTypeConstants;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get staticData() {
|
|
12
|
+
return this.options.staticData;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
drawLogic() {
|
|
16
|
+
this.setColor();
|
|
17
|
+
this.drawShape();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
setColor() {
|
|
21
|
+
const fillAlpha = 0.2;
|
|
22
|
+
const { alpha, blue, green, red } = this.shape.color;
|
|
23
|
+
|
|
24
|
+
const r = Math.ceil(red * 255);
|
|
25
|
+
const g = Math.ceil(green * 255);
|
|
26
|
+
const b = Math.ceil(blue * 255);
|
|
27
|
+
|
|
28
|
+
this.ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${fillAlpha})`;
|
|
29
|
+
this.ctx.strokeStyle = `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
drawShape() {
|
|
33
|
+
// Override this function in a subclass
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = InternalShapeLayer;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// require all modules on the path and with the pattern defined
|
|
2
|
+
const req = require.context('./layers/', true, /.js$/);
|
|
3
|
+
|
|
4
|
+
const modules = {};
|
|
5
|
+
|
|
6
|
+
req.keys().forEach(key => {
|
|
7
|
+
const mname = key.replace('./', '').replace('.js', '');
|
|
8
|
+
modules[mname] = req(key);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
module.exports = modules;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const InternalShapeLayer = require('../base/InternalShapeLayer');
|
|
2
|
+
|
|
3
|
+
const CIRCLE_SHAPE_RADIUS = 5;
|
|
4
|
+
|
|
5
|
+
class CircleShapeLayer extends InternalShapeLayer {
|
|
6
|
+
drawShape() {
|
|
7
|
+
const { location, scale } = this.shape;
|
|
8
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH;
|
|
9
|
+
this.ctx.translate(location.x, location.y);
|
|
10
|
+
this.ctx.scale(scale.x, scale.y);
|
|
11
|
+
this.ctx.beginPath();
|
|
12
|
+
this.ctx.arc(0, 0, CIRCLE_SHAPE_RADIUS, 0, Math.PI * 2);
|
|
13
|
+
this.ctx.stroke();
|
|
14
|
+
this.ctx.fill();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = CircleShapeLayer;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const InternalShapeLayer = require('../base/InternalShapeLayer');
|
|
2
|
+
|
|
3
|
+
const SHAPE_SIZE = 5;
|
|
4
|
+
|
|
5
|
+
class ConeShapeLayer extends InternalShapeLayer {
|
|
6
|
+
drawShape() {
|
|
7
|
+
const { location, scale } = this.shape;
|
|
8
|
+
this.ctx.translate(location.x - SHAPE_SIZE / 2, location.y - SHAPE_SIZE / 2);
|
|
9
|
+
this.ctx.scale(scale.x, scale.y);
|
|
10
|
+
|
|
11
|
+
if (this.staticData.shapes && this.staticData.shapes.length) {
|
|
12
|
+
const coneShape = this.staticData.shapes.find(shape => shape.key === 'cone');
|
|
13
|
+
if (coneShape) {
|
|
14
|
+
this.ctx.drawImage(coneShape.image, 0, 0, SHAPE_SIZE, SHAPE_SIZE);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = ConeShapeLayer;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const InternalShapeLayer = require('../base/InternalShapeLayer');
|
|
2
|
+
|
|
3
|
+
const SQUARE_SIDE_LENGTH = 10;
|
|
4
|
+
|
|
5
|
+
class SquareShapeLayer extends InternalShapeLayer {
|
|
6
|
+
drawShape() {
|
|
7
|
+
const { location, scale } = this.shape;
|
|
8
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH;
|
|
9
|
+
this.ctx.translate(location.x, location.y);
|
|
10
|
+
this.ctx.scale(scale.x, scale.y);
|
|
11
|
+
|
|
12
|
+
this.ctx.beginPath();
|
|
13
|
+
this.ctx.rect(-SQUARE_SIDE_LENGTH / 2, -SQUARE_SIDE_LENGTH / 2, SQUARE_SIDE_LENGTH, SQUARE_SIDE_LENGTH);
|
|
14
|
+
|
|
15
|
+
this.ctx.stroke();
|
|
16
|
+
this.ctx.fill();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = SquareShapeLayer;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const { sin, cos } = require('mathjs');
|
|
2
|
+
const InternalShapeLayer = require('../base/InternalShapeLayer');
|
|
3
|
+
|
|
4
|
+
const OUTER_RADIUS = 10;
|
|
5
|
+
|
|
6
|
+
class TriangleShapeLayer extends InternalShapeLayer {
|
|
7
|
+
drawShape() {
|
|
8
|
+
const { location, scale } = this.shape;
|
|
9
|
+
const triangle = [
|
|
10
|
+
{ x: 0, y: -OUTER_RADIUS },
|
|
11
|
+
{ x: OUTER_RADIUS * cos(210), y: OUTER_RADIUS * sin(210) },
|
|
12
|
+
{ x: -OUTER_RADIUS * cos(210), y: OUTER_RADIUS * sin(210) }
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
this.ctx.lineWidth = this.courtTypeConstants.COURT_LINE_WIDTH;
|
|
16
|
+
this.ctx.translate(location.x, location.y);
|
|
17
|
+
this.ctx.scale(scale.x, scale.y);
|
|
18
|
+
|
|
19
|
+
this.ctx.beginPath();
|
|
20
|
+
|
|
21
|
+
this.ctx.moveTo(triangle[0].x, triangle[0].y);
|
|
22
|
+
this.ctx.lineTo(triangle[1].x, triangle[1].y);
|
|
23
|
+
this.ctx.lineTo(triangle[2].x, triangle[2].y);
|
|
24
|
+
this.ctx.lineTo(triangle[0].x, triangle[0].y);
|
|
25
|
+
|
|
26
|
+
this.ctx.stroke();
|
|
27
|
+
this.ctx.fill();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = TriangleShapeLayer;
|
package/src/models/Frame.js
CHANGED
|
@@ -5,6 +5,7 @@ const { splitBezierCurveAtTVal, distanceBetweenPoints } = require('../math/LineD
|
|
|
5
5
|
const CourtLayer = require('../layers/CourtLayer');
|
|
6
6
|
const LineLayer = require('../layers/LineLayer');
|
|
7
7
|
const PlayerLayer = require('../layers/PlayerLayer');
|
|
8
|
+
const ShapeLayer = require('../layers/ShapeLayer');
|
|
8
9
|
const LineControlPointLayer = require('../layers/LineControlPointLayer');
|
|
9
10
|
const Line = require('./Line');
|
|
10
11
|
const Player = require('./Player');
|
|
@@ -34,6 +35,7 @@ class Frame {
|
|
|
34
35
|
court: this.play.playData.court,
|
|
35
36
|
lines: this.lines,
|
|
36
37
|
players: this.players,
|
|
38
|
+
shapes: this.shapes,
|
|
37
39
|
options: {
|
|
38
40
|
...this.play.options,
|
|
39
41
|
staticData: this.play.staticData,
|
|
@@ -51,6 +53,13 @@ class Frame {
|
|
|
51
53
|
return this.animationGlobalProgress ? this.animationProgressPlayers : this.currentPhasePlayers;
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
get shapes() {
|
|
57
|
+
if (!this.play.playData.shapes) return [];
|
|
58
|
+
return this.play.playData.shapes.map(s => {
|
|
59
|
+
return JSON.parse(JSON.stringify(s));
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
54
63
|
get currentPhasePlayers() {
|
|
55
64
|
const lines = this.play.options.huddleMode ? this.playDataLines : this.prevPhaseLines;
|
|
56
65
|
const { currentPhaseLines } = this;
|
|
@@ -116,7 +125,7 @@ class Frame {
|
|
|
116
125
|
});
|
|
117
126
|
});
|
|
118
127
|
|
|
119
|
-
if (this.animationGlobalProgress
|
|
128
|
+
if (this.animationGlobalProgress >= player.lastAnimEndTime) {
|
|
120
129
|
player.location = player.lastAnimationLastLinePartControlPoint;
|
|
121
130
|
}
|
|
122
131
|
|
|
@@ -200,6 +209,7 @@ class Frame {
|
|
|
200
209
|
|
|
201
210
|
const { frameData } = this;
|
|
202
211
|
new CourtLayer(this.ctx, frameData).apply();
|
|
212
|
+
new ShapeLayer(this.ctx, frameData).apply();
|
|
203
213
|
new LineLayer(this.ctx, frameData).apply();
|
|
204
214
|
new PlayerLayer(this.ctx, frameData).apply();
|
|
205
215
|
new LineControlPointLayer(this.ctx, frameData).apply();
|
package/src/models/Play.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const { loadImage } = require('canvas');
|
|
3
3
|
const playerHatsConfig = require('../playerHatsConfig');
|
|
4
|
+
const shapesConfig = require('../shapesConfig');
|
|
4
5
|
|
|
5
6
|
const STORAGE_URL = 'https://playbooksstore.blob.core.windows.net/public';
|
|
6
7
|
const LUCEOSPORTS_WATERMARK_PATH = 'partners/LuceoSports/luceo-sports-logo-powered-by-sm.png';
|
|
@@ -49,6 +50,7 @@ class Play {
|
|
|
49
50
|
|
|
50
51
|
static async init({ teamLogoPath = '' } = {}) {
|
|
51
52
|
Play.playerHats = await playerHatsConfig();
|
|
53
|
+
Play.shapes = await shapesConfig();
|
|
52
54
|
|
|
53
55
|
const hardwoodImageData = require('../assets/wood_bg.png');
|
|
54
56
|
const hardwoodImage = await loadImage(hardwoodImageData);
|
|
@@ -89,7 +91,8 @@ class Play {
|
|
|
89
91
|
return {
|
|
90
92
|
backgroundOptions: Play.backgroundOptions,
|
|
91
93
|
watermark: Play.watermark,
|
|
92
|
-
playerHats: Play.playerHats
|
|
94
|
+
playerHats: Play.playerHats,
|
|
95
|
+
shapes: Play.shapes
|
|
93
96
|
};
|
|
94
97
|
}
|
|
95
98
|
|