etro 0.6.0

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.
Files changed (103) hide show
  1. package/.env +2 -0
  2. package/.github/workflows/nodejs.yml +27 -0
  3. package/CHANGELOG.md +109 -0
  4. package/CODE_OF_CONDUCT.md +77 -0
  5. package/CONTRIBUTING.md +155 -0
  6. package/LICENSE +674 -0
  7. package/README.md +57 -0
  8. package/dist/etro.js +3397 -0
  9. package/docs/effect.js.html +1215 -0
  10. package/docs/event.js.html +145 -0
  11. package/docs/index.html +81 -0
  12. package/docs/index.js.html +92 -0
  13. package/docs/layer.js.html +888 -0
  14. package/docs/module-effect-GaussianBlurComponent.html +345 -0
  15. package/docs/module-effect.Brightness.html +339 -0
  16. package/docs/module-effect.Channels.html +319 -0
  17. package/docs/module-effect.ChromaKey.html +611 -0
  18. package/docs/module-effect.Contrast.html +339 -0
  19. package/docs/module-effect.EllipticalMask.html +200 -0
  20. package/docs/module-effect.GaussianBlur.html +202 -0
  21. package/docs/module-effect.GaussianBlurHorizontal.html +242 -0
  22. package/docs/module-effect.GaussianBlurVertical.html +242 -0
  23. package/docs/module-effect.Pixelate.html +330 -0
  24. package/docs/module-effect.Shader.html +1227 -0
  25. package/docs/module-effect.Stack.html +406 -0
  26. package/docs/module-effect.Transform.Matrix.html +193 -0
  27. package/docs/module-effect.Transform.html +1174 -0
  28. package/docs/module-effect.html +148 -0
  29. package/docs/module-event.html +473 -0
  30. package/docs/module-index.html +186 -0
  31. package/docs/module-layer-Media.html +1116 -0
  32. package/docs/module-layer-MediaMixin.html +164 -0
  33. package/docs/module-layer.Audio.html +1188 -0
  34. package/docs/module-layer.Base.html +629 -0
  35. package/docs/module-layer.Image.html +1421 -0
  36. package/docs/module-layer.Text.html +1731 -0
  37. package/docs/module-layer.Video.html +1938 -0
  38. package/docs/module-layer.Visual.html +1698 -0
  39. package/docs/module-layer.html +137 -0
  40. package/docs/module-movie.html +3118 -0
  41. package/docs/module-util.Color.html +702 -0
  42. package/docs/module-util.Font.html +395 -0
  43. package/docs/module-util.html +845 -0
  44. package/docs/movie.js.html +689 -0
  45. package/docs/scripts/collapse.js +20 -0
  46. package/docs/scripts/linenumber.js +25 -0
  47. package/docs/scripts/nav.js +12 -0
  48. package/docs/scripts/polyfill.js +4 -0
  49. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  50. package/docs/scripts/prettify/lang-css.js +2 -0
  51. package/docs/scripts/prettify/prettify.js +28 -0
  52. package/docs/scripts/search.js +83 -0
  53. package/docs/styles/jsdoc.css +671 -0
  54. package/docs/styles/prettify.css +79 -0
  55. package/docs/util.js.html +503 -0
  56. package/eslint.conf.js +28 -0
  57. package/eslint.test-conf.js +4 -0
  58. package/examples/application/readme-screenshot.html +86 -0
  59. package/examples/application/video-player.html +131 -0
  60. package/examples/application/webcam.html +28 -0
  61. package/examples/introduction/audio.html +52 -0
  62. package/examples/introduction/effects.html +56 -0
  63. package/examples/introduction/export.html +70 -0
  64. package/examples/introduction/functions.html +35 -0
  65. package/examples/introduction/hello-world1.html +33 -0
  66. package/examples/introduction/hello-world2.html +32 -0
  67. package/examples/introduction/keyframes.html +67 -0
  68. package/examples/introduction/media.html +55 -0
  69. package/examples/introduction/text.html +27 -0
  70. package/jsdoc.conf.json +3 -0
  71. package/karma.conf.js +60 -0
  72. package/package.json +63 -0
  73. package/private-todo.txt +70 -0
  74. package/rename-file.sh +18 -0
  75. package/rename-versions.sh +14 -0
  76. package/rename.sh +22 -0
  77. package/rollup.config.js +31 -0
  78. package/screenshots/2019-08-17_0.png +0 -0
  79. package/scripts/gen-effect-samples.html +99 -0
  80. package/scripts/save-effect-samples.js +43 -0
  81. package/spec/assets/effect/gaussian-blur-horizontal.png +0 -0
  82. package/spec/assets/effect/gaussian-blur-vertical.png +0 -0
  83. package/spec/assets/effect/original.png +0 -0
  84. package/spec/assets/effect/pixelate.png +0 -0
  85. package/spec/assets/effect/transform/multiply.png +0 -0
  86. package/spec/assets/effect/transform/rotate.png +0 -0
  87. package/spec/assets/effect/transform/scale-fraction.png +0 -0
  88. package/spec/assets/effect/transform/scale.png +0 -0
  89. package/spec/assets/effect/transform/translate-fraction.png +0 -0
  90. package/spec/assets/effect/transform/translate.png +0 -0
  91. package/spec/assets/layer/audio.wav +0 -0
  92. package/spec/assets/layer/image.jpg +0 -0
  93. package/spec/effect.spec.js +352 -0
  94. package/spec/event.spec.js +25 -0
  95. package/spec/layer.spec.js +128 -0
  96. package/spec/movie.spec.js +154 -0
  97. package/spec/util.spec.js +285 -0
  98. package/src/effect.js +1265 -0
  99. package/src/event.js +78 -0
  100. package/src/index.js +23 -0
  101. package/src/layer.js +875 -0
  102. package/src/movie.js +636 -0
  103. package/src/util.js +487 -0
@@ -0,0 +1,131 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Video player in Etro</title>
5
+ <style>
6
+ body {
7
+ background: #333;
8
+ }
9
+
10
+ /* TODO: make chrome-compatable */
11
+ input[type=range]::-moz-range-progress {
12
+ background-color: #d0d0d0;
13
+ }
14
+ input[type=range]::-moz-range-track {
15
+ background-color: #808080;
16
+ }
17
+
18
+ .center-x {
19
+ text-align: center;
20
+ }
21
+
22
+ img, video {
23
+ display: none;
24
+ }
25
+
26
+ /* https://css-tricks.com/making-pure-css-playpause-button/ */
27
+
28
+ .play {
29
+ background: transparent;
30
+ width: 24px;
31
+ height: 24px;
32
+ box-sizing: border-box;
33
+ border-style: solid;
34
+ border-color: transparent transparent transparent #d0d0d0;
35
+ border-width: 12px 0 12px 24px;
36
+ }
37
+
38
+ .pause {
39
+ background: transparent;
40
+ width: 24px;
41
+ height: 24px;
42
+ border-style: double;
43
+ border-color: #d0d0d0;
44
+ border-width: 0 0 0 12px;
45
+ }
46
+ .pause:focus {
47
+ /* TODO: hide outline */
48
+ }
49
+
50
+ #progress {
51
+ width: calc(100% - 64px); /* TODO: make better */
52
+ float: right;
53
+ }
54
+
55
+ #container {
56
+ display: inline-block;
57
+ }
58
+ </style>
59
+ </head>
60
+ <body>
61
+ <script type="module">
62
+ import etro from '../../src/index.js'
63
+
64
+ window.addEventListener('load', () => {
65
+ const canvas = document.getElementById('output')
66
+
67
+ const controls = {
68
+ playPause: document.getElementById('pause-play'),
69
+ progressBar: document.getElementById('progress')
70
+ }
71
+
72
+ const movie = new etro.Movie(canvas, { repeat: true })
73
+
74
+ // FIXME: resetting to beginning every time paused and played
75
+ controls.playPause.onclick = event => {
76
+ if (controls.playPause.className === 'play') {
77
+ movie.play()
78
+ controls.playPause.className = 'pause'
79
+ } else {
80
+ movie.pause()
81
+ controls.playPause.className = 'play'
82
+ }
83
+ }
84
+ canvas.addEventListener('click', controls.playPause.click) // FIXME: isn"t firing
85
+ document.body.addEventListener('keyup', event => {
86
+ const key = event.which || event.keyCode || 0
87
+ if (key === 32) {
88
+ controls.playPause.click()
89
+ } // spacebar
90
+ })
91
+ etro.event.subscribe(movie, 'movie.ended', event => {
92
+ if (!event.repeat) {
93
+ controls.playPause.className = 'play'
94
+ }
95
+ })
96
+
97
+ controls.progressBar.min = 0
98
+ /* controls.progressBar.step = movie.duration / controls.progressBar.style.getComputedStyle().width;
99
+ controls.progressBar.addEventListener("resize", () => {
100
+ controls.progressBar.step = movie.duration / controls.progressBar.style.width;
101
+ }); */
102
+ controls.progressBar.step = 0.5 // half of a second
103
+ controls.progressBar.value = 0 // just for sure, it's weird
104
+ controls.progressBar.addEventListener('input', () => {
105
+ movie.currentTime = 1 * controls.progressBar.value
106
+ })
107
+ etro.event.subscribe(movie, 'movie.timeupdate', () => {
108
+ controls.progressBar.value = movie.currentTime
109
+ })
110
+
111
+ const video = document.querySelector('video')
112
+ canvas.width = video.videoWidth
113
+ canvas.height = video.videoHeight
114
+
115
+ // For simplicity, only use one layer
116
+ movie.addLayer(
117
+ new etro.layer.Video(0, video)
118
+ )
119
+
120
+ controls.progressBar.max = movie.duration
121
+ })
122
+ </script>
123
+ <div id="container">
124
+ <video src="../assets/sample.ogv"></video>
125
+ <img src="../assets/sample.jpg"/>
126
+ <canvas id="output"></canvas><br>
127
+ <button id="pause-play" class="play"><!-- styled --></button>
128
+ <input id="progress" type="range" value="0"/>
129
+ </div>
130
+ </body>
131
+ </html>
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>getUserMedia()</title>
5
+ </head>
6
+ <body>
7
+ <video style="display:none"></video>
8
+ <canvas></canvas>
9
+ <script type="module">
10
+ import etro from '../../src/index.js'
11
+
12
+ const video = document.querySelector('video')
13
+ navigator.mediaDevices.getUserMedia({ video: true }).then(stream => {
14
+ video.srcObject = stream
15
+ video.onloadedmetadata = () => {
16
+ movie.width = video.videoWidth
17
+ movie.height = video.videoHeight
18
+ movie.play()
19
+ }
20
+ })
21
+
22
+ const movie = new etro.Movie(document.querySelector('canvas'))
23
+ .addLayer(new etro.layer.Visual(0, Infinity, { background: 'black' }))
24
+ .addLayer(new etro.layer.Video(0, video)
25
+ .addEffect(new etro.effect.ChromaKey(etro.parseColor('black'), 100)))
26
+ </script>
27
+ </body>
28
+ </html>
@@ -0,0 +1,52 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Manipulating Audio in Etro</title>
5
+ </head>
6
+ <body>
7
+ <script type="module">
8
+ import etro from '../../src/index.js'
9
+ let movie
10
+
11
+ const initMovie = () => {
12
+ // initialize movie
13
+ movie = new etro.Movie(document.createElement('canvas'))
14
+ // initialize layers (all with durations clipped to 5 seconds)
15
+ const layer1 = new etro.layer.Audio(0, document.getElementById('layer1'), { duration: 5 })
16
+ const layer2 = new etro.layer.Audio(layer1.duration, document.getElementById('layer2'), { duration: 5 })
17
+ const layer3 = new etro.layer.Audio(layer2.startTime + layer2.duration, document.getElementById('layer3'), { duration: 5 })
18
+
19
+ /*
20
+ Once a media layer is added to the movie, it will automatically be connected to the movie's `actx`
21
+ property.
22
+ */
23
+ // add layers to movie (first, so we can reconnect it to the graph)
24
+ // movie.layers.push.apply(movie.layers, [layer1, layer2, layer3])
25
+ movie.layers.push(layer1, layer2, layer3)
26
+
27
+ // Now, disconnect the layers from the audio node graph and reconnect them with intermediate audio
28
+ // effect nodes.
29
+
30
+ layer1.source.disconnect(movie.actx.destination)
31
+ const muter = movie.actx.createGain()
32
+ muter.gain.value = 0
33
+ layer1.source.connect(muter).connect(movie.actx.destination)
34
+
35
+ layer2.source.disconnect(movie.actx.destination)
36
+ const panner = movie.actx.createStereoPanner()
37
+ panner.pan.value = +1 // completely to the right
38
+ layer2.source.connect(panner).connect(movie.actx.destination)
39
+
40
+ // Manipulating the audio graph is not always necessary
41
+ layer3.playbackRate = 2 // double the speed
42
+
43
+ movie.play()
44
+ }
45
+
46
+ window.addEventListener('load', initMovie)
47
+ </script>
48
+ <audio id="layer1" src="../assets/sample.wav"></audio>
49
+ <audio id="layer2" src="../assets/sample.wav"></audio>
50
+ <audio id="layer3" src="../assets/sample.wav"></audio>
51
+ </body>
52
+ </html>
@@ -0,0 +1,56 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Effects in Etro</title>
5
+ </head>
6
+ <body>
7
+ <script type="module">
8
+ import etro from '../../src/index.js'
9
+ let movie
10
+ window.addEventListener('load', () => {
11
+ const canvas = document.createElement('canvas')
12
+ document.body.appendChild(canvas)
13
+
14
+ initMovie(canvas)
15
+ })
16
+
17
+ const initMovie = canvas => {
18
+ movie = new etro.Movie(canvas)
19
+
20
+ const image = document.querySelector('img')
21
+ canvas.width = image.width
22
+ canvas.height = image.height
23
+ // create a red 400x400 rectangle that starts at time 0 and lasts 2 seconds
24
+ movie
25
+ .addLayer(new etro.layer.Image(0, 2, image))
26
+ // create a transparent blue 500x200 at (50, 20) that starts at time 1 and lasts 2 seconds
27
+ .addLayer(
28
+ new etro.layer.Image(2, 2, image).addEffect(
29
+ new etro.effect.GaussianBlur(3)
30
+ )
31
+ )
32
+ .addLayer(
33
+ new etro.layer.Image(4, 2, image).addEffect(
34
+ // you can also use keyframes for almost any property in Etro
35
+ new etro.effect.Channels({ 0: { r: 2, g: 0.5 }, 2: { r: 0.5, g: 2 } })
36
+ )
37
+ )
38
+ .addLayer(
39
+ new etro.layer.Image(6, 2, image, {
40
+ // allow rotated image to fill entire screen by setting the size of the layer, which is not the image
41
+ width: movie.width, height: movie.height
42
+ }).addEffect(
43
+ new etro.effect.Transform(new etro.effect.Transform.Matrix().rotate(Math.PI / 6)) // 30d
44
+ )
45
+ )
46
+ .addLayer(
47
+ new etro.layer.Image(8, 2, image).addEffect(
48
+ new etro.effect.EllipticalMask(image.width / 2, image.height / 2, image.width / 2, image.height / 2)
49
+ )
50
+ )
51
+ .play()
52
+ }
53
+ </script>
54
+ <img src="../assets/sample.jpg" style="display: none;"/>
55
+ </body>
56
+ </html>
@@ -0,0 +1,70 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Media in Etro</title>
5
+ </head>
6
+ <body>
7
+ <script type="module">
8
+ // TODO: test audio output on a device that actually has drivers
9
+ import etro from '../../src/index.js'
10
+ let movie
11
+ window.addEventListener('load', () => {
12
+ const canvas = document.createElement('canvas')
13
+ canvas.width = 600
14
+ canvas.height = 400
15
+ // no need to add to body, as we don't need to say the movie but just the exported video
16
+
17
+ initMovie(canvas)
18
+ })
19
+
20
+ const initMovie = canvas => {
21
+ movie = new etro.Movie(canvas)
22
+ const video = document.querySelector('#input video')
23
+ movie.width = video.videoWidth
24
+ movie.height = video.videoHeight
25
+ movie
26
+ .addLayer(new etro.layer.Image(0, 3, document.querySelector('#input img'), {
27
+ // crop @ (150, 150) extending (200, 200)
28
+ clipX: 100,
29
+ clipY: 100,
30
+ x: 100,
31
+ y: 100,
32
+ clipWidth: 400,
33
+ clipHeight: 400,
34
+ width: 400,
35
+ height: 400
36
+ }))
37
+ .addLayer(new etro.layer.Video(3, video, {
38
+ // trim video to only include 3 seconds starting 2 minutes into the video in the video
39
+ mediaStartTime: 120,
40
+ duration: 3
41
+ }))
42
+ .addLayer(new etro.layer.Audio(6, document.querySelector('#input audio'), {
43
+ mediaStartTime: 9, // start audio at 9s
44
+ duration: 3 // last 3s
45
+ // volume: 0.25 // 25% of default volume (same as setting volume attribute on audio element)
46
+ }))
47
+
48
+ .record(25)
49
+ .then(blob => {
50
+ const video = document.querySelector('#output video')
51
+ video.src = URL.createObjectURL(blob)
52
+ document.querySelector('p').innerHTML = 'Done'
53
+ })
54
+ .catch(error => {
55
+ throw error
56
+ })
57
+ }
58
+ </script>
59
+ <div id="input">
60
+ <img src="../assets/sample.jpg" style="display:none"/>
61
+ <video src="../assets/sample.ogv" style="display:none"></video>
62
+ <audio src="../assets/sample.wav" style="display:none"></audio>
63
+ </div>
64
+ <div id="output">
65
+ <video controls></video><br>
66
+ </div>
67
+
68
+ <p>Recording</p>
69
+ </body>
70
+ </html>
@@ -0,0 +1,35 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Functions in Etro</title>
5
+ </head>
6
+ <body>
7
+ <script type="module">
8
+ import etro from '../../src/index.js'
9
+ let movie
10
+ window.addEventListener('load', () => {
11
+ const canvas = document.createElement('canvas')
12
+ document.body.appendChild(canvas)
13
+
14
+ initMovie(canvas)
15
+ })
16
+
17
+ const initMovie = canvas => {
18
+ movie = new etro.Movie(canvas)
19
+
20
+ canvas.width = canvas.height = 400
21
+ movie
22
+ // Functions are callbacks that are called every time a property value is queried.
23
+ // For instance, you can set a layer's opacity to the function `Math.random`, which will make the
24
+ // layer's opacity randomized each animation frame.
25
+ .addLayer(new etro.layer.Visual(0, 3, {
26
+ // omitting width or height sets the respective element to fill the screen
27
+ background: 'green',
28
+
29
+ opacity: (element, reltime) => Math.random()
30
+ }))
31
+ .play()
32
+ }
33
+ </script>
34
+ </body>
35
+ </html>
@@ -0,0 +1,33 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Hello World in Etro</title>
5
+ </head>
6
+ <body>
7
+ <script type="module">
8
+ import etro from '../../src/index.js'
9
+ window.addEventListener('load', () => {
10
+ const canvas = document.createElement('canvas')
11
+ canvas.width = 600
12
+ canvas.height = 400
13
+ document.body.appendChild(canvas)
14
+
15
+ new etro.Movie(canvas)
16
+ // create a red rectangle that starts at time 0 and lasts 4 seconds and fills the entire screen
17
+ .addLayer(new etro.layer.Visual(0, 4, {
18
+ background: 'red'
19
+ }))
20
+ // create a transparent blue 500x200 at (50, 20) that starts at time 1 and lasts 2 seconds
21
+ .addLayer(new etro.layer.Visual(1, 2, {
22
+ background: '#0000ff80',
23
+ border: { color: '#00f', thickness: 4 },
24
+ width: 500,
25
+ height: 200,
26
+ x: 50,
27
+ y: 20
28
+ }))
29
+ .play()
30
+ })
31
+ </script>
32
+ </body>
33
+ </html>
@@ -0,0 +1,32 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Hello World in Etro</title>
5
+ </head>
6
+ <body>
7
+ <script type="module">
8
+ import etro from '../../src/index.js'
9
+ window.addEventListener('load', () => {
10
+ const canvas = document.createElement('canvas')
11
+ document.body.appendChild(canvas)
12
+
13
+ const video = document.createElement('video')
14
+ video.src = '../assets/sample.ogv'
15
+
16
+ video.onloadeddata = () => {
17
+ canvas.width = video.videoWidth // you could also do movie.width = video.videoWidth;
18
+ canvas.height = video.videoHeight
19
+ const movie = new etro.Movie(canvas)
20
+ movie
21
+ // add a video layer at 0s in the timeline
22
+ .addLayer(new etro.layer.Video(0, video))
23
+ .play()
24
+
25
+ // FOR TESTING issue#8 (don't delete):
26
+ // movie.setCurrentTime(1);
27
+ // movie.play();
28
+ }
29
+ })
30
+ </script>
31
+ </body>
32
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Keyframes in Etro</title>
5
+ </head>
6
+ <body>
7
+ <script type="module">
8
+ import etro from '../../src/index.js'
9
+ let movie
10
+ window.addEventListener('load', () => {
11
+ const canvas = document.createElement('canvas')
12
+ document.body.appendChild(canvas)
13
+
14
+ initMovie(canvas)
15
+ })
16
+
17
+ const initMovie = canvas => {
18
+ movie = new etro.Movie(canvas)
19
+
20
+ canvas.width = canvas.height = 400
21
+ movie
22
+ // create a red 400x400 rectangle that starts at time 0 and lasts 2 seconds
23
+ // Keyframes let you make a dynamic property that interpolates.
24
+ // For instance, you can set a layer's opacity to decrease over time, effectively making it fade out
25
+ // Numbers and objects interpolate (animate smoothly)
26
+ .addLayer(new etro.layer.Visual(0, 3, {
27
+ // omitting width or height sets the respective element to fill the screen
28
+ background: 'green',
29
+ // opacity=1 @ 0s (relative to the layer) -> opacity=0 @ 1s (relative to the layer)
30
+ opacity: { 0: 1, 3: 0 }
31
+ }))
32
+ // Because strings don't interpolate, you need to convert colors and fonts to objects
33
+ // for a smooth effect (which will then be automatically `.toString()`ed when set on the canvas
34
+ // context).
35
+ .addLayer(new etro.layer.Visual(3, 3, {
36
+ background: { 0: etro.parseColor('red'), 3: new etro.Color(0, 0, 255) }
37
+ }))
38
+ // You can use other types in keyframes, but they will be used sequentially without interpolation
39
+ .addLayer(new etro.layer.Text(6, 3, { 0: 'Hello ...', 1.5: '...world' }))
40
+
41
+ // When interpolating, you can specify how the keyframes will be interpolated
42
+ .addLayer(new etro.layer.Visual(9, 3, {
43
+ width: { 0: movie.width, 3: 0, interpolate: etro.linearInterp }, // (obviously) linear
44
+ height: { 0: movie.height, 3: 0, interpolate: etro.cosineInterp }, // curved
45
+ background: 'blue'
46
+ }))
47
+
48
+ // Of course, you can have more than two keyframes
49
+ .addLayer(new etro.layer.Text(12, 6, 'Etro', {
50
+ background: {
51
+ 0: etro.parseColor('#0ff'),
52
+ 2: etro.parseColor('#ff0'),
53
+ 4: etro.parseColor('#f0f'),
54
+ 6: etro.parseColor('#fff')
55
+ },
56
+ // let's just add another property (fonts can be parsed into objects just like colors)
57
+ font: {
58
+ 0: etro.parseFont('28px monospace'),
59
+ 6: etro.parseFont('36px monospace'),
60
+ interpolate: etro.cosineInterp
61
+ }
62
+ }))
63
+ .play()
64
+ }
65
+ </script>
66
+ </body>
67
+ </html>
@@ -0,0 +1,55 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Media in Etro</title>
5
+ <style> img, video {display: none;} </style>
6
+ </head>
7
+ <body>
8
+ <script type="module">
9
+ import etro from '../../src/index.js'
10
+
11
+ let movie
12
+ window.addEventListener('load', () => {
13
+ const canvas = document.createElement('canvas')
14
+ canvas.width = 600
15
+ canvas.height = 400
16
+ document.body.appendChild(canvas)
17
+
18
+ initMovie(canvas)
19
+ })
20
+
21
+ const initMovie = canvas => {
22
+ movie = new etro.Movie(canvas)
23
+ const video = document.querySelector('video')
24
+ movie.width = video.videoWidth
25
+ movie.height = video.videoHeight
26
+ movie
27
+ .addLayer(new etro.layer.Image(0, 3, document.querySelector('img'), {
28
+ // crop @ (150, 150) extending (200, 200)
29
+ clipX: 100,
30
+ clipY: 100,
31
+ x: 100,
32
+ y: 100,
33
+ clipWidth: 400,
34
+ clipHeight: 400,
35
+ width: 400,
36
+ height: 400
37
+ }))
38
+ .addLayer(new etro.layer.Video(3, video, {
39
+ // trim video to only include 3 seconds starting 2 minutes into the video in the video
40
+ mediaStartTime: 120,
41
+ duration: 3
42
+ }))
43
+ .addLayer(new etro.layer.Audio(6, document.querySelector('audio'), {
44
+ mediaStartTime: 9, // start audio at 9s
45
+ duration: 3 // last 3s
46
+ // volume: 0.25 // 25% of default volume (same as setting volume attribute on audio element)
47
+ }))
48
+ .play()
49
+ }
50
+ </script>
51
+ <img src="../assets/sample.jpg"/>
52
+ <video src="../assets/sample.ogv"></video>
53
+ <audio src="../assets/sample.wav"></audio>
54
+ </body>
55
+ </html>
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Text in Etro</title>
5
+ </head>
6
+ <body>
7
+ <script type="module">
8
+ import etro from '../../src/index.js'
9
+ let movie
10
+ window.addEventListener('load', () => {
11
+ const canvas = document.createElement('canvas')
12
+ canvas.width = 600
13
+ canvas.height = 400
14
+ document.body.appendChild(canvas)
15
+
16
+ initMovie(canvas)
17
+ })
18
+
19
+ const initMovie = canvas => {
20
+ movie = new etro.Movie(canvas)
21
+ movie.addLayer(new etro.layer.Text(0, 4, 'Hello world', {
22
+ font: '24px monospace', color: 'blue'
23
+ })).play()
24
+ }
25
+ </script>
26
+ </body>
27
+ </html>
@@ -0,0 +1,3 @@
1
+ {
2
+ "plugins": ["../node_modules/jsdoc-export-default-interop/dist/index"]
3
+ }
package/karma.conf.js ADDED
@@ -0,0 +1,60 @@
1
+ // Karma configuration
2
+ // Generated on Thu Sep 19 2019 02:05:06 GMT-0400 (Eastern Daylight Time)
3
+
4
+ module.exports = function (config) {
5
+ config.set({
6
+
7
+ // base path that will be used to resolve all patterns (eg. files, exclude)
8
+ basePath: '',
9
+
10
+ // frameworks to use
11
+ // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
12
+ frameworks: ['jasmine'],
13
+
14
+ // list of files / patterns to load in the browser
15
+ files: [
16
+ 'dist/etro.js',
17
+ 'spec/*.spec.js',
18
+ { pattern: 'spec/assets/**/*', included: false }
19
+ ],
20
+
21
+ // list of files / patterns to exclude
22
+ exclude: [
23
+ ],
24
+
25
+ // preprocess matching files before serving them to the browser
26
+ // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
27
+ preprocessors: {
28
+ },
29
+
30
+ // test results reporter to use
31
+ // possible values: 'dots', 'progress'
32
+ // available reporters: https://npmjs.org/browse/keyword/karma-reporter
33
+ reporters: ['progress'],
34
+
35
+ // web server port
36
+ port: 9876,
37
+
38
+ // enable / disable colors in the output (reporters and logs)
39
+ colors: true,
40
+
41
+ // level of logging
42
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
43
+ logLevel: config.LOG_INFO,
44
+
45
+ // enable / disable watching file and executing tests whenever any file changes
46
+ autoWatch: true,
47
+
48
+ // start these browsers
49
+ // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
50
+ browsers: ['ChromeHeadless'],
51
+
52
+ // Continuous Integration mode
53
+ // if true, Karma captures browsers, runs the tests and exits
54
+ singleRun: true,
55
+
56
+ // Concurrency level
57
+ // how many browser should be started simultaneous
58
+ concurrency: Infinity
59
+ })
60
+ }