ouatterrir-app/src/components/MapConcernements.vue

354 lines
10 KiB
Vue

<script>
// import { mapActions, mapState } from 'pinia'
import { computed } from 'vue'
import MapBackground from '@components/MapBackground.vue'
// https://brm.io/matter-js/docs/classes/Engine.html
import Matter from "matter-js";
import MatterAttractors from "matter-attractors";
Matter.use(MatterAttractors);
import paper from 'paper';
import { mapState, mapActions } from 'pinia'
import { ConcernementsStore } from '@/stores/concernements'
import { CommonStore } from '@/stores/common'
import ConcernementMapPopup from '@components/ConcernementMapPopup.vue';
export default {
data() {
return {
canvasMap: {
canvas: null,
ctx: null
},
animateEvent: new Event('animate'),
granim: null,
// MATTER
engine: null,
world: null,
// PAPERJS
paper: null,
//
mapPopupData: null,
}
},
provide() {
// https://www.digitalocean.com/community/tutorials/vuejs-vue-html5-canvas
return {
// explicitly provide a computed property
canvasMap: computed(() => this.canvasMap),
matterEngine: computed(() => this.engine)
}
},
computed: {
...mapState(ConcernementsStore,['map_mode']),
...mapState(ConcernementsStore,['concernements']),
...mapState(ConcernementsStore,['concernementsByID']),
// ...mapState(ConcernementsStore,['opened_concernement']),
...mapState(CommonStore,['hover_elmt']),
...mapState(CommonStore,['paper_symbol_definitions'])
},
created() {
// MATTER
// create an engine
let engineOptions = {
enableSleeping: true,
timing: {
//timestamp: 0.5,
timeScale: 0.5
}
}
this.engine = Matter.Engine.create(engineOptions);
this.engine.gravity.scale = 0;
this.world = this.engine.world;
},
mounted() {
this.canvasMap.canvas = this.$refs['canvas-map'];
this.canvasMap.ctx = this.canvasMap.canvas.getContext('2d');
let canvas_w = this.canvasMap.canvas.width = this.canvasMap.canvas.parentElement.clientWidth;
let canvas_h = this.canvasMap.canvas.height = this.canvasMap.canvas.parentElement.clientHeight;
console.log(`canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);
// PAPER
this.paper = paper.setup(this.canvasMap.canvas);
// symbol defintions
this.initPaperSymbols();
// use the paper.view click to get back if no items is clicked
this.paper.view.onClick = function(event) {
console.log("view onClick", this, event.target);
if(event.target._id === "paper-view-0") {
this.resetConcernementOpened();
this.$router.push({
name: 'home',
hash: `#${this.map_mode}`
});
}
}.bind(this);
// MATTER
let wall_w = 100;
Matter.Composite.add(this.world, [
// walls
Matter.Bodies.rectangle(canvas_w/2, -wall_w/2, canvas_w, wall_w, { isStatic: true }), // top
Matter.Bodies.rectangle(canvas_w/2, canvas_h+wall_w/2, canvas_w, wall_w, { isStatic: true }), // bottom
Matter.Bodies.rectangle(-wall_w/2, canvas_h/2, wall_w, canvas_h, { isStatic: true }), // left
Matter.Bodies.rectangle(canvas_w+wall_w/2, canvas_h/2, wall_w, canvas_h, { isStatic: true }), // right
// make the items never goes under menus
Matter.Bodies.rectangle(550, 25, 900, 50, { isStatic: true }), // menu top
Matter.Bodies.rectangle(550, canvas_h-15, 900, 30, { isStatic: true }) // menu bottom
]);
// add mouse control
// https://github.com/liabru/matter-js/issues/491#issuecomment-331329404
// this.mouse = Matter.Mouse.create(this.canvasMap.canvas);
this.animate()
},
watch: {
hover_elmt: {
handler (n, o) {
// console.log(`watch hover_elmt map`, o, n);
// over highlight effect on paper items
if (n && n.paper_id) {
let nitem = paper.project.getItem({id: n.paper_id});
nitem.bringToFront();
if (nitem.strokeColor) {
nitem.data.prevStrokeColor = nitem.strokeColor.toCSS(true);
nitem.strokeColor = "#01ffe2";
} else {
nitem.data.prevFillColor = nitem.fillColor.toCSS(true);
nitem.fillColor = "#01ffe2";
}
}
if (o && o.paper_id) {
let oitem = paper.project.getItem({id: o.paper_id})
if (oitem.data.prevStrokeColor) {
oitem.strokeColor = oitem.data.prevStrokeColor;
} else {
oitem.fillColor = oitem.data.prevFillColor;
}
}
},
deep: true
}
},
methods: {
...mapActions(ConcernementsStore,['setMapMode']),
...mapActions(ConcernementsStore,['resetConcernementOpened']),
// ...mapActions(ConcernementsStore,['openCloseConcernements']),
...mapActions(CommonStore,['addPaperSymbolDefinition']),
animate () {
Matter.Engine.update(this.engine, 1);
window.requestAnimationFrame(this.animate);
},
initPaperSymbols(){
this.addPaperSymbolDefinition('boussole_bg', this.setPaperBoussoleBGSymbol());
},
setPaperBoussoleBGSymbol(){
// BOUSSOLE
let children = [];
let ray = 100;
let pos = {x:0, y:0};
// cercles pointillés
for (let i = 1; i < 9; i++) {
let sw = i === 4 || i === 8 ? 0.5 : 0.25;
let da = i === 4 || i === 8 ? null : [5,5];
children.push(new paper.Path.Circle({
center: [pos.x, pos.y],
radius: ray/8*i,
strokeColor: '#fff',
strokeWidth: sw,
dashArray: da
}));
}
// axes
// vertical
children.push(new paper.Path.Line({
from: [pos.x, pos.y - ray],
to: [pos.x, pos.y + ray],
strokeColor: '#fff',
strokeWidth: 0.5
}));
// horizontal
children.push(new paper.Path.Line({
from: [pos.x - ray, pos.y],
to: [pos.x + ray, pos.y],
strokeColor: '#fff',
strokeWidth: 0.5
}))
// fleches
// haute
children.push(new paper.Path({
segments: [
[pos.x - 8, pos.y - ray + 8],
[pos.x, pos.y - ray],
[pos.x + 8, pos.y - ray + 8],
],
strokeWidth: 0.5,
strokeColor: '#fff',
}));
// milieu
children.push(new paper.Path({
segments: [
[pos.x - 8, pos.y + 8],
[pos.x, pos.y],
[pos.x + 8, pos.y + 8],
],
strokeWidth: 0.5,
strokeColor: '#fff',
}));
// MOINS - PLUS
// PLUS
// horizontal
children.push(new paper.Path.Line({
from: [pos.x + ray - 5, pos.y - ray],
to: [pos.x + ray + 5, pos.y - ray],
strokeWidth: 2,
strokeColor: '#fff',
}))
// vertical
children.push(new paper.Path.Line({
from: [pos.x + ray, pos.y - ray - 5],
to: [pos.x + ray, pos.y - ray + 5],
strokeWidth: 2,
strokeColor: '#fff',
}))
// MOINS
// horizontal
children.push(new paper.Path.Line({
from: [pos.x - ray - 5, pos.y - ray],
to: [pos.x - ray + 5, pos.y - ray],
strokeWidth: 2,
strokeColor: '#fff',
}))
let fontsize = 4;
let fontFamily = "public_sans";
children.push(new paper.PointText({
point: [pos.x + 4.5, pos.y - ray - 5],
content: `entités qui menacent \u2194 entités qui maintiennent`,
fontSize: fontsize,
fontFamily: fontFamily,
justification: 'center',
fillColor: '#000',
}))
children.push(new paper.PointText({
point: [pos.x - ray - 5, pos.y + 1],
content: "axe d'intensité",
fontSize: fontsize,
fontFamily: fontFamily,
justification: 'right',
fillColor: '#000',
}))
children.push(new paper.PointText({
point: [pos.x + ray + 5, pos.y - 3],
content: "situation future\n\u2195\nsituation actuelle",
fontSize: fontsize,
fontFamily: fontFamily,
justification: 'left',
fillColor: '#000',
}))
let t1 = new paper.PointText({
point: [pos.x - ray/8*2.3, pos.y - ray/8*2.3],
content: "avec prise",
fontSize: fontsize,
fontFamily: fontFamily,
justification: 'center',
fillColor: '#000',
})
t1.rotate(-45)
children.push(t1)
let t2 = new paper.PointText({
point: [pos.x - ray/8*2.95, pos.y - ray/8*2.95],
content: "sans prise",
fontSize: fontsize,
fontFamily: fontFamily,
justification: 'center',
fillColor: '#000',
})
t2.rotate(-45)
children.push(t2)
return new paper.Group({
children: children,
pivot: new paper.Point(pos),
name: 'boussole_bg',
locked: true,
});
}
},
beforeUpdate () {
},
components: {
MapBackground,
ConcernementMapPopup
}
}
</script>
<template>
<div id="map-backgrounds">
<MapBackground />
</div>
<div id="map-matter">
<canvas ref="canvas-engine"></canvas>
</div>
<div id="map-concernements">
<canvas ref="canvas-map"></canvas>
<slot></slot>
</div>
<nav id="map-nav">
<ul>
<li>
<a href="#terraindevie" @click="setMapMode('terraindevie')"><span class="icon terraindevie"></span> terrain de vie</a>
</li>
<li>
<a href="#proximite" @click="setMapMode('proximite')"><span class="icon proximite"></span> proximité</a>
</li>
<li>
<a href="#superposition" @click="setMapMode('superposition')"><span class="icon superposition"></span> superposition</a>
</li>
<li>
<a href="#puissancedagir" @click="setMapMode('puissancedagir')"><span class="icon puissancedagir"></span> puissance d'agir</a>
</li>
<li>
<a href="#action" @click="setMapMode('action')"><span class="icon action"></span> action</a>
</li>
<li>
<a href="#doleancer" @click="setMapMode('doleancer')"><span class="icon doleancer"></span> cercle politique</a>
</li>
</ul>
</nav>
<ConcernementMapPopup
v-if="hover_elmt && hover_elmt.type !== 'doleance_step'"
:infos="hover_elmt"
/>
</template>
<style lang="css" scoped>
</style>