MapConcernements.vue 50 KB

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