1
0
Prechádzať zdrojové kódy

enites as matter body and popup display on mouse over entites

bach 2 rokov pred
rodič
commit
a2ae70ef48

+ 1 - 1
src/assets/main.scss

@@ -104,7 +104,7 @@ body{
     }
   }
 
-  #concernement-map-popup{
+  #map-popup{
     position: absolute;
     // top:0;
     // left: 0;

+ 78 - 25
src/components/ConcernementMapItem.vue

@@ -32,6 +32,7 @@ export default {
   inject: ['canvasMap', 'matterEngine'],
   data() {
     return {
+      entities: null,
       // concernement: null,
       canvas: null,
       ctx: null,
@@ -58,6 +59,7 @@ export default {
   created () {
     // console.log("ConcernementsMapItem concernement", this.canvasMap, this.matterEngine);
     this.entites = this.concernement.entites
+    this.entites_byid = this.concernement.entites_byid
     this.parsePoints()
     this.getSalientPoints()
   },
@@ -82,16 +84,11 @@ export default {
     },
     opened: {
       handler (n, o) {
-        if(n){
-          console.log('concernement item opened');
-          // opened
+        if(n){ // opened
           this.openClose(true);
-        }else{
-          console.log('concernement item closed');
-          // closed
+        }else{ // closed
           this.openClose(false)
         }
-        console.log(`watch opened ${this.concernement.id}`, n, o, this.anim);
       },
       deep: true
     }
@@ -105,6 +102,10 @@ export default {
 
       // define init position of the item
       this.pos = this.getRandomPos();
+      //
+      this.initMatterBody()
+    },
+    initMatterBody (){
       
       // MATTER
       // create the matter body and add it to the engine
@@ -114,12 +115,38 @@ export default {
         // https://github.com/liabru/matter-attractors/issues/8        
         // https://github.com/liabru/matter-attractors/blob/master/index.js
         // MatterAttractors.Attractors.gravityConstant = -5;
-        this.body = Matter.Bodies.circle(this.pos.x, this.pos.y, this.ray, {
+        
+        // Create parts of the body : main big circle & entities
+        var parts = [
+          Matter.Bodies.circle(0, 0, this.ray, {
+            item_type: 'concernement',
+            id: this.concernement.id,
+          })
+        ];
+        for (let i = 0; i < this.entites.length; i++) {
+          // parts.push(Matter.Bodies.circle(this.pos.x+this.entites[i].display.pos.x, this.pos.y+this.entites[i].display.pos.y, 15, {
+          //   item_type: 'entite',
+          //   id: this.entites[i].id  
+          // }))
+          parts.push(Matter.Bodies.circle(this.entites[i].display.pos.x, this.entites[i].display.pos.y, 2, {
+            item_type: 'entite',
+            id: this.entites[i].entite.id,
+            isSensor: true
+          }))
+        }
+
+        // create the body
+        this.body = Matter.Body.create({
+          parts: parts,
+          item_type: 'concernement',
+          id: this.concernement.id,
           frictionAir: 0,
           // mass: Math.pow(3, this.entites.length),
           mass: 10,
           restitution: 0.4,
-          id: this.concernement.id,
+          collisionFilter: {
+            group: -1
+          },
           plugin: {
             attractors: [
               // there is a built in helper function for Newtonian gravity!
@@ -128,8 +155,10 @@ export default {
             ]
           }
         });
-        let delta = 10;
+        Matter.Body.setPosition(this.body, this.pos);
+
         // add init velocity
+        let delta = 10;
         Matter.Body.setVelocity(this.body, {
             x: -delta + Math.random()*delta*2,
             y: -delta + Math.random()*delta*2
@@ -137,14 +166,14 @@ export default {
         // console.log('concernementItem mass', this.body.mass);
         Matter.Composite.add(this.matterEngine.world, this.body);
         // console.log('concernement body', this.body);
-      }
 
-      // // listen for animate event dispatched from parent
-      // this.canvas.addEventListener('animate', this.animate)
+        // // listen for animate event dispatched from parent
+        // this.canvas.addEventListener('animate', this.animate)
 
-      // listen for afterUpdate event from Matter.Engine object
-      Matter.Events.on(this.matterEngine, "beforeUpdate", this.onBeforeEngineUpdate)
-      Matter.Events.on(this.matterEngine, "afterUpdate", this.onAfterEngineUpdate);
+        // listen for afterUpdate event from Matter.Engine object
+        Matter.Events.on(this.matterEngine, "beforeUpdate", this.onBeforeEngineUpdate);
+        Matter.Events.on(this.matterEngine, "afterUpdate", this.onAfterEngineUpdate);
+      }
     },
     getRandomPos(){
       return {
@@ -167,8 +196,13 @@ export default {
         // slope = (output_end - output_start) / (input_end - input_start)
         // output = output_start + slope * (input - input_start)
         // from range 0 -> 100 to range 0 -> this.ray
-        let slope = this.ray / 100
-        this.entites[i].display.ray = slope * (100 - entite.prise);
+        let init_max = 100
+        let slope = this.ray / init_max
+        this.entites[i].display.ray = slope * (init_max - entite.prise);
+        // if (this.concernement.id === 28) {
+        //   console.log(`entity prise: ${entite.prise} | ray: ${this.entites[i].display.ray}`);
+        // }
+        
 
         // ANGLE
         // -90 <= mm <= 90
@@ -187,6 +221,8 @@ export default {
           x: this.entites[i].display.ray * Math.cos(this.entites[i].display.alpha * (Math.PI/180)),
           y: this.entites[i].display.ray * Math.sin(this.entites[i].display.alpha * (Math.PI/180))
         }
+
+        this.entites_byid[entite.entite.id].display = this.entites[i].display;
       }
     },
     getSalientPoints () {
@@ -309,7 +345,8 @@ export default {
         this.ctx.beginPath();
         this.ctx.lineWidth = 2;
         this.ctx.strokeStyle = `rgba(255,255,255,${this.opacity})`;
-        this.ctx.arc(this.pos.x, this.pos.y, this.ray*this.scale, 0, 2 * Math.PI, false);
+        // external circle is %8 less than max ray = (*0.92)
+        this.ctx.arc(this.pos.x, this.pos.y, this.ray*this.scale*0.92, 0, 2 * Math.PI, false);
         // this.ctx.stroke();
 
         // interieur circle
@@ -327,9 +364,9 @@ export default {
         
         // fleches
         // haute
-        this.ctx.moveTo(this.pos.x - (8*this.scale), this.pos.y - this.ray*this.scale + (8*this.scale));
-        this.ctx.lineTo(this.pos.x, this.pos.y - this.ray*this.scale);
-        this.ctx.lineTo(this.pos.x + (8*this.scale), this.pos.y - this.ray*this.scale + (8*this.scale));      
+        this.ctx.moveTo(this.pos.x - (8*this.scale), this.pos.y - this.ray*this.scale*0.92 + (8*this.scale));
+        this.ctx.lineTo(this.pos.x, this.pos.y - this.ray*this.scale*0.92);
+        this.ctx.lineTo(this.pos.x + (8*this.scale), this.pos.y - this.ray*this.scale*0.92 + (8*this.scale));      
         // milieu
         this.ctx.moveTo(this.pos.x - (8*this.scale), this.pos.y + (8*this.scale));
         this.ctx.lineTo(this.pos.x, this.pos.y);
@@ -380,10 +417,26 @@ export default {
           let entite = this.entites[i];
           // console.log('entite', entite);
           this.ctx.beginPath();
-          this.ctx.arc(this.pos.x+entite.display.pos.x*this.scale, this.pos.y+entite.display.pos.y*this.scale, 2, 0, 2 * Math.PI, false);
-          this.ctx.fillStyle = "#000";
-          this.ctx.fill();
+          this.ctx.arc(this.pos.x+entite.display.pos.x*this.scale, this.pos.y+entite.display.pos.y*this.scale, 5, 0, 2 * Math.PI, false);
+          this.ctx.strokeStyle = "#F00";
+          this.ctx.stroke();
+        }
+        // OR
+        for (let i = 0; i < this.body.parts.length; i++) {
+          // let entite = this.entites[i];
+          if (this.body.parts[i].item_type === 'entity') {
+            let part = this.body.parts[i];
+            // console.log('part', part);
+            // console.log(`part pos x:${part.position.x} y:${part.position.y} || entity pos  x:${this.pos.x+this.entites_byid[part.id].display.pos.x*this.scale} y:${this.pos.y+this.entites_byid[part.id].display.pos.y*this.scale}`);
+            this.ctx.beginPath();
+            // this.ctx.arc(this.pos.x+entite.display.pos.x*this.scale, this.pos.y+entite.display.pos.y*this.scale, 2, 0, 2 * Math.PI, false);
+            this.ctx.arc(this.body.parts[i].position.x, this.body.parts[i].position.y, 2*this.scale, 0, 2 * Math.PI, false);
+            this.ctx.strokeStyle = "#000";
+            this.ctx.stroke();
+            
+          }
         } 
+
       }
 
       // concernement id @center

+ 33 - 8
src/components/ConcernementMapPopup.vue

@@ -7,28 +7,48 @@ import { ConcernementsStore } from '@/stores/concernements'
 
 export default {
   name: 'concernementMapPopup',  
-  props: ['id'],
+  props: ['infos'],
   data() {
     return {
       dom: null,
-      concernement: null
+      type: null,
+      concernement: null,
+      entite: null
     }
   },
   created () {
-    this.concernement = this.concernementsByID[this.id];
+    // console.log(`popup created type: ${this.infos.type}`);
+    if (this.infos.type === 'concernement') {
+      this.concernement = this.concernementsByID[this.infos.id];
+    } else {
+      this.entite = this.allEntitesById[this.infos.id];
+    }
   },
   mounted () {
     // console.log('APP onMounted')
-    this.dom = this.$refs['concernement-map-popup'];
+    this.dom = this.$refs['map-popup'];
     window.addEventListener('mousemove', this.onMousemove);
   },
   computed: {
     ...mapState(ConcernementsStore,['concernements']),
-    ...mapState(ConcernementsStore,['concernementsByID'])
+    ...mapState(ConcernementsStore,['concernementsByID']),
+    ...mapState(ConcernementsStore,['allEntitesById'])
+  },
+  watch: {
+    infos: {
+      handler (n, o){
+        if (n.type === 'concernement') {
+          this.concernement = this.concernementsByID[n.id];
+        } else {
+          this.entite = this.allEntitesById[n.id];
+        }   
+      },
+      deep: true
+    },
   },
   methods: {
     onMousemove(e){
-      // console.log('popup mousemove', e, this.dom);
+      // console.log(`popup move type: ${this.infos.type}`);
       this.dom.style.left = `${e.clientX + 5}px`;
       this.dom.style.top = `${e.clientY - this.dom.clientHeight - 5}px`;
     }
@@ -40,8 +60,13 @@ export default {
 </script>
 
 <template>
-  <div id="concernement-map-popup" ref="concernement-map-popup">
-    <h1>{{ concernement.title }}</h1>
+  <div id="map-popup" ref="map-popup">
+    <section v-if="infos.type === 'concernement'" class="concernement-map-popup">
+      <h1>{{ concernement.title }}</h1>
+    </section>
+    <section v-if="infos.type === 'entite'" class="entite-map-popup">
+      <h1>alors ? {{ entite.entite.title }}</h1>
+    </section>
   </div>
 </template>
 

+ 46 - 13
src/components/MapConcernements.vue

@@ -46,7 +46,7 @@ export default {
       world: null,
       // render: null,
       mouse: null,
-      concernementpopupid: null
+      mapPopupData: null,
     }
   },
   provide() {
@@ -59,7 +59,8 @@ export default {
   },
   computed: {
     ...mapState(ConcernementsStore,['concernements']),
-    ...mapState(ConcernementsStore,['concernementsByID'])
+    ...mapState(ConcernementsStore,['concernementsByID']),
+    ...mapState(ConcernementsStore,['opened'])
   },
   created() {
     // MATTER
@@ -105,6 +106,7 @@ export default {
   },
   methods: {
     ...mapActions(ConcernementsStore,['openCloseConcernement']),
+    ...mapActions(ConcernementsStore,['resetConcernementOpened']),
     animate () {
       this.canvasMap.ctx.clearRect(0, 0, this.canvasMap.canvas.width, this.canvasMap.canvas.height)
       // this.canvasMap.canvas.dispatchEvent(this.animateEvent)
@@ -113,16 +115,45 @@ export default {
     },
     onMouseMove (e) {
       // check concernement item mouse over
-      const query = Matter.Query.point(Matter.Composite.allBodies(this.world), this.mouse.position)
-      // console.log('mousemove query', query);
-      if (query.length) {
-        if (typeof this.concernementsByID[query[0].id] !== "undefined" && !this.concernementsByID[query[0].id].opened) {
-          this.concernementpopupid = query[0].id;
-        } else {
-          this.concernementpopupid = null;  
+      // const query = Matter.Query.point(Matter.Composite.allBodies(this.world), this.mouse.position)
+      let query;
+      if (this.opened) {
+        // if a concernement is opened we query the opened concernement's parts (aka entitées bodies)
+        const bodies = Matter.Composite.allBodies(this.world);
+        for (let body of bodies) {
+          if (body.item_type === "concernement" && body.id === this.opened.id) {
+            query = Matter.Query.point(body.parts, this.mouse.position);
+            break;    
+          }
+        }
+      } else {
+        // if no concernement opened we query concernements
+        query = Matter.Query.point(this.world.bodies, this.mouse.position)
+      }
+      
+      this.mapPopupData = null;
+      if (query && query.length) {
+        // if we have a results
+        for (let body of query) {
+          if (!this.opened // if no concernement is opened
+            && body.item_type === "concernement" // if it is a concernement
+            && typeof this.concernementsByID[body.id] !== "undefined"  // if the id exists
+            && !this.concernementsByID[body.id].opened) { // if the concernement is not opened
+              this.mapPopupData = {
+                type: 'concernement',
+                id: body.id
+              };
+          }
+          if (body.item_type === "entite" // if it is an entite
+            && this.opened // if a concernement is opened
+            && typeof this.opened.entites_byid[body.id] !== "undefined") { // if the entity exists
+              this.mapPopupData = {
+                type: 'entite',
+                id: body.id
+              };
+          }
         }
-      }else{
-        this.concernementpopupid = null;
+        // console.log(`this.mapPopupData type: ${this.mapPopupData.type}, id: ${this.mapPopupData.id}`);
       }
     },
     onClick (e) {
@@ -141,7 +172,9 @@ export default {
         this.openCloseConcernement(concernement.id, clickedIDs.indexOf(concernement.id) !== -1)
       });
       // if no concernement opened retrun to home (closing concernement contents opened)
+      // and reset the opened state in concernement store
       if (!clickedIDs.length) {
+        this.resetConcernementOpened();
         this.$router.push({name: 'home'});
       }
     }
@@ -190,8 +223,8 @@ export default {
     </ul>
   </nav>
   <ConcernementMapPopup
-    v-if="concernementpopupid"
-    :id="concernementpopupid"
+    v-if="mapPopupData"
+    :infos="mapPopupData"
   />  
 </template>
 

+ 14 - 2
src/stores/concernements.js

@@ -18,6 +18,7 @@ export const ConcernementsStore = defineStore({
   state: () => ({
     concernements: [],
     concernementsByID: {},
+    allEntitesById: {},
     opened: false,
     ct_concernement: {}
   }),
@@ -39,9 +40,17 @@ export const ConcernementsStore = defineStore({
         GQL.post('', { query: print(ast) })
           .then(({ data : { data  : { allconcernements } } }) => {
             console.log('loadconcernements loaded', allconcernements)
-            this.concernements = allconcernements
+            
+            this.concernements = [];
             allconcernements.forEach(concernement => {
-              this.concernementsByID[concernement.id] = concernement
+              concernement.entites_byid = {};
+              concernement.entites.forEach(entite => {
+                concernement.entites_byid[entite.entite.id] = entite;
+                // record a flat list of all entités of all concernement for map-popup
+                this.allEntitesById[entite.entite.id] = entite;
+              });
+              this.concernements.push(concernement);
+              this.concernementsByID[concernement.id] = concernement;
             });
           })
           .catch(error => {
@@ -81,6 +90,9 @@ export const ConcernementsStore = defineStore({
         this.opened = this.concernementsByID[id];
         this.router.push({name: 'concernement', params: {id: id}});
       }
+    },
+    resetConcernementOpened () {
+      this.opened = null;
     }
   }
 })