選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

49 行
1.7KB

  1. const VolumeMap = {
  2. size: 200,
  3. positions: new Map(),
  4. onremove() {
  5. VolumeMap.positions.clear()
  6. },
  7. getDot(username) {
  8. if(VolumeMap.positions.has(username)) {
  9. return VolumeMap.positions.get(username)
  10. }
  11. return [VolumeMap.size / 2, VolumeMap.size / 2]
  12. },
  13. moveNotify({layerX, layerY}) {
  14. wire({kind: 'volumeMapMove', value: [layerX, layerY]})
  15. },
  16. moveDot({detail: {source, value}}) {
  17. VolumeMap.positions.set(source, value)
  18. const [x0, y0] = VolumeMap.getDot(State.username);
  19. for(const video of document.querySelectorAll('video:not(.self')) {
  20. const [x1, y1] = VolumeMap.getDot(video.username)
  21. const dist1 = Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2))
  22. const dist2 = VolumeMap.size / Math.pow(dist1, 1.5) - 0.2
  23. const dist3 = Math.max(Math.min(dist2, 1), 0)
  24. video.style.opacity = dist3
  25. video.volume = dist3
  26. }
  27. },
  28. view() {
  29. const style = {
  30. 'z-index': '999',
  31. 'background-color': 'rgba(65, 105, 225, 0.8)',
  32. 'font-family': 'monospace',
  33. 'position': 'fixed',
  34. 'height': VolumeMap.size + 'px',
  35. 'width': VolumeMap.size + 'px',
  36. 'right': '0',
  37. 'top': '0',
  38. }
  39. return m('svg', {onclick: VolumeMap.moveNotify, style},
  40. m('style', 'text { pointer-events: none }'),
  41. State.online.map(username => {
  42. const [x, y] = VolumeMap.getDot(username)
  43. return m('text', {x, y, fill: 'white'}, `・${username}`)
  44. })
  45. )
  46. },
  47. }
  48. addEventListener('volumeMapMove', VolumeMap.moveDot)