MapConcernements.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <script>
  2. // import { mapActions, mapState } from 'pinia'
  3. import { computed } from 'vue'
  4. import MapBackground from '@components/MapBackground.vue'
  5. // https://brm.io/matter-js/docs/classes/Engine.html
  6. import Matter from "matter-js";
  7. import MatterAttractors from "matter-attractors";
  8. Matter.use(MatterAttractors);
  9. import paper from 'paper';
  10. import { mapState, mapActions } from 'pinia'
  11. import { ConcernementsStore } from '@/stores/concernements'
  12. import { CommonStore } from '@/stores/common'
  13. import ConcernementMapPopup from '@components/ConcernementMapPopup.vue';
  14. export default {
  15. data() {
  16. return {
  17. canvasMap: {
  18. canvas: null,
  19. ctx: null
  20. },
  21. animateEvent: new Event('animate'),
  22. granim: null,
  23. // MATTER
  24. engine: null,
  25. world: null,
  26. // PAPERJS
  27. paper: null,
  28. //
  29. mapPopupData: null,
  30. }
  31. },
  32. provide() {
  33. // https://www.digitalocean.com/community/tutorials/vuejs-vue-html5-canvas
  34. return {
  35. // explicitly provide a computed property
  36. canvasMap: computed(() => this.canvasMap),
  37. matterEngine: computed(() => this.engine)
  38. }
  39. },
  40. computed: {
  41. ...mapState(ConcernementsStore,['map_mode']),
  42. ...mapState(ConcernementsStore,['concernements']),
  43. ...mapState(ConcernementsStore,['concernementsByID']),
  44. ...mapState(ConcernementsStore,['opened']),
  45. ...mapState(CommonStore,['hover_elmt'])
  46. },
  47. created() {
  48. // MATTER
  49. // create an engine
  50. let engineOptions = {
  51. enableSleeping: true,
  52. timing: {
  53. //timestamp: 0.5,
  54. timeScale: 0.5
  55. }
  56. }
  57. this.engine = Matter.Engine.create(engineOptions);
  58. this.engine.gravity.scale = 0;
  59. this.world = this.engine.world;
  60. },
  61. mounted() {
  62. this.canvasMap.canvas = this.$refs['canvas-map'];
  63. this.canvasMap.ctx = this.canvasMap.canvas.getContext('2d');
  64. let canvas_w = this.canvasMap.canvas.width = this.canvasMap.canvas.parentElement.clientWidth;
  65. let canvas_h = this.canvasMap.canvas.height = this.canvasMap.canvas.parentElement.clientHeight;
  66. console.log(`canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);
  67. this.paper = paper.setup(this.canvasMap.canvas);
  68. // // use the paper.view click to get back if no items is clicked
  69. this.paper.view.onClick = function(event) {
  70. console.log("view onClick", this, event.target);
  71. if(event.target._id === "paper-view-0") {
  72. this.resetConcernementOpened();
  73. this.$router.push({
  74. name: 'home',
  75. hash: `#${this.map_mode}`
  76. });
  77. }
  78. }.bind(this);
  79. // MATTER
  80. let wall_w = 100;
  81. Matter.Composite.add(this.world, [
  82. // walls
  83. Matter.Bodies.rectangle(canvas_w/2, -wall_w/2, canvas_w, wall_w, { isStatic: true }), // top
  84. Matter.Bodies.rectangle(canvas_w/2, canvas_h+wall_w/2, canvas_w, wall_w, { isStatic: true }), // bottom
  85. Matter.Bodies.rectangle(-wall_w/2, canvas_h/2, wall_w, canvas_h, { isStatic: true }), // left
  86. Matter.Bodies.rectangle(canvas_w+wall_w/2, canvas_h/2, wall_w, canvas_h, { isStatic: true }), // right
  87. // make the items never goes under menus
  88. Matter.Bodies.rectangle(550, 25, 900, 50, { isStatic: true }), // menu top
  89. Matter.Bodies.rectangle(550, canvas_h-15, 900, 30, { isStatic: true }) // menu bottom
  90. ]);
  91. // add mouse control
  92. // https://github.com/liabru/matter-js/issues/491#issuecomment-331329404
  93. // this.mouse = Matter.Mouse.create(this.canvasMap.canvas);
  94. this.animate()
  95. },
  96. watch: {
  97. hover_elmt: {
  98. handler (n, o) {
  99. // console.log(`watch hover_elmt map`, o, n);
  100. // over highlight effect on paper items
  101. if (n && n.paper_id) {
  102. let nitem = paper.project.getItem({id: n.paper_id});
  103. nitem.bringToFront();
  104. if (nitem.strokeColor) {
  105. nitem.data.prevStrokeColor = nitem.strokeColor.toCSS(true);
  106. nitem.strokeColor = "#01ffe2";
  107. } else {
  108. nitem.data.prevFillColor = nitem.fillColor.toCSS(true);
  109. nitem.fillColor = "#01ffe2";
  110. }
  111. }
  112. if (o && o.paper_id) {
  113. let oitem = paper.project.getItem({id: o.paper_id})
  114. if (oitem.data.prevStrokeColor) {
  115. oitem.strokeColor = oitem.data.prevStrokeColor;
  116. } else {
  117. oitem.fillColor = oitem.data.prevFillColor;
  118. }
  119. }
  120. },
  121. deep: true
  122. }
  123. },
  124. methods: {
  125. ...mapActions(ConcernementsStore,['setMapMode']),
  126. ...mapActions(ConcernementsStore,['openCloseConcernements']),
  127. ...mapActions(ConcernementsStore,['resetConcernementOpened']),
  128. ...mapActions(CommonStore,['setHoverElmt']),
  129. animate () {
  130. Matter.Engine.update(this.engine, 1);
  131. window.requestAnimationFrame(this.animate);
  132. },
  133. },
  134. beforeUpdate () {
  135. },
  136. components: {
  137. MapBackground,
  138. ConcernementMapPopup
  139. }
  140. }
  141. </script>
  142. <template>
  143. <div id="map-backgrounds">
  144. <MapBackground />
  145. </div>
  146. <div id="map-matter">
  147. <canvas ref="canvas-engine"></canvas>
  148. </div>
  149. <div id="map-concernements">
  150. <canvas ref="canvas-map"></canvas>
  151. <slot></slot>
  152. </div>
  153. <nav id="map-nav">
  154. <ul>
  155. <li>
  156. <a href="#terraindevie" @click="setMapMode('terraindevie')"><span class="icon terraindevie"></span> terrain de vie</a>
  157. </li>
  158. <li>
  159. <a href="#proximite" @click="setMapMode('proximite')"><span class="icon proximite"></span> proximité</a>
  160. </li>
  161. <li>
  162. <a href="#superposition" @click="setMapMode('superposition')"><span class="icon superposition"></span> superposition</a>
  163. </li>
  164. <li>
  165. <a href="#puissancedagir" @click="setMapMode('puissancedagir')"><span class="icon puissancedagir"></span> puissance d'agir</a>
  166. </li>
  167. <li>
  168. <a href="#action" @click="setMapMode('action')"><span class="icon action"></span> action</a>
  169. </li>
  170. <li>
  171. <a href="#doleancer" @click="setMapMode('doleancer')"><span class="icon doleancer"></span> cercle politique</a>
  172. </li>
  173. </ul>
  174. </nav>
  175. <ConcernementMapPopup
  176. v-if="hover_elmt && hover_elmt.type !== 'doleance_step'"
  177. :infos="hover_elmt"
  178. />
  179. </template>
  180. <style lang="css" scoped>
  181. </style>