MapConcernements.vue 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537
  1. <script>
  2. // import { mapActions, mapState } from 'pinia'
  3. import { computed } from 'vue'
  4. import { nextTick } from 'vue'
  5. import MapBackground from '@components/MapBackground.vue'
  6. // https://brm.io/matter-js/docs/classes/Engine.html
  7. import Matter from "matter-js";
  8. import MatterAttractors from "matter-attractors";
  9. Matter.use(MatterAttractors);
  10. import paper from 'paper';
  11. import { mapState, mapActions } from 'pinia'
  12. import { ConcernementsStore } from '@/stores/concernements'
  13. import { CommonStore } from '@/stores/common'
  14. import ConcernementMapPopup from '@components/ConcernementMapPopup.vue';
  15. import RecitPlayer from '@components/RecitPlayer.vue';
  16. // import iconTerraindevie from "@/assets/icons/terraindevie.svg"
  17. // import iconProximite from "@/assets/icons/proximite.svg"
  18. // import iconSuperposition from "@/assets/icons/superposition.svg"
  19. // import iconPuissanceagir from "@/assets/icons/puissancedagir.svg"
  20. // import iconAction from "@/assets/icons/action_2.svg"
  21. // import iconDoleancer from "@/assets/icons/doleancer.svg"
  22. export default {
  23. data() {
  24. return {
  25. canvasMap: {
  26. canvas: null,
  27. ctx: null
  28. },
  29. animateEvent: new Event('animate'),
  30. granim: null,
  31. // MATTER
  32. engine: null,
  33. world: null,
  34. walls: null,
  35. // PAPERJS
  36. paper: null,
  37. //
  38. mapPopupData: null,
  39. //
  40. superpositions_constraints: []
  41. }
  42. },
  43. provide() {
  44. // https://www.digitalocean.com/community/tutorials/vuejs-vue-html5-canvas
  45. return {
  46. // explicitly provide a computed property
  47. canvasMap: computed(() => this.canvasMap),
  48. matterEngine: computed(() => this.engine)
  49. }
  50. },
  51. computed: {
  52. ...mapState(ConcernementsStore,['map_mode',
  53. 'concernements',
  54. 'concernementsByID',
  55. 'opened_concernement',
  56. 'opened_entite_id',
  57. 'opened_recit',
  58. 'allSuperpositions',
  59. // 'allSuperpositions_bycids',
  60. 'allSuperpositions_clustered',
  61. 'allMapItems_byid'
  62. ]),
  63. ...mapState(CommonStore,['map_item_ray',
  64. 'hover_elmt',
  65. 'paper_symbol_definitions'])
  66. },
  67. created() {
  68. // MATTER
  69. // create an engine
  70. let engineOptions = {
  71. enableSleeping: true,
  72. timing: {
  73. //timestamp: 0.5,
  74. timeScale: 0.5
  75. },
  76. // constraintIterations: 20,
  77. // positionIterations: 20,
  78. // velocityIterations: 20
  79. }
  80. this.engine = Matter.Engine.create(engineOptions);
  81. this.engine.gravity.scale = 0;
  82. this.world = this.engine.world;
  83. // listen for afterUpdate event from Matter.Engine object
  84. Matter.Events.on(this.engine, "beforeUpdate", this.onBeforeEngineUpdate);
  85. Matter.Events.on(this.engine, "afterUpdate", this.onAfterEngineUpdate);
  86. },
  87. mounted() {
  88. console.log('map mounted');
  89. this.canvasMap.canvas = this.$refs['canvas-map'];
  90. this.canvasMap.ctx = this.canvasMap.canvas.getContext('2d');
  91. let canvas_w = this.canvasMap.canvas.width = this.canvasMap.canvas.parentElement.clientWidth;
  92. let canvas_h = this.canvasMap.canvas.height = this.canvasMap.canvas.parentElement.clientHeight;
  93. console.log(`canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);
  94. // PAPER
  95. this.paper = paper.setup(this.canvasMap.canvas);
  96. // symbol defintions
  97. this.initPaperSymbols();
  98. // use the paper.view click to get back if no items is clicked
  99. this.paper.view.onClick = function(event) {
  100. // console.log("view onClick", this, event.target);
  101. if(event.target._id === "paper-view-0") {
  102. this.resetConcernementOpened();
  103. this.$router.push({
  104. name: 'home',
  105. hash: `#${this.map_mode}`
  106. });
  107. }
  108. }.bind(this);
  109. // use the paper.view mousemouve to removed mappopup
  110. this.paper.view.onMouseMove = function(event) {
  111. // console.log("view onMouseMove", event.target);
  112. if(event.target._id === "paper-view-0") {
  113. this.setHoverElmt(null);
  114. }
  115. }.bind(this);
  116. // MATTER
  117. this.buildMatterWalls();
  118. // add mouse control
  119. // https://github.com/liabru/matter-js/issues/491#issuecomment-331329404
  120. // this.mouse = Matter.Mouse.create(this.canvasMap.canvas);
  121. window.addEventListener("resize", this.onWindowResize.bind(this));
  122. this.animate()
  123. },
  124. watch: {
  125. hover_elmt: {
  126. handler (n, o) {
  127. // console.log(`watch hover_elmt map: o, n`, o, n);
  128. // over highlight effect on paper items
  129. if (n && n.paper_id) {
  130. let nitem = paper.project.getItem({id: n.paper_id});
  131. console.log('watch hover_element nitem', nitem.definition);
  132. if (!nitem.is_symbol_instance) { // not symbol instance
  133. nitem.bringToFront();
  134. if (nitem.strokeColor) {
  135. nitem.data.prevStrokeColor = nitem.strokeColor.toCSS(true);
  136. nitem.strokeColor = "#01ffe2";
  137. } else {
  138. nitem.data.prevFillColor = nitem.fillColor.toCSS(true);
  139. nitem.fillColor = "#01ffe2";
  140. }
  141. } else { // is a symbol instanceof, then swap
  142. console.log(`symbol instance n.type:${n.type}, nitem`, nitem);
  143. switch (n.type) {
  144. case 'entite':
  145. nitem.definition = this.paper_symbol_definitions.entite_hover;
  146. break;
  147. case 'besoin':
  148. nitem.definition = this.paper_symbol_definitions.besoin_hover;
  149. break;
  150. case 'reponse':
  151. nitem.definition = this.paper_symbol_definitions.reponse_hover;
  152. break;
  153. case 'entite_action':
  154. nitem.definition = this.paper_symbol_definitions.entite_action_hover;
  155. break;
  156. }
  157. }
  158. }
  159. if (o && o.paper_id && (!n || o.paper_id !== n.paper_id)) {
  160. let oitem = paper.project.getItem({id: o.paper_id})
  161. if (oitem) {
  162. console.log('watch hover_element oitem', oitem);
  163. if (!oitem.is_symbol_instance) { // not symbol instance
  164. if (oitem.data.prevStrokeColor) {
  165. oitem.strokeColor = oitem.data.prevStrokeColor;
  166. } else {
  167. oitem.fillColor = oitem.data.prevFillColor;
  168. }
  169. } else { // is a symbol instanceof, then swap
  170. console.log(`symbol instance o.type:${o.type}, oitem`, oitem);
  171. switch (o.type) {
  172. case 'entite':
  173. // console.log('this.opened_entite_id', parseInt(this.opened_entite_id), 'oitem.item_id', oitem.item_id);
  174. if (!this.opened_entite_id || parseInt(this.opened_entite_id) !== oitem.item_id) {
  175. oitem.definition = this.paper_symbol_definitions.entite;
  176. }
  177. break;
  178. case 'besoin':
  179. oitem.definition = this.paper_symbol_definitions.besoin;
  180. break;
  181. case 'reponse':
  182. oitem.definition = this.paper_symbol_definitions.reponse;
  183. break;
  184. case 'entite_action':
  185. if (!this.opened_entite_id || parseInt(this.opened_entite_id) !== oitem.item_id) {
  186. oitem.definition = this.paper_symbol_definitions.entite_action;
  187. }
  188. break;
  189. }
  190. }
  191. }
  192. }
  193. },
  194. deep: true
  195. },
  196. map_mode: {
  197. handler (n, o) {
  198. console.log('concernementMap watch map_mode o n', o, n);
  199. if (n === 'superposition') { // && !this.opened_concernement
  200. // create constraints
  201. this.setSuperpositionsMatterConstraints();
  202. }else{
  203. // destroy constraints
  204. this.clearSuperpositionsMatterConstraints();
  205. }
  206. },
  207. deep: true
  208. },
  209. opened_concernement: {
  210. handler (n, o) {
  211. console.log('concernementMap watch opened_concernement o n', o, n);
  212. // if (n && this.map_mode === 'superposition') {
  213. // this.clearSuperpositionsMatterConstraints();
  214. // }
  215. // if(o && !n){
  216. // this.setSuperpositionsMatterConstraints();
  217. // }
  218. },
  219. deep: true
  220. },
  221. allSuperpositions: {
  222. handler (n, o) {
  223. console.log('concernementMap watch allSuperpositions', o, n);
  224. if (this.map_mode === "superposition" && n && n.length) {
  225. // create constraints with a delay (watch is needed for first page load)
  226. window.setTimeout(this.setSuperpositionsMatterConstraints, 200);
  227. }
  228. // else{
  229. // // destroy constraints
  230. // this.clearSuperpositionsMatterConstraints();
  231. // }
  232. },
  233. deep: true
  234. },
  235. // opened_concernement: {
  236. // handler (n, o) {
  237. // console.log('map opened_concernement', this.opened_concernement);
  238. // if (this.map_mode === 'superposition' && n) {
  239. // this.resetSuperpositionsMatterConstraints();
  240. // }
  241. // },
  242. // deep: true
  243. // }
  244. },
  245. methods: {
  246. ...mapActions(ConcernementsStore,['setMapMode',
  247. 'resetConcernementOpened']),
  248. ...mapActions(CommonStore,['addPaperSymbolDefinition',
  249. 'setHoverElmt',
  250. 'updateMapItemRay']),
  251. animate () {
  252. // if (document.hasFocus()) {
  253. Matter.Engine.update(this.engine, 1);
  254. // }
  255. window.requestAnimationFrame(this.animate);
  256. },
  257. buildMatterWalls(){
  258. console.log('buildMatterWalls');
  259. // remove old walls if exists
  260. let oldWallsBody = Matter.Composite.get(this.world, 'walls', 'body');
  261. if (oldWallsBody) {
  262. console.log('buildMatterWalls oldWallsBody', oldWallsBody);
  263. Matter.Composite.remove(this.world, oldWallsBody);
  264. }
  265. console.log('buildMatterWalls oldWallsBody after remove', Matter.Composite.get(this.world, 'walls', 'body'));
  266. // create walls
  267. let canvas_w = this.canvasMap.canvas.width;
  268. let canvas_h = this.canvasMap.canvas.height;
  269. console.log(`buildMatterWalls canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);
  270. let length = 10000; // set a length long enought that we don't have to redimmension it when window resize
  271. let thickness = 1000;
  272. let pad = 1;
  273. let wallsParts = [
  274. // walls
  275. // Matter.Bodies.rectangle(x, y, width, height, [options])
  276. Matter.Bodies.rectangle(canvas_w/2, -thickness/2 +pad, length, thickness, { label: 'top_wall'}), // top
  277. Matter.Bodies.rectangle(canvas_w/2, canvas_h+thickness/2 -pad, length, thickness, { label: 'bottom_wall'}), // bottom
  278. Matter.Bodies.rectangle(-thickness/2 +pad, canvas_h/2, thickness, length, { label: 'left_wall'}), // left
  279. Matter.Bodies.rectangle(canvas_w+thickness/2 -pad, canvas_h/2, thickness, length, { label: 'right_wall'}), // right
  280. // make the items never goes under menus
  281. // Matter.Bodies.rectangle(500, 25, 1000, 50, { label: 'menutop_wall'}), // menu top
  282. // Matter.Bodies.rectangle(500, canvas_h-15, 1000, 30, { label: 'menubottom_wall'}) // menu bottom
  283. ];
  284. this.walls = Matter.Body.create({
  285. parts: wallsParts,
  286. id: 'walls',
  287. isStatic: true
  288. });
  289. Matter.Composite.add(this.world, this.walls);
  290. console.log('buildMatterWalls this.walls', this.walls);
  291. },
  292. updateMatterWalls(){
  293. let canvas_w = this.canvasMap.canvas.width;
  294. let canvas_h = this.canvasMap.canvas.height;
  295. console.log(`buildMatterWalls canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);
  296. let thickness = 1000;
  297. let pad = 10;
  298. this.walls.parts.forEach((p, i) =>{
  299. // console.log('p.label', p.label);
  300. let pos = false;
  301. switch (p.label) {
  302. case 'top_wall':
  303. pos = Matter.Vector.create(canvas_w/2, -thickness/2 +pad)
  304. break;
  305. case 'bottom_wall':
  306. pos = Matter.Vector.create(canvas_w/2, canvas_h+thickness/2 -pad)
  307. break;
  308. case 'left_wall':
  309. pos = Matter.Vector.create(-thickness/2 +pad, canvas_h/2)
  310. break;
  311. case 'right_wall':
  312. pos = Matter.Vector.create(canvas_w+thickness/2 -pad, canvas_h/2)
  313. break;
  314. case 'menutop_wall':
  315. pos = Matter.Vector.create(500, 25)
  316. break;
  317. case 'menubottom_wall':
  318. pos = Matter.Vector.create(500, canvas_h-15)
  319. break;
  320. }
  321. if(pos){
  322. Matter.Body.setPosition(p, pos);
  323. }
  324. })
  325. },
  326. onWindowResize(e){
  327. // console.log('onWindowResize', e);
  328. // get the new size
  329. let canvas_w = this.canvasMap.canvas.width = this.canvasMap.canvas.parentElement.clientWidth;
  330. let canvas_h = this.canvasMap.canvas.height = this.canvasMap.canvas.parentElement.clientHeight;
  331. console.log(`canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);
  332. // apply to paper env
  333. // paper.view.viewSize.width = canvas_w;
  334. // paper.view.viewSize.height = canvas_h;
  335. this.paper.view.viewSize = new paper.Size(canvas_w, canvas_h);
  336. // apply to matter env
  337. // this.buildMatterWalls();
  338. this.updateMatterWalls();
  339. // resize the base item ray, this will trigger all the map_items to resize in nextTick()
  340. this.updateMapItemRay();
  341. // rebuild all the paper symbols with new ray
  342. this.initPaperSymbols(true)
  343. },
  344. initPaperSymbols(update){
  345. this.addPaperSymbolDefinition('boussole_bg', this.setPaperBoussoleBGSymbol());
  346. this.addPaperSymbolDefinition('puissanceagir_bg', this.setPaperPuissanceagirBGSymbol());
  347. // this.addPaperSymbolDefinition('puissanceagir_icon', this.setPaperPuissanceagirICONSymbol());
  348. this.addPaperSymbolDefinition('doleance_bg', this.setPaperDoleanceBGSymbol());
  349. // this.addPaperSymbolDefinition('doleance_icon', this.setPaperDoleanceICONSymbol());
  350. if (!update) {
  351. this.addPaperSymbolDefinition('entite', this.setPaperEntiteSymbol());
  352. this.addPaperSymbolDefinition('entite_hidden', this.setPaperHiddenEntiteSymbol());
  353. this.addPaperSymbolDefinition('entite_hover', this.setPaperEntiteHoverSymbol());
  354. this.addPaperSymbolDefinition('entite_action_icon', this.setPaperEntiteActionIconSymbol());
  355. this.addPaperSymbolDefinition('entite_action', this.setPaperEntiteActionSymbol());
  356. this.addPaperSymbolDefinition('entite_action_hover', this.setPaperEntiteActionHoverSymbol());
  357. this.addPaperSymbolDefinition('besoin', this.setPaperBesoinSymbol());
  358. this.addPaperSymbolDefinition('besoin_hover', this.setPaperBesoinHoverSymbol());
  359. this.addPaperSymbolDefinition('reponse', this.setPaperReponseSymbol());
  360. this.addPaperSymbolDefinition('reponse_hover', this.setPaperReponseHoverSymbol());
  361. }
  362. },
  363. setPaperBoussoleBGSymbol(){
  364. // BOUSSOLE
  365. let children = [];
  366. let ray = this.map_item_ray;
  367. let pos = {x:0, y:0};
  368. // big invisible global exterior circle to keep center aligned
  369. children.push(new paper.Path.Circle({
  370. center: [0, 0],
  371. radius: ray*3,
  372. style: {
  373. strokeColor: 'rgba(255,255,255,0)',
  374. strokeWidth: 0.5
  375. }
  376. }));
  377. // cercles
  378. // for (let i = 1; i < 9; i++) {
  379. // let sw = i === 4 || i === 8 ? 0.25 : 0.1; // width
  380. // let da = i === 4 || i === 8 ? null : [5,5]; // dash array
  381. // if (!da) { // draw only 2 main non-dashed circles
  382. // children.push(new paper.Path.Circle({
  383. // center: [pos.x, pos.y],
  384. // radius: ray/8*i,
  385. // strokeColor: '#fff',
  386. // strokeWidth: sw,
  387. // dashArray: da
  388. // }));
  389. // }
  390. // }
  391. // cercle exterieur
  392. let ext_circle_factor = 0.915;
  393. children.push(new paper.Path.Circle({
  394. center: [pos.x, pos.y],
  395. radius: ray*ext_circle_factor,
  396. strokeColor: '#fff',
  397. strokeWidth: 0.25
  398. }));
  399. // cercle interieur
  400. children.push(new paper.Path.Circle({
  401. center: [pos.x, pos.y],
  402. radius: ray*0.51,
  403. strokeColor: '#fff',
  404. strokeWidth: 0.25
  405. }));
  406. // axes
  407. // vertical
  408. children.push(new paper.Path.Line({
  409. from: [pos.x, pos.y - ray*ext_circle_factor],
  410. to: [pos.x, pos.y + ray*ext_circle_factor],
  411. strokeColor: '#fff',
  412. strokeWidth: 0.25
  413. }));
  414. // horizontal
  415. children.push(new paper.Path.Line({
  416. from: [pos.x - ray*ext_circle_factor, pos.y],
  417. to: [pos.x + ray*ext_circle_factor, pos.y],
  418. strokeColor: '#fff',
  419. strokeWidth: 0.25
  420. }))
  421. // fleches
  422. // haute
  423. children.push(new paper.Path({
  424. segments: [
  425. [pos.x - 8, pos.y - ray*ext_circle_factor + 8],
  426. [pos.x, pos.y - ray*ext_circle_factor],
  427. [pos.x + 8, pos.y - ray*ext_circle_factor + 8],
  428. ],
  429. strokeWidth: 0.25,
  430. strokeColor: '#fff',
  431. }));
  432. // milieu
  433. children.push(new paper.Path({
  434. segments: [
  435. [pos.x - 8, pos.y + 8],
  436. [pos.x, pos.y],
  437. [pos.x + 8, pos.y + 8],
  438. ],
  439. strokeWidth: 0.25,
  440. strokeColor: '#fff',
  441. }));
  442. // MOINS - PLUS
  443. // PLUS
  444. // horizontal
  445. children.push(new paper.Path.Line({
  446. from: [pos.x + ray - 5, pos.y - ray],
  447. to: [pos.x + ray + 5, pos.y - ray],
  448. strokeWidth: 2,
  449. strokeColor: '#fff',
  450. }))
  451. // vertical
  452. children.push(new paper.Path.Line({
  453. from: [pos.x + ray, pos.y - ray - 5],
  454. to: [pos.x + ray, pos.y - ray + 5],
  455. strokeWidth: 2,
  456. strokeColor: '#fff',
  457. }))
  458. // MOINS
  459. // horizontal
  460. children.push(new paper.Path.Line({
  461. from: [pos.x - ray - 5, pos.y - ray],
  462. to: [pos.x - ray + 5, pos.y - ray],
  463. strokeWidth: 2,
  464. strokeColor: '#fff',
  465. }))
  466. let fontsize = 4;
  467. let fontFamily = "public_sans";
  468. children.push(new paper.PointText({
  469. point: [pos.x + 4.5, pos.y - ray - 5],
  470. content: `entités qui menacent \u2194 entités qui maintiennent`,
  471. fontSize: fontsize,
  472. fontFamily: fontFamily,
  473. justification: 'center',
  474. fillColor: '#000',
  475. }))
  476. children.push(new paper.PointText({
  477. point: [pos.x - ray - 5, pos.y + 1],
  478. content: "axe d'intensité",
  479. fontSize: fontsize,
  480. fontFamily: fontFamily,
  481. justification: 'right',
  482. fillColor: '#000',
  483. }))
  484. children.push(new paper.PointText({
  485. point: [pos.x + ray + 5, pos.y - 3],
  486. content: "situation future\n\u2195\nsituation actuelle",
  487. fontSize: fontsize,
  488. fontFamily: fontFamily,
  489. justification: 'left',
  490. fillColor: '#000',
  491. }))
  492. let t1 = new paper.PointText({
  493. point: [pos.x - ray/8*2.3, pos.y - ray/8*2.3],
  494. content: "avec prise",
  495. fontSize: fontsize,
  496. fontFamily: fontFamily,
  497. justification: 'center',
  498. fillColor: '#000',
  499. })
  500. t1.rotate(-45)
  501. children.push(t1)
  502. let t2 = new paper.PointText({
  503. point: [pos.x - ray/8*2.95, pos.y - ray/8*2.95],
  504. content: "sans prise",
  505. fontSize: fontsize,
  506. fontFamily: fontFamily,
  507. justification: 'center',
  508. fillColor: '#000',
  509. })
  510. t2.rotate(-45)
  511. children.push(t2)
  512. return new paper.Group({
  513. children: children,
  514. pivot: new paper.Point(pos),
  515. name: 'boussole_bg',
  516. // locked: true,
  517. });
  518. },
  519. setPaperPuissanceagirBGSymbol(){
  520. let children = [];
  521. let ray = this.map_item_ray;
  522. let pos = {x:0,y:0};
  523. // cercles interieur
  524. for (let i = 1; i < 6; i++) {
  525. children.push(new paper.Path.Circle({
  526. center: [pos.x, pos.y],
  527. radius: (ray/5)*i,
  528. strokeWidth: 0.25
  529. }));
  530. }
  531. // rayons
  532. for (let j = 0; j < 16; j++) {
  533. let a = (360 / 16) * j;
  534. let ext_x = Math.cos(a*(Math.PI/180)) * ray;
  535. let ext_y = Math.sin(a*(Math.PI/180)) * ray;
  536. let int_x = Math.cos(a*(Math.PI/180)) * 2;
  537. let int_y = Math.sin(a*(Math.PI/180)) * 2;
  538. children.push(new paper.Path.Line({
  539. from: [pos.x + ext_x, pos.y + ext_y],
  540. to: [pos.x + int_x, pos.y + int_y],
  541. strokeWidth: 0.25,
  542. dashArray: [0.5,1]
  543. }))
  544. }
  545. // cercle exterieur
  546. children.push(new paper.Path.Circle({
  547. center: [pos.x, pos.y],
  548. radius: ray,
  549. strokeWidth: 0.5,
  550. fillColor: `rgba(255,255,255,0.6)`
  551. }));
  552. return new paper.Group({
  553. children: children,
  554. pivot: new paper.Point(pos),
  555. name: 'puissanceagir_bg',
  556. // locked: true,
  557. style: {
  558. strokeColor: '#fff'
  559. }
  560. });
  561. },
  562. // setPaperPuissanceagirICONSymbol(){
  563. // let children = [];
  564. // let svgIcon = paper.project.importSVG(iconPuissanceagir);
  565. // children.push(svgIcon);
  566. // svgIcon.position = this.pos;
  567. // return new paper.Group({
  568. // children: children,
  569. // pivot: new paper.Point(this.pos),
  570. // name: 'puissanceagir_icon',
  571. // locked: true,
  572. // style: {
  573. // strokeColor: '#000',
  574. // strokeWidth: 0.75,
  575. // fillColor: null
  576. // }
  577. // });
  578. // },
  579. setPaperDoleanceBGSymbol(){
  580. let ray = this.map_item_ray;
  581. let pos = {x:0,y:0};
  582. var r = ray * 0.8; // ray
  583. var dr = r/2; // demi ray
  584. var pcr = 3; // petits cercle rayon
  585. // https://fr.wikipedia.org/wiki/Trigonom%C3%A9trie#/media/Fichier:Unit_circle_angles_color.svg
  586. // https://fr.wikipedia.org/wiki/Identit%C3%A9_trigonom%C3%A9trique_pythagoricienne#Preuve_utilisant_le_cercle_unit%C3%A9
  587. // radians = degrees * (pi/180)
  588. // degrees = radians * (180/pi)
  589. // Points for 45° axes
  590. let m = Math.sin(45*(Math.PI/180)) * r; // x = y for rayon
  591. let n = Math.sin(45*(Math.PI/180)) * r/2; // x = y for demi rayon
  592. // console.log('m', m);
  593. // points for legende arcs
  594. var lar = r*1.1; // legendes arcs rayon
  595. let o = Math.cos(22.5*(Math.PI/180)) * lar; // x @ 22.5° for legende arc rayon
  596. let p = Math.sin(22.5*(Math.PI/180)) * lar; // y @ 22.5° for legende arc rayon
  597. let q = Math.sin(45*(Math.PI/180)) * lar; // x = y @ 45° for legende arc rayon
  598. var ltr = lar + 4; // legendes texts rayon
  599. let o_t = Math.cos(22.5*(Math.PI/180)) * ltr; // x @ 22.5° for legende text rayon
  600. let p_t = Math.sin(22.5*(Math.PI/180)) * ltr; // y @ 22.5° for legende text rayon
  601. let q_t = Math.sin(45*(Math.PI/180)) * ltr; // x = y @ 45° for legende text rayon
  602. let style = {strokeColor: '#fff', strokeWidth: 0.25}
  603. let felchesstyle = {strokeColor: '#fff', strokeWidth: 0.5}
  604. let legende_style = {strokeColor: '#000', strokeWidth: 0.25}
  605. let fontsize = 3;
  606. let fontFamily = "public_sans";
  607. let children = [
  608. // big global exterior circle to keep center aligned
  609. new paper.Path.Circle({
  610. center: [0, 0],
  611. radius: r*3,
  612. style: {
  613. strokeColor: 'rgba(255,255,255,0)',
  614. strokeWidth: 0.5
  615. }
  616. }),
  617. //
  618. // ARCS EXTERIEURS
  619. // haut gauche
  620. new paper.Path.Arc({
  621. from: [- r, -pcr],
  622. through: [- m, -m],
  623. to: [ -pcr, -r],
  624. style: style
  625. }),
  626. // haut droite
  627. new paper.Path.Arc({
  628. from: [pcr, -r],
  629. through: [m, -m],
  630. to: [r, -pcr],
  631. style: style
  632. }),
  633. // bas droite
  634. new paper.Path.Arc({
  635. from: [r, pcr],
  636. through: [m, m],
  637. to: [pcr, r],
  638. style: style
  639. }),
  640. // bas gauche
  641. new paper.Path.Arc({
  642. from: [-pcr, r],
  643. through: [-m, m],
  644. to: [-r, pcr],
  645. style: style
  646. }),
  647. //
  648. // cercle interieur
  649. new paper.Path.Circle({
  650. center: [0, 0],
  651. radius: dr,
  652. style: style
  653. }),
  654. //
  655. // petit cercles
  656. new paper.Path.Circle({
  657. center: [0, -r],
  658. radius: pcr,
  659. style: style
  660. }),
  661. new paper.Path.Circle({
  662. center: [0, r],
  663. radius: pcr,
  664. style: {...style, ...{fillColor: 'rgba(255,255,255,0.9)'}},
  665. }),
  666. new paper.Path.Circle({
  667. center: [r, 0],
  668. radius: pcr,
  669. style: style
  670. }),
  671. new paper.Path.Circle({
  672. center: [-r, 0],
  673. radius: pcr,
  674. style: style
  675. }),
  676. //
  677. // AXES
  678. // vertical haut
  679. new paper.Path.Line({
  680. from: [0, -r + pcr],
  681. to: [0, -dr],
  682. style: style
  683. }),
  684. // vertical bas
  685. new paper.Path.Line({
  686. from: [0, r - pcr],
  687. to: [0, dr],
  688. style: style
  689. }),
  690. // horizontal gauche
  691. new paper.Path.Line({
  692. from: [-r + pcr, 0],
  693. to: [-dr, 0],
  694. style: style
  695. }),
  696. // horizontal droite
  697. new paper.Path.Line({
  698. from: [r - pcr, 0],
  699. to: [dr, 0],
  700. style: style
  701. }),
  702. //
  703. // DIAGONALES
  704. // bas droite
  705. new paper.Path.Line({
  706. from: [m, m],
  707. to: [n, n],
  708. style: style
  709. }),
  710. // bas gauche
  711. new paper.Path.Line({
  712. from: [-m, m],
  713. to: [-n, n],
  714. style: style
  715. }),
  716. // fleches
  717. // haut
  718. new paper.Path({
  719. segments: [
  720. [-4, -dr*1.5 - 4],
  721. [0, -dr*1.5],
  722. [-4, -dr*1.5 + 4]
  723. ],
  724. style: felchesstyle
  725. }),
  726. // bas
  727. new paper.Path({
  728. segments: [
  729. [4, dr*1.5 - 4],
  730. [0, dr*1.5],
  731. [4, dr*1.5 + 4]
  732. ],
  733. style: felchesstyle
  734. }),
  735. // gauche
  736. new paper.Path({
  737. segments: [
  738. [-dr*1.5 - 4, 4],
  739. [-dr*1.5, 0],
  740. [-dr*1.5 + 4, 4]
  741. ],
  742. style: felchesstyle
  743. }),
  744. // droite
  745. new paper.Path({
  746. segments: [
  747. [dr*1.5 - 4, -4],
  748. [dr*1.5, 0],
  749. [dr*1.5 + 4, -4]
  750. ],
  751. style: felchesstyle
  752. }),
  753. //
  754. // LEGENDES
  755. //
  756. // arc bas gauche 1
  757. new paper.Path.Arc({
  758. from: [-pcr, lar],
  759. through: [-p, o],
  760. to: [-q + pcr/2, q + pcr/2],
  761. style: legende_style
  762. }),
  763. // tiret
  764. new paper.Path.Line({
  765. from: [-p, o],
  766. to: [-p_t, o_t],
  767. style: legende_style
  768. }),
  769. //text
  770. new paper.PointText({
  771. point: [-p_t - 1, o_t],
  772. content: "2. Enquête menée\nsur le terrain de vie",
  773. fontSize: fontsize,
  774. fontFamily: fontFamily,
  775. justification: 'right'
  776. }),
  777. // arc bas gauche 2
  778. new paper.Path.Arc({
  779. from: [-q - pcr/2, q - pcr/2],
  780. through: [-o, p],
  781. to: [-lar, pcr],
  782. style: legende_style
  783. }),
  784. // tiret
  785. new paper.Path.Line({
  786. from: [-o, p],
  787. to: [-o_t, p_t],
  788. style: legende_style
  789. }),
  790. // texte
  791. new paper.PointText({
  792. point: [-o_t - 1, p_t],
  793. content: "3. Construction de groupes d'intérets\navec qui composer la doléance",
  794. fontSize: fontsize,
  795. fontFamily: fontFamily,
  796. justification: 'right'
  797. }),
  798. // arc haut gauche
  799. new paper.Path.Arc({
  800. from: [-lar, -pcr],
  801. through: [-q, -q],
  802. to: [-pcr, -lar],
  803. style: legende_style
  804. }),
  805. // tiret
  806. new paper.Path.Line({
  807. from: [-q, -q],
  808. to: [-q_t, -q_t],
  809. style: legende_style
  810. }),
  811. // texte
  812. new paper.PointText({
  813. point: [-q_t - 1, -q_t],
  814. content: "5. Réception et traitement\nde la doléance",
  815. fontSize: fontsize,
  816. fontFamily: fontFamily,
  817. justification: 'right'
  818. }),
  819. // arc haut droite
  820. new paper.Path.Arc({
  821. from: [pcr, -lar],
  822. through: [q, -q],
  823. to: [lar, -pcr],
  824. style: legende_style
  825. }),
  826. // tiret
  827. new paper.Path.Line({
  828. from: [q, -q],
  829. to: [q_t, -q_t],
  830. style: legende_style
  831. }),
  832. // texte
  833. new paper.PointText({
  834. point: [q_t + 1, -q_t],
  835. content: "7. Mise-en-œuvre\nde la décision",
  836. fontSize: fontsize,
  837. fontFamily: fontFamily,
  838. justification: 'left'
  839. }),
  840. // arc bas droite 1
  841. new paper.Path.Arc({
  842. from: [lar, pcr],
  843. through: [o, p],
  844. to: [q + pcr/2, q - pcr/2],
  845. style: legende_style
  846. }),
  847. // tiret
  848. new paper.Path.Line({
  849. from: [o, p],
  850. to: [o_t, p_t],
  851. style: legende_style
  852. }),
  853. // texte
  854. new paper.PointText({
  855. point: [o_t + 1, p_t],
  856. content: "9. Réception et application\nde la décision",
  857. fontSize: fontsize,
  858. fontFamily: fontFamily,
  859. justification: 'left'
  860. }),
  861. // arc bas droite 2
  862. new paper.Path.Arc({
  863. from: [q - pcr/2, q + pcr/2],
  864. through: [p, o],
  865. to: [pcr, lar],
  866. style: legende_style
  867. }),
  868. // tiret
  869. new paper.Path.Line({
  870. from: [p, o],
  871. to: [p_t, o_t],
  872. style: legende_style
  873. }),
  874. // texte
  875. new paper.PointText({
  876. point: [p_t + 1, o_t],
  877. content: "10. Réussite / échec / reprise\ndu cercle politique",
  878. fontSize: fontsize,
  879. fontFamily: fontFamily,
  880. justification: 'left'
  881. }),
  882. //
  883. // Points Cardinaux
  884. //
  885. // haut
  886. new paper.Path.Circle({
  887. center: [0, -r],
  888. radius: 0.5,
  889. style: {
  890. fillColor: '#000'
  891. }
  892. }),
  893. new paper.Path.Line({
  894. from: [0, -r],
  895. to: [0, -r - 9],
  896. style: legende_style
  897. }),
  898. new paper.PointText({
  899. point: [0, -r - 11],
  900. content: "6. Décision",
  901. fontSize: fontsize,
  902. fontFamily: fontFamily,
  903. justification: 'center'
  904. }),
  905. // bas
  906. new paper.Path.Circle({
  907. center: [0, r],
  908. radius: 0.5,
  909. style: {
  910. fillColor: '#000'
  911. }
  912. }),
  913. new paper.Path.Line({
  914. from: [0, r],
  915. to: [0, r + 9],
  916. style: legende_style
  917. }),
  918. new paper.PointText({
  919. point: [0, r + 14],
  920. content: "1. Début du cercle\nLe problème\n(injustice, indignation, plainte...)",
  921. fontSize: fontsize,
  922. fontFamily: fontFamily,
  923. justification: 'center'
  924. }),
  925. // droite
  926. new paper.Path.Circle({
  927. center: [r, 0],
  928. radius: 0.5,
  929. style: {
  930. fillColor: '#000'
  931. }
  932. }),
  933. new paper.Path.Line({
  934. from: [r, 0],
  935. to: [r + 8, 0],
  936. style: legende_style
  937. }),
  938. new paper.PointText({
  939. point: [r + 10, -0.5],
  940. content: "8. Adresse de la décision\nà appliquer",
  941. fontSize: fontsize,
  942. fontFamily: fontFamily,
  943. justification: 'left'
  944. }),
  945. // gauche
  946. new paper.Path.Circle({
  947. center: [-r, 0],
  948. radius: 0.5,
  949. style: {
  950. fillColor: '#000'
  951. }
  952. }),
  953. new paper.Path.Line({
  954. from: [-r, 0],
  955. to: [-r - 8, 0],
  956. style: legende_style
  957. }),
  958. new paper.PointText({
  959. point: [-r - 10, 0.4],
  960. content: "4. Adresse de la doléance",
  961. fontSize: fontsize,
  962. fontFamily: fontFamily,
  963. justification: 'right'
  964. }),
  965. ];
  966. return new paper.Group({
  967. children: children,
  968. pivot: new paper.Point(pos),
  969. name: 'doleance_bg',
  970. // locked: true
  971. });
  972. },
  973. // setPaperDoleanceICONSymbol(){
  974. // let children = [];
  975. // let svgIcon = paper.project.importSVG(iconDoleancer);
  976. // children.push(svgIcon);
  977. // svgIcon.position = this.pos;
  978. // return new paper.Group({
  979. // children: children,
  980. // pivot: new paper.Point(this.pos),
  981. // name: 'doleance_icon',
  982. // locked: true,
  983. // style: {
  984. // strokeColor: '#000',
  985. // strokeWidth: 0.75,
  986. // fillColor: null
  987. // }
  988. // });
  989. // },
  990. setPaperEntiteSymbol(){
  991. return new paper.Path.Circle({
  992. pivot: new paper.Point({x:0,y:0}),
  993. center: [0,0],
  994. radius: 0.5, //0.3
  995. fillColor: '#000',
  996. strokeColor: 'rgba(255,255,255,0.05)',
  997. strokeWidth:2
  998. })
  999. },
  1000. setPaperHiddenEntiteSymbol(){
  1001. return new paper.Path.Circle({
  1002. pivot: new paper.Point({x:0,y:0}),
  1003. center: [0,0],
  1004. radius: 0.7, //0.3
  1005. fillColor: '#fff',
  1006. strokeColor: 'rgba(255,255,255,0.05)',
  1007. strokeWidth:2
  1008. })
  1009. },
  1010. setPaperEntiteHoverSymbol(){
  1011. return new paper.Path.Circle({
  1012. pivot: new paper.Point({x:0,y:0}),
  1013. center: [0,0],
  1014. radius: 0.5,
  1015. fillColor: '#01ffe2',
  1016. strokeColor: 'rgba(255,255,255,0.05)',
  1017. strokeWidth:2
  1018. })
  1019. },
  1020. setPaperEntiteActionIconSymbol(){
  1021. // let svgIcon = paper.project.importSVG(iconAction);
  1022. // svgIcon.strokeWidth = 0.8;
  1023. // svgIcon.scale(0.6);
  1024. // svgIcon.strokeColor = '#000';
  1025. // svgIcon.fillColor = null;
  1026. // svgIcon.position = {x:0, y:0};
  1027. let children = [];
  1028. let ray = 2; //this.map_item_ray;
  1029. let pos = {x:0, y:0};
  1030. children.push(new paper.Path.Line({
  1031. from: [- ray, ray],
  1032. to: [ray, - ray],
  1033. strokeColor: '#000',
  1034. strokeWidth: 1.1
  1035. }));
  1036. children.push(new paper.Path.Line({
  1037. from: [ray, ray],
  1038. to: [- ray, - ray],
  1039. strokeColor: '#000',
  1040. strokeWidth: 1.1
  1041. }));
  1042. return new paper.Group({
  1043. children: children,
  1044. name: 'action_icon'
  1045. });
  1046. },
  1047. setPaperEntiteActionSymbol(){
  1048. // let svgIcon = paper.project.importSVG(iconAction);
  1049. // svgIcon.strokeWidth = 0.25;
  1050. // svgIcon.scale(0.15);
  1051. // svgIcon.strokeColor = '#000';
  1052. // svgIcon.fillColor = null;
  1053. // svgIcon.position = {x:0, y:0};
  1054. let children = [];
  1055. let ray = 1; //this.map_item_ray;
  1056. // let pos = {x:0, y:0};
  1057. // children.push(new paper.Path.Line({
  1058. // from: [- ray, ray],
  1059. // to: [ray, - ray],
  1060. // strokeColor: '#000',
  1061. // strokeWidth: strokewidth
  1062. // }));
  1063. // children.push(new paper.Path.Line({
  1064. // from: [ray, ray],
  1065. // to: [- ray, - ray],
  1066. // strokeColor: '#000',
  1067. // strokeWidth: strokewidth
  1068. // }));
  1069. children.push(new paper.Path.Circle({
  1070. radius: ray/2,
  1071. fillColor: 'rgba(0,0,0,1)'
  1072. }))
  1073. children.push(new paper.Path.Circle({
  1074. radius: ray,
  1075. strokeColor: 'rgba(0,0,0,1)',
  1076. strokeWidth: 0.2,
  1077. fillColor: 'rgba(0,0,0,0)'
  1078. }))
  1079. children.push(new paper.Path.Circle({
  1080. radius: ray,
  1081. fillColor: 'rgba(255,255,255,0.01)'
  1082. }))
  1083. return new paper.Group({
  1084. children: children,
  1085. name: 'action_icon'
  1086. });
  1087. },
  1088. setPaperEntiteActionHoverSymbol(){
  1089. // let svgIcon = paper.project.importSVG(iconAction);
  1090. // svgIcon.strokeColor = '#01ffe2';
  1091. // svgIcon.strokeWidth = 0.25;
  1092. // svgIcon.scale(0.15);
  1093. // svgIcon.fillColor = null;
  1094. // svgIcon.position = {x:0, y:0};
  1095. // let circle = new paper.Path.Circle({
  1096. // radius: 3,
  1097. // fillColor: 'rgba(255,255,255,0.05)'
  1098. // })
  1099. // return new paper.Group({
  1100. // children: [circle, svgIcon],
  1101. // name: 'action_icon'
  1102. // });
  1103. let children = [];
  1104. let ray = 0.7; //this.map_item_ray;
  1105. // let pos = {x:0, y:0};
  1106. // let strokewidth = 0.4;
  1107. // children.push(new paper.Path.Line({
  1108. // from: [- ray, ray],
  1109. // to: [ray, - ray],
  1110. // strokeColor: '#01ffe2',
  1111. // strokeWidth: strokewidth
  1112. // }));
  1113. // children.push(new paper.Path.Line({
  1114. // from: [ray, ray],
  1115. // to: [- ray, - ray],
  1116. // strokeColor: '#01ffe2',
  1117. // strokeWidth: strokewidth
  1118. // }));
  1119. children.push(new paper.Path.Circle({
  1120. radius: ray/2,
  1121. fillColor: '#01ffe2'
  1122. }))
  1123. children.push(new paper.Path.Circle({
  1124. radius: ray,
  1125. strokeColor: '#01ffe2',
  1126. strokeWidth: 0.2,
  1127. fillColor: 'rgba(0,0,0,0)'
  1128. }))
  1129. children.push(new paper.Path.Circle({
  1130. radius: ray,
  1131. fillColor: 'rgba(255,255,255,0.01)'
  1132. }))
  1133. return new paper.Group({
  1134. children: children,
  1135. name: 'action_icon'
  1136. });
  1137. },
  1138. setPaperBesoinSymbol(){
  1139. return new paper.Path({
  1140. pivot: new paper.Point(this.pos),
  1141. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  1142. fillColor: '#000'
  1143. })
  1144. },
  1145. setPaperBesoinHoverSymbol(){
  1146. return new paper.Path({
  1147. pivot: new paper.Point(this.pos),
  1148. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  1149. fillColor: '#01ffe2'
  1150. })
  1151. },
  1152. setPaperReponseSymbol(){
  1153. return new paper.Path({
  1154. pivot: new paper.Point(this.pos),
  1155. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  1156. fillColor: '#eee',
  1157. strokeColor: "#000",
  1158. strokeWidth: 0.25,
  1159. })
  1160. },
  1161. setPaperReponseHoverSymbol(){
  1162. return new paper.Path({
  1163. pivot: new paper.Point(this.pos),
  1164. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  1165. fillColor: '#eee',
  1166. strokeColor: "#01ffe2",
  1167. strokeWidth: 0.25,
  1168. })
  1169. },
  1170. async setSuperpositionsMatterConstraints(){
  1171. await nextTick(); // wait for dom to be upadted before applying constraint
  1172. console.log('setSuperpositionsMatterConstraints this.allSuperpositions_clustered', this.allSuperpositions_clustered);
  1173. // loop through all supperposition couple
  1174. for(let [cluster_index, cluster] of Object.entries(this.allSuperpositions_clustered)){
  1175. for(let [i, cid_eid_A] of cluster.entries()){
  1176. // console.log(`i:${i}, cid_eid_A cid:${cid_eid_A.cid}, eid:${cid_eid_A.eid}`);
  1177. let cid_eid_B = i === cluster.length -1 ? cluster[0] : cluster[i+1];
  1178. // console.log(`i:${i}, cid_eid_B cid:${cid_eid_B.cid}, eid:${cid_eid_B.eid}`);
  1179. let concernementA = this.concernementsByID[cid_eid_A.cid];
  1180. // console.log('concernementA', concernementA);
  1181. let concernementB = this.concernementsByID[cid_eid_B.cid];
  1182. // console.log('concernementB', concernementB);
  1183. // console.log('superposition', superposition_id, superposition);
  1184. let mapitemA_id = `${cid_eid_A.cid}___${cluster_index}`
  1185. let mapitemB_id = `${cid_eid_B.cid}___${cluster_index}`
  1186. // console.log(`mapitemA_id: ${mapitemA_id}, mapitemB_id: ${mapitemB_id}`);
  1187. let mapitemA = this.allMapItems_byid[mapitemA_id];
  1188. let mapitemB = this.allMapItems_byid[mapitemB_id];
  1189. console.log('mapitemA', mapitemA);
  1190. console.log('mapitemB', mapitemB);
  1191. // get the concernement matter bodies with id
  1192. let bodyA = Matter.Composite.get(this.world, mapitemA_id, 'body'); // matter body id is the same as mapitem_id
  1193. let bodyB = Matter.Composite.get(this.world, mapitemB_id, 'body'); // matter body id is the same as mapitem_id
  1194. // console.log('bodyA, bodyB', bodyA, bodyB);
  1195. // get the entite coordinates inside the concernement body
  1196. let pointA = null;
  1197. for(let entiteA of concernementA.revisions_byid[concernementA.active_revision].entites){
  1198. if (entiteA.entite && entiteA.entite.id === cid_eid_A.eid && entiteA.display) {
  1199. // console.log('entiteA', entiteA);
  1200. let scale = mapitemA.scale;
  1201. console.log(`mapitemA.scale ${concernementA.id}`, scale);
  1202. pointA = Matter.Vector.create(entiteA.display.pos.x * scale, entiteA.display.pos.y * scale);
  1203. break;
  1204. }
  1205. }
  1206. let pointB = null;
  1207. for(let entiteB of concernementB.revisions_byid[concernementB.active_revision].entites){
  1208. if (entiteB.entite && entiteB.entite.id === cid_eid_B.eid && entiteB.display) {
  1209. // console.log('entiteB', entiteB);
  1210. let scale = mapitemB.scale;
  1211. console.log(`mapitemB.scale ${concernementB.id}`, scale);
  1212. pointB = Matter.Vector.create(entiteB.display.pos.x * scale, entiteB.display.pos.y * scale);
  1213. break;
  1214. }
  1215. }
  1216. // console.log(`pointA:`, pointA,` pointB:`, pointB);
  1217. if (bodyA && bodyB && pointA && pointB) {
  1218. let c = Matter.Constraint.create({
  1219. bodyA: bodyA,
  1220. pointA: pointA,
  1221. bodyB: bodyB,
  1222. pointB: pointB,
  1223. stiffness: 1,
  1224. length: 0,
  1225. damping: 1,
  1226. concernementA: concernementA,
  1227. concernementB: concernementB
  1228. });
  1229. this.superpositions_constraints.push(c);
  1230. Matter.Composite.add(this.world, c);
  1231. // keep a link the constraint into the concernement object (useful for tweening the constraint pointA & pointB in concernementMapItem)
  1232. if(!concernementA.superposition_constraints_id[mapitemA_id]){
  1233. concernementA.superposition_constraints_id[mapitemA_id] = [];
  1234. }
  1235. concernementA.superposition_constraints_id[mapitemA_id].push(c.id);
  1236. if(!concernementB.superposition_constraints_id[mapitemB_id]){
  1237. concernementB.superposition_constraints_id[mapitemB_id] = [];
  1238. }
  1239. concernementB.superposition_constraints_id[mapitemB_id].push(c.id);
  1240. // record all superposed concernements for each concernement
  1241. if (concernementA.all_superposed_concernements_id.indexOf(concernementB.id) < 0) {
  1242. concernementA.all_superposed_concernements_id.push(concernementB.id);
  1243. }
  1244. if (concernementB.all_superposed_concernements_id.indexOf(concernementA.id) < 0) {
  1245. concernementB.all_superposed_concernements_id.push(concernementA.id);
  1246. }
  1247. // record all superposed concernements for each concernement by mapitem_id
  1248. // A
  1249. if (!concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id]) {
  1250. concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id] = []
  1251. }
  1252. if (concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id].indexOf(mapitemB_id) < 0) {
  1253. concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id].push(mapitemB_id);
  1254. }
  1255. // B
  1256. if (!concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id]) {
  1257. concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id] = []
  1258. }
  1259. if (concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id].indexOf(mapitemA_id) < 0) {
  1260. concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id].push(mapitemA_id);
  1261. }
  1262. }
  1263. }
  1264. }
  1265. },
  1266. clearSuperpositionsMatterConstraints(){
  1267. console.log('clearSuperpositionsMatterConstraints', this.superpositions_constraints);
  1268. for(let constraint of this.superpositions_constraints){
  1269. // Delete superposition constraints ids recorded in concernement object
  1270. ['A', 'B'].forEach(ab => {
  1271. for( let [mapitem_id, constraint_ids] of Object.entries(constraint[`concernement${ab}`].superposition_constraints_id)){
  1272. let indexes = Object.keys(constraint_ids);
  1273. indexes.forEach(i => {
  1274. if(constraint_ids[i] === constraint.id) {
  1275. delete constraint[`concernement${ab}`].superposition_constraints_id[mapitem_id][i];
  1276. }
  1277. })
  1278. }
  1279. });
  1280. Matter.Composite.remove(this.world, constraint, true);
  1281. }
  1282. this.superpositions_constraints = [];
  1283. },
  1284. // resetSuperpositionsMatterConstraints(){
  1285. // this.clearSuperpositionsMatterConstraints();
  1286. // this.setSuperpositionsMatterConstraints();
  1287. // },
  1288. onBeforeEngineUpdate(){
  1289. },
  1290. onAfterEngineUpdate(){
  1291. // // START OF DEBUGGING
  1292. // this.debugDrawConstraints()
  1293. // this.debugDrawWalls()
  1294. // // END OF DEBUGGING
  1295. },
  1296. debugDrawConstraints(){
  1297. // draw lines of constraints for debuging
  1298. let constraints_lines = this.paper.project.getItem({name: 'constraints_lines', class: paper.Group});
  1299. if (constraints_lines) {
  1300. constraints_lines.removeChildren();
  1301. }else{
  1302. constraints_lines = new paper.Group({
  1303. pivot: new paper.Point({x:0,y:0}),
  1304. name: 'constraints_lines',
  1305. });
  1306. }
  1307. let all_constrains = Matter.Composite.allConstraints(this.world);
  1308. let children = [];
  1309. for(let constraint of all_constrains){
  1310. // console.log('constrain', constraint);
  1311. let pointAWorld = Matter.Constraint.pointAWorld(constraint);
  1312. let pointBWorld = Matter.Constraint.pointBWorld(constraint);
  1313. // console.log('pointAWorld, pointBWorld', pointAWorld, pointBWorld);
  1314. children.push(new paper.Path.Line({
  1315. from: [pointAWorld.x, pointAWorld.y],
  1316. to: [pointBWorld.x, pointBWorld.y],
  1317. strokeColor: '#f00',
  1318. strokeWidth: 1
  1319. }));
  1320. }
  1321. constraints_lines.addChildren(children);
  1322. },
  1323. debugDrawWalls(){
  1324. let wall_rects = this.paper.project.getItem({name: 'wall_rects', class: paper.Group});
  1325. if (wall_rects) {
  1326. wall_rects.removeChildren();
  1327. }else{
  1328. wall_rects = new paper.Group({
  1329. pivot: new paper.Point({x:0,y:0}),
  1330. name: 'wall_rects',
  1331. });
  1332. }
  1333. let wallsbody = Matter.Composite.get(this.world, 'walls', 'body');
  1334. if (wallsbody) {
  1335. // console.log('wallsbody', wallsbody.parts);
  1336. let children = [];
  1337. wallsbody.parts.forEach((part, i) => {
  1338. if(i > 0){
  1339. // console.log('part', part.label, part.bounds.min);
  1340. children.push(new paper.Path.Rectangle({
  1341. from: part.bounds.min,
  1342. to: part.bounds.max,
  1343. strokeColor: '#00f',
  1344. strokeWidth: 2
  1345. }));
  1346. }
  1347. });
  1348. wall_rects.addChildren(children);
  1349. }
  1350. }
  1351. },
  1352. beforeUpdate () {
  1353. },
  1354. components: {
  1355. MapBackground,
  1356. ConcernementMapPopup,
  1357. RecitPlayer
  1358. }
  1359. }
  1360. </script>
  1361. <template>
  1362. <div id="map-backgrounds">
  1363. <MapBackground />
  1364. </div>
  1365. <div id="map-matter">
  1366. <canvas ref="canvas-engine"></canvas>
  1367. </div>
  1368. <div id="map-concernements">
  1369. <canvas ref="canvas-map"></canvas>
  1370. <slot></slot>
  1371. </div>
  1372. <nav id="map-nav">
  1373. <ul>
  1374. <li>
  1375. <a
  1376. title="terrain de vie" href="#terraindevie" @click="setMapMode('terraindevie')"
  1377. :class="{active: map_mode === 'terraindevie'}"
  1378. >
  1379. <span class="icon terraindevie"/> <span class="label"> terrain de vie</span>
  1380. </a>
  1381. </li>
  1382. <li>
  1383. <a
  1384. title="proximite" href="#proximite" @click="setMapMode('proximite')"
  1385. :class="{ disabled: opened_concernement && !opened_concernement.has_proximites, active: map_mode === 'proximite'}"
  1386. >
  1387. <span class="icon proximite"/> <span class="label"> proximité</span>
  1388. </a>
  1389. </li>
  1390. <li>
  1391. <a
  1392. title="superposition" href="#superposition" @click="setMapMode('superposition')"
  1393. :class="{ disabled: opened_concernement && !opened_concernement.has_superpositions, active: map_mode === 'superposition'}"
  1394. >
  1395. <span class="icon superposition"/> <span class="label"> superposition</span>
  1396. </a>
  1397. </li>
  1398. <li>
  1399. <a
  1400. title="puissance d'agir" href="#puissancedagir" @click="setMapMode('puissancedagir')"
  1401. :class="{ disabled: opened_concernement && !opened_concernement.has_puissancedagir, active: map_mode === 'puissancedagir'}"
  1402. >
  1403. <span class="icon puissancedagir"/> <span class="label"> puissance d'agir</span>
  1404. </a>
  1405. </li>
  1406. <li>
  1407. <a
  1408. title="action" href="#action" @click="setMapMode('action')"
  1409. :class="{ disabled: opened_concernement && !opened_concernement.has_agissantes, active: map_mode === 'action'}"
  1410. >
  1411. <span class="icon action"/> <span class="label"> action</span>
  1412. </a>
  1413. </li>
  1414. <li>
  1415. <a
  1416. title="cercle politique" href="#doleancer" @click="setMapMode('doleancer')"
  1417. :class="{ disabled: opened_concernement && !opened_concernement.has_doleance, active: map_mode === 'doleancer'}"
  1418. >
  1419. <span class="icon doleancer"/> <span class="label"> cercle politique</span>
  1420. </a>
  1421. </li>
  1422. </ul>
  1423. </nav>
  1424. <RecitPlayer />
  1425. <ConcernementMapPopup
  1426. v-if="hover_elmt && hover_elmt.type !== 'doleance_step' && !hover_elmt.no_popup"
  1427. :infos="hover_elmt"
  1428. />
  1429. </template>
  1430. <style lang="css" scoped>
  1431. </style>