cm-chessboard 8.4.2 → 8.5.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/README.md CHANGED
@@ -24,7 +24,6 @@ The core of cm-chessboard is small, fast and reduced to the essentials. You can
24
24
  - [Arrows Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/arrows-extension.html) ⇨ renders arrows on the chessboard
25
25
  - [Accessibility Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/accessibility-extension.html) ⇨ makes the chessboard more accessible
26
26
  - [PromotionDialog Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/promotion-dialog-extension.html) ⇨ shows a dialog to select the piece to promote to
27
- - [RenderVideo Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/render-video-extension.html) ⇨ renders a video from the pieces movement on the board (beta version for now)
28
27
 
29
28
  ## Demo and repository
30
29
 
package/index.html CHANGED
@@ -32,7 +32,6 @@ It works, it is cool and it is easy to use. 👍</p>
32
32
  <li><a href="examples/extensions/html-layer-extension.html">HTML Layer extension</a></li>
33
33
  <li><a href="examples/extensions/promotion-dialog-extension.html">PromotionDialog extension</a></li>
34
34
  <li><a href="examples/extensions/accessibility-extension.html">Accessibility extension</a></li>
35
- <li><a href="examples/extensions/render-video-extension.html">RenderVideo extension</a></li>
36
35
  </ul>
37
36
  </div>
38
37
  <h2>Chessboard</h2>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cm-chessboard",
3
- "version": "8.4.2",
3
+ "version": "8.5.1",
4
4
  "description": "A JavaScript chessboard which is lightweight, ES6 module based, responsive, SVG rendered and without dependencies.",
5
5
  "keywords": [
6
6
  "chess",
@@ -179,7 +179,7 @@ export class PromotionDialog extends Extension {
179
179
  this.state.displayState = displayState
180
180
  if (displayState === DISPLAY_STATE.shown) {
181
181
  this.clickDelegate = Utils.delegate(this.chessboard.view.svg,
182
- "mousedown",
182
+ "pointerdown",
183
183
  "*",
184
184
  this.promotionDialogOnClickPiece.bind(this))
185
185
  this.contextMenuListener = this.contextMenu.bind(this)
@@ -57,6 +57,7 @@ export class ChessboardView {
57
57
  this.chessboard.context.removeEventListener("mousedown", this.pointerDownListener)
58
58
  this.chessboard.context.removeEventListener("touchstart", this.pointerDownListener)
59
59
  Svg.removeElement(this.svg)
60
+ this.container.remove()
60
61
  }
61
62
 
62
63
  // Sprite //
@@ -1,45 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>cm-chessboard</title>
6
- <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"/>
7
- <link rel="stylesheet" href="../styles/examples.css"/>
8
- <link rel="stylesheet" href="../../assets/chessboard.css"/>
9
- </head>
10
- <body>
11
- <h1><a href="../..">cm-chessboard</a></h1>
12
- <h2>Example: RenderVideo extension</h2>
13
- <p>With this extension you can render a video from the pieces movement on the board.</p>
14
- <p>It renders .mp4 files in macOS Safari and .webm files in Chrome Browser.</p>
15
- <div class="board board-small" id="board"></div>
16
- <video id="videoOut" controls="controls"></video>
17
- <br/>
18
- <a href="" style="visibility: hidden" id="download-link">Download video</a>
19
- <script type="module">
20
- import {RenderVideo} from "../../src/extensions/render-video/RenderVideo.js"
21
- import {Chessboard} from "../../src/Chessboard.js"
22
- import {FEN} from "../../src/model/Position.js"
23
-
24
- const boardElement = document.getElementById("board")
25
- const chessboard = new Chessboard(boardElement, {
26
- position: FEN.start,
27
- assetsUrl: "../../assets/",
28
- extensions: [{class: RenderVideo}]})
29
- await chessboard.recorderInit()
30
- await chessboard.recorderStart()
31
- await chessboard.recorderPause(500)
32
- await chessboard.movePiece("e2", "e4", true)
33
- await chessboard.recorderPause(500)
34
- await chessboard.movePiece("e7", "e5", true)
35
- await chessboard.recorderPause(1000)
36
- chessboard.recorderStop().then((url) => {
37
- const video = document.getElementById("videoOut")
38
- video.src = url
39
- document.getElementById("download-link").href = url
40
- document.getElementById("download-link").style.visibility = "visible"
41
- })
42
-
43
- </script>
44
- </body>
45
- </html>
@@ -1,162 +0,0 @@
1
- /**
2
- * Author and copyright: Stefan Haack (https://shaack.com)
3
- * Repository: https://github.com/shaack/cm-chessboard
4
- * License: MIT, see file 'LICENSE'
5
- */
6
-
7
- import {Extension, EXTENSION_POINT} from "../../model/Extension.js"
8
- import {ANIMATION_EVENT_TYPE} from "../../view/PositionAnimationsQueue.js"
9
-
10
- export class RenderVideo extends Extension {
11
-
12
- /** @constructor */
13
- constructor(chessboard, props) {
14
- super(chessboard)
15
- this.props = {
16
- mediaType: "auto",
17
- safariMode: true
18
- }
19
- Object.assign(this.props, props)
20
- if(this.props.mediaType === "auto") {
21
- if(MediaRecorder.isTypeSupported("video/mp4;codecs:h264,aac")) {
22
- this.props.mediaType = "video/mp4;codecs:h264,aac"
23
- } else if(MediaRecorder.isTypeSupported("video/webm;codecs=h264")) {
24
- this.props.mediaType = "video/webm;codecs=H264"
25
- } else if(MediaRecorder.isTypeSupported("video/webm")) {
26
- this.props.mediaType = "video/webm"
27
- } else if(MediaRecorder.isTypeSupported("video/mp4")) {
28
- this.props.mediaType = "video/mp4"
29
- }else {
30
- console.error("no suitable mediaType found")
31
- }
32
- }
33
- console.log("recorder mediaType", this.props.mediaType)
34
- this.makeSpriteInline()
35
- this.registerExtensionPoint(EXTENSION_POINT.animation, async (event) => {
36
- if(event.type === ANIMATION_EVENT_TYPE.frame) {
37
- if (this.recorder && this.recorder.state === "recording") {
38
- await this.cloneImageAndRender()
39
- }
40
- }
41
- })
42
- chessboard.recorderInit = () => {
43
- return new Promise((resolve) => {
44
- let all = document.querySelectorAll("svg *")
45
- for (let i = 0; i < all.length; i++) {
46
- this.transferComputedStyle(all[i])
47
- }
48
- const dimensions = this.chessboard.view.svg.getBBox()
49
- this.canvas = document.createElement("canvas")
50
- this.canvas.style.backgroundColor = "#000"
51
- this.canvas.style.display = "none"
52
- this.canvas.width = dimensions.width
53
- this.canvas.height = dimensions.height
54
- this.context = this.canvas.getContext('2d')
55
- document.body.append(this.canvas)
56
-
57
- this.image = new Image()
58
- this.image.width = this.canvas.width
59
- this.image.height = this.canvas.height
60
- this.image.style.position = "absolute"
61
- this.image.style.visibility = "hidden"
62
- document.body.append(this.image)
63
-
64
- this.stream = this.canvas.captureStream(50)
65
- this.recorder = new MediaRecorder(this.stream, {
66
- mimeType: this.props.mediaType})
67
- this.recorder.ondataavailable = (event) => {
68
- if (event.data && event.data.size) {
69
- this.recordedData.push(event.data)
70
- }
71
- }
72
- setTimeout(() => {
73
- resolve()
74
- }, 100)
75
- })
76
- }
77
- chessboard.recorderStart = () => {
78
- return new Promise((resolve) => {
79
- if (this.recorder && this.recorder.state === "recording") {
80
- console.error("recorder is running")
81
- return
82
- }
83
- this.recordedData = []
84
- this.recorder.start(100)
85
- console.log("recorder", this.recorder.state)
86
- resolve()
87
- })
88
- }
89
- /**
90
- * returns the url of the recorded media
91
- */
92
- chessboard.recorderStop = () => {
93
- return new Promise(async (resolve, reject) => {
94
- if (!this.recorder || this.recorder.state !== "recording") {
95
- reject("recorder is not recording")
96
- }
97
- await this.cloneImageAndRender()
98
- setTimeout(() => {
99
- this.recorder.stop()
100
- console.log("recorder", this.recorder.state)
101
- resolve(URL.createObjectURL(new Blob(this.recordedData, {type: this.props.mediaType})))
102
- }, 200)
103
- })
104
- }
105
- chessboard.recorderPause = (ms) => {
106
- return new Promise(async (resolve) => {
107
- await this.cloneImageAndRender()
108
- const interval = setInterval(async () => {
109
- await this.cloneImageAndRender()
110
- }, 50)
111
- setTimeout(async () => {
112
- clearInterval(interval)
113
- await this.cloneImageAndRender()
114
- resolve()
115
- }, ms)
116
- })
117
- }
118
- }
119
-
120
- async cloneImageAndRender() {
121
- return new Promise((resolve) => {
122
- let serialized = new XMLSerializer().serializeToString(this.chessboard.view.svg)
123
- const blob = new Blob([serialized], {type: "image/svg+xml"})
124
- const blobURL = URL.createObjectURL(blob)
125
- // strange Safari "bug" that the content has only 300x150px
126
- const image = this.props.safariMode ? this.image : new Image()
127
- image.onload = () => {
128
- this.context.drawImage(image, 0, 0, this.canvas.width, this.canvas.height, 0, 0, this.canvas.width, this.canvas.height)
129
- resolve()
130
- }
131
- image.src = blobURL
132
- })
133
- }
134
-
135
- transferComputedStyle(element) {
136
- const computedStyle = getComputedStyle(element, null)
137
- for (let i = 0; i < computedStyle.length; i++) {
138
- const style = computedStyle[i] + ""
139
- if (["fill", "stroke", "stroke-width", "font-size"].includes(style)) {
140
- element.style[style] = computedStyle[style]
141
- }
142
- }
143
- }
144
-
145
- makeSpriteInline() {
146
- const wrapper = document.createElement("div")
147
- wrapper.style.display = "none"
148
- document.body.appendChild(wrapper)
149
- const svg = this.chessboard.view.svg
150
- const xhr = new XMLHttpRequest()
151
- xhr.open("GET", this.chessboard.view.getSpriteUrl(), true)
152
- xhr.onload = function () {
153
- const doc = new DOMParser().parseFromString(xhr.response, "text/xml")
154
- const pieces = doc.querySelectorAll("svg>g")
155
- for (const piece of pieces) {
156
- svg.prepend(piece)
157
- }
158
- }
159
- xhr.send()
160
- }
161
-
162
- }