You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
3.9 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. export class Display {
  2. constructor(baseUrl, dispatch, target) {
  3. this.baseUrl = baseUrl
  4. this.target = target
  5. target.addEventListener('click', e => {
  6. let target = e.target
  7. while (target.nodeName !== 'A') {
  8. target = target.parentNode
  9. if (!target) return
  10. }
  11. window.history.pushState(null, "", target.href)
  12. dispatch(target.getAttribute('href'))
  13. e.preventDefault()
  14. })
  15. this.graph = new Springy.Graph()
  16. this.layout = new Springy.Layout.ForceDirected(
  17. this.graph,
  18. 400.0, // Spring stiffness
  19. 400.0, // Node repulsion
  20. 0.5 // Damping
  21. )
  22. }
  23. render(state) {
  24. const target = document.createElement('div')
  25. target.className = 'wrapper'
  26. const field = document.createElement('ul')
  27. field.className = 'items'
  28. field.addEventListener('dragstart', e => {
  29. let target = findA(e.target)
  30. if (!target || !target.draggable) return
  31. e.dataTransfer.setData('application/prs.x', target.dataset['id'])
  32. e.dataTransfer.effectAllowed = 'link'
  33. })
  34. field.addEventListener('dragenter', e => {
  35. let target = findA(e.target)
  36. if (!target) return
  37. e.preventDefault()
  38. })
  39. field.addEventListener('dragover', e => {
  40. let target = findA(e.target)
  41. if (!target) return
  42. e.preventDefault()
  43. })
  44. field.addEventListener('drop', e => {
  45. let target = findA(e.target)
  46. if (!target) return
  47. e.preventDefault()
  48. dispatch({ action: 'link', from: e.dataTransfer.getData("application/prs.x"), to: target.dataset['id']})
  49. })
  50. const graph = this.graph
  51. for (const item of state.items) {
  52. graph.addNode(new Springy.Node(item.id, item))
  53. }
  54. let currentBB = this.layout.getBoundingBox()
  55. let width = this.target.scrollWidth || 100
  56. let height = this.target.scrollHeight || 100
  57. var toScreen = function(p) {
  58. var size = currentBB.topright.subtract(currentBB.bottomleft);
  59. var sx = p.subtract(currentBB.bottomleft).divide(size.x).x * (width - 100);
  60. var sy = p.subtract(currentBB.bottomleft).divide(size.y).y * (height - 100);
  61. return new Springy.Vector(sx, sy);
  62. };
  63. var fromScreen = function(s) {
  64. var size = currentBB.topright.subtract(currentBB.bottomleft);
  65. var px = (s.x / canvas.width) * size.x + currentBB.bottomleft.x;
  66. var py = (s.y / canvas.height) * size.y + currentBB.bottomleft.y;
  67. return new Springy.Vector(px, py);
  68. };
  69. var renderer = new Springy.Renderer(
  70. this.layout,
  71. () => {
  72. currentBB = this.layout.getBoundingBox()
  73. width = this.target.scrollWidth
  74. height = this.target.scrollHeight
  75. field.innerHTML = ''
  76. },
  77. function drawEdge(edge, p1, p2) {
  78. // draw an edge
  79. },
  80. function drawNode(item, p) {
  81. const target = toScreen(p)
  82. const dom = document.createElement('li')
  83. const a = document.createElement('a')
  84. const action = item.data.state == 'face-down' ? 'flip' : 'show'
  85. a.href = `/${item.id}/${action}`
  86. a.style.backgroundImage = `url(img/${item.data.img})`
  87. dom.className = item.data.state
  88. dom.style.position = 'absolute'
  89. dom.style.left = target.x + 'px'
  90. dom.style.top = target.y + 'px'
  91. dom.appendChild(a)
  92. field.appendChild(dom)
  93. }, undefined, undefined,
  94. () => {
  95. const dd = new diffDOM.DiffDOM()
  96. const diff = dd.diff(this.target.children[0], field)
  97. dd.apply(this.target.children[0], diff)
  98. }
  99. );
  100. target.appendChild(field)
  101. if (state.show !== null) {
  102. const wrapper = document.createElement('a')
  103. wrapper.href = '/'
  104. const fullview = document.createElement('div')
  105. wrapper.className = 'fullview'
  106. wrapper.appendChild(fullview)
  107. target.appendChild(wrapper)
  108. }
  109. const dd = new diffDOM.DiffDOM()
  110. const diff = dd.diff(this.target, target)
  111. dd.apply(this.target, diff)
  112. renderer.start();
  113. }
  114. }