class Player { constructor(wrapperEl) { this.wrapperEl = wrapperEl; this.svgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); this.wrapperEl.appendChild(this.svgEl); } playlist(url) { const request = new Request(url, { method: 'GET', }); fetch(request) .then(response => response.json()) .then(data => { let playlist = this.wrapperEl.querySelector('.playlist'); if(!playlist) { playlist = document.createElement('nav'); playlist.classList.add('playlist'); this.wrapperEl.appendChild(playlist) } else{ playlist.innerHTML = ""; } const listEl = document.createElement("ul"); for(let fileUrl of data) { const liEl = document.createElement("li"); liEl.innerText = fileUrl liEl.addEventListener('click', (e) => { this.play(fileUrl); playlist.style.display = "none"; }); listEl.appendChild(liEl); } playlist.appendChild(listEl); // do something with the data sent in the request }); } play(file) { const request = new Request(file, { method: 'GET', }); fetch(request) .then(response => response.json()) .then(data => { this.playStrokes(data) // do something with the data sent in the request }); } playStrokes(drawing){ this.strokes = drawing.shape; this.currentPath = null; this.dimensions = drawing.dimensions; this.svgEl.setAttribute('viewBox', `0 0 ${this.dimensions[0]} ${this.dimensions[1]}`) this.startTime = window.performance.now() - this.strokes[0].points[0][3]; this.playStroke(0,1); } playStroke(path_i, point_i){ const path = this.strokes[path_i]; // console.log(path); let pathEl = this.svgEl.querySelector(`.path${path_i}`); if(!pathEl){ pathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path'); pathEl.style.stroke = path.color; pathEl.classList.add('path'+path_i) this.svgEl.appendChild(pathEl) } const d = this.strokes2D(path.points.slice(0, point_i)); pathEl.setAttribute('d', d); let next_path, next_point,t; if(path.points.length > point_i + 1){ next_path = path_i; next_point = point_i + 1; t = path.points[next_point][3];// - path.points[point_i][3]; // setTimeout(() => this.playStroke(next_path, next_point), dt); } else if(this.strokes.length > path_i + 1) { next_path = path_i + 1; next_point = 1; t = this.strokes[next_path].points[next_point][3];// - path.points[point_i][3]; // use starttime instead of diff, to prevent floating } else { console.log('done'); return } const dt = t - (window.performance.now() - this.startTime); setTimeout(() => this.playStroke(next_path, next_point), dt); } playUntil(path_i){ // for scrubber } strokes2D(strokes) { // strokes to a d attribute for a path let d = ""; let last_stroke = undefined; let cmd = ""; for (let stroke of strokes) { if (!last_stroke) { d += `M${stroke[0] * this.dimensions[0]},${stroke[1] * this.dimensions[1]} `; cmd = 'M'; } else { if (last_stroke[2] == 1) { d += " m"; cmd = 'm'; } else if (cmd != 'l') { d += ' l '; cmd = 'l'; } let rel_stroke = [stroke[0] - last_stroke[0], stroke[1] - last_stroke[1]]; d += `${rel_stroke[0] * this.dimensions[0]},${rel_stroke[1] * this.dimensions[1]} `; } last_stroke = stroke; } return d; } }