Kaynağa Gözat

concernement on map hover effect, better mappopup

bach 1 yıl önce
ebeveyn
işleme
453e07ec31

+ 60 - 5
src/assets/main.scss

@@ -112,13 +112,68 @@ body{
 
   #map-popup{
     position: absolute;
+    z-index: 10;
+    // outline: 1px solid red;
     // top:0;
     // left: 0;
-    background-color: white;
-    padding: 1em;
-    h1{
-      font-size: 1em;
-      font-weight: 400;
+
+    .popup-content-wrapper{
+      background-color: white;
+      padding: 1em;
+      border-radius: 3px;
+      // min-width: 10em;
+      // max-width: 30em;
+      h1{
+        font-size: 1em;
+        font-weight: 400;
+      }
+    }
+
+    &:before{
+      content: "";
+      display: block;
+      height: 0;
+      width: 2.9em;
+      border-top: 1px solid #01ffe2;
+      position: absolute;
+    }
+
+    &[pos="top-right"]{
+      padding: 0 0 2em 2em;
+      &:before{
+        bottom: 0;
+        left: 0;
+        transform-origin: 0 0;
+        transform: rotate(-45deg);
+      }
     }
+    &[pos="bottom-right"]{
+      padding: 2em 0 0 2em;
+      &:before{
+        top: 0;
+        left: 0;
+        transform-origin: 0 0;
+        transform: rotate(45deg);
+      }
+    }
+    &[pos="top-left"]{
+      padding: 0 2em 2em 0;
+      &:before{
+        bottom: 0;
+        right: 0;
+        transform-origin: right bottom;
+        transform: rotate(45deg);
+      }
+    }
+    &[pos="bottom-left"]{
+      padding: 2em 2em 0 0;
+      &:before{
+        top: 0;
+        right: 0;
+        transform-origin: right top;
+        transform: rotate(-45deg);
+      }
+    }
+
   }
 }

+ 21 - 3
src/components/ConcernementMapItem.vue

@@ -27,6 +27,7 @@ import Tween from "@tweenjs/tween.js";
 
 import { mapState, mapActions } from 'pinia'
 import { ConcernementsStore } from '@/stores/concernements'
+import { CommonStore } from '@/stores/common'
 
 export default {
   inject: ['canvasMap', 'matterEngine'],
@@ -49,14 +50,16 @@ export default {
       tween: null,
       body: null,
       body_parts: [],
-      constraint: null
+      constraint: null,
+      isHover: false
     }
   },
   props: ['concernement', 'opened'],
   computed: {
     ...mapState(ConcernementsStore,['map_mode']),
     ...mapState(ConcernementsStore,['concernementsByID']),
-    ...mapState(ConcernementsStore,['opened_entite_id'])
+    ...mapState(ConcernementsStore,['opened_entite_id']),
+    ...mapState(CommonStore,['hover_elmt'])
   },
   created () {
     // console.log(`ConcernementsMapItem ${this.concernement.id} created`, this.canvasMap, this.matterEngine);
@@ -115,6 +118,17 @@ export default {
         }
       },
       deep: true
+    },
+    hover_elmt: {
+      handler (n, o) {
+        console.log('watch hover_elmt', o, n);
+        if (n && n.type === 'concernement' && n.id === this.id) {
+          this.isHover = true;
+        } else {
+          this.isHover = false;
+        }
+      },
+      deep: true
     }
   },
   methods: {
@@ -725,14 +739,18 @@ export default {
     drawContour(){
       if (this.salientPoints.length > 3) {
         var fillStyle;
+        let strokeStyle = "#000";
         if (!this.isFocused()){
           fillStyle = "rgba(255,255,255,0.3)";
         }else{
           fillStyle = "rgba(255,255,255,0.8)"
+          if (this.isHover) {
+            strokeStyle = "#01ffe2";
+          }
         }
         this.ctx.beginPath();
         this.ctx.lineWidth = 1;
-        this.ctx.strokeStyle = "#000";
+        this.ctx.strokeStyle = strokeStyle;
         this.ctx.fillStyle = fillStyle;
         this.ctx.moveTo(this.pos.x+this.salientPoints[0].pos.x*this.scale*1.15, this.pos.y+this.salientPoints[0].pos.y*this.scale*1.15)
         for (let j = 1; j < this.salientPoints.length; j++) {

+ 44 - 14
src/components/ConcernementMapPopup.vue

@@ -57,8 +57,35 @@ export default {
   methods: {
     onMousemove(e){
       // 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`;
+      let v = "top";
+      let h = "right";
+      if (e.clientX + this.dom.clientWidth > document.body.clientWidth) {
+        h = "left";
+      } else {
+        h = "right";
+      }
+      if (e.clientY - this.dom.clientHeight < 0) {
+        v = "bottom";
+      } else {
+        v = "top";
+      }
+      this.dom.setAttribute("pos", `${v}-${h}`);
+      switch (h) {
+        case "right":
+          this.dom.style.left = `${e.clientX}px`;
+          break;
+        case "left":
+          this.dom.style.left = `${e.clientX - this.dom.clientWidth}px`;
+          break;
+      }
+      switch (v) {
+        case "top":
+          this.dom.style.top = `${e.clientY - this.dom.clientHeight}px`;
+          break;
+        case "bottom":
+          this.dom.style.top = `${e.clientY}px`;
+          break;
+      }
     }
   },
   components: {
@@ -69,18 +96,21 @@ export default {
 
 <template>
   <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>{{ entite.entite.title }}</h1>
-    </section>
-    <section v-if="infos.type === 'besoin'" class="besoin-map-popup">
-      <h1>Besoin</h1>
-    </section>
-    <section v-if="infos.type === 'reponse'" class="reponse-map-popup">
-      <h1>Réponse</h1>
-    </section>
+    
+    <div class="popup-content-wrapper">
+      <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>{{ entite.entite.title }}</h1>
+      </section>
+      <section v-if="infos.type === 'besoin'" class="besoin-map-popup">
+        <h1>Besoin</h1>
+      </section>
+      <section v-if="infos.type === 'reponse'" class="reponse-map-popup">
+        <h1>Réponse</h1>
+      </section>
+    </div>
   </div>
 </template>
 

+ 14 - 10
src/components/MapConcernements.vue

@@ -29,6 +29,7 @@ Matter.use(MatterAttractors);
 
 import { mapState, mapActions } from 'pinia'
 import { ConcernementsStore } from '@/stores/concernements'
+import { CommonStore } from '@/stores/common'
 
 import ConcernementMapPopup from '@components/ConcernementMapPopup.vue';
 
@@ -61,7 +62,8 @@ export default {
     ...mapState(ConcernementsStore,['map_mode']),
     ...mapState(ConcernementsStore,['concernements']),
     ...mapState(ConcernementsStore,['concernementsByID']),
-    ...mapState(ConcernementsStore,['opened'])
+    ...mapState(ConcernementsStore,['opened']),
+    ...mapState(CommonStore,['hover_elmt'])
   },
   created() {
     // MATTER
@@ -109,6 +111,7 @@ export default {
     ...mapActions(ConcernementsStore,['setMapMode']),
     ...mapActions(ConcernementsStore,['openCloseConcernements']),
     ...mapActions(ConcernementsStore,['resetConcernementOpened']),
+    ...mapActions(CommonStore,['setHoverElmt']),
     animate () {
       this.canvasMap.ctx.clearRect(0, 0, this.canvasMap.canvas.width, this.canvasMap.canvas.height)
       // this.canvasMap.canvas.dispatchEvent(this.animateEvent)
@@ -132,7 +135,7 @@ export default {
         query = Matter.Query.point(this.world.bodies, this.mouse.position)
       }
       
-      this.mapPopupData = null;
+      let hover_elmt = null;
       if (query && query.length) {
         // if we have a results
         for (let body of query) {
@@ -140,7 +143,7 @@ export default {
             && 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 = {
+              hover_elmt = {
                 type: 'concernement',
                 id: body.id
               };
@@ -148,14 +151,14 @@ export default {
           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 = {
+              hover_elmt = {
                 type: 'entite',
                 id: body.id
               };
           }
           if (body.item_type === "besoin" // if it is a besoin
             && this.opened) { // if a concernement is opened
-              this.mapPopupData = {
+              hover_elmt = {
                 type: 'besoin',
                 id: body.id
               };
@@ -163,15 +166,16 @@ export default {
 
           if (body.item_type === "reponse" // if it is a besoin
             && this.opened) { // if a concernement is opened
-              this.mapPopupData = {
+              hover_elmt = {
                 type: 'reponse',
                 id: body.id
               };
           }
         }
-        // console.log(`this.mapPopupData type: ${this.mapPopupData.type}, id: ${this.mapPopupData.id}`);
+        // console.log(`hover_elmt type: ${hover_elmt.type}, id: ${hover_elmt.id}`);
       }
-      if (this.mapPopupData) {
+      this.setHoverElmt(hover_elmt);
+      if (hover_elmt) {
         document.body.style.cursor = "pointer";
       } else {
         document.body.style.cursor = "auto";
@@ -293,8 +297,8 @@ export default {
     </ul>
   </nav>
   <ConcernementMapPopup
-    v-if="mapPopupData"
-    :infos="mapPopupData"
+    v-if="hover_elmt"
+    :infos="hover_elmt"
   />  
 </template>
 

+ 18 - 0
src/stores/common.js

@@ -0,0 +1,18 @@
+import { defineStore } from 'pinia'
+
+export const CommonStore = defineStore({
+  id: 'common',
+  state: () => ({
+    hover_elmt: null
+  }),
+  getters: {
+    
+  },
+  actions: {
+    setHoverElmt(elmt) {
+      console.log(`setHoverElmt ${elmt}`);
+      // mode can be : terraindevie, proximite, superposition, puissancedagir, action, doleancer
+      this.hover_elmt = elmt;
+    }
+  }
+})