1
0

MapConcernements.vue 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634
  1. <script>
  2. // import { mapActions, mapState } from 'pinia'
  3. import { computed } from 'vue'
  4. import { nextTick } from 'vue'
  5. import MapGradientBackground from '@components/MapGradientBackground.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_hover', this.setPaperEntiteHoverSymbol());
  374. this.addPaperSymbolDefinition('entite_inactive', this.setPaperInactiveEntiteSymbol());
  375. this.addPaperSymbolDefinition('entite_inactive_hover', this.setPaperInactiveEntiteHoverSymbol());
  376. this.addPaperSymbolDefinition('entite_hidden', this.setPaperHiddenEntiteSymbol());
  377. this.addPaperSymbolDefinition('entite_action_icon', this.setPaperEntiteActionIconSymbol());
  378. this.addPaperSymbolDefinition('entite_action', this.setPaperEntiteActionSymbol());
  379. this.addPaperSymbolDefinition('entite_action_hover', this.setPaperEntiteActionHoverSymbol());
  380. this.addPaperSymbolDefinition('besoin', this.setPaperBesoinSymbol());
  381. this.addPaperSymbolDefinition('besoin_hover', this.setPaperBesoinHoverSymbol());
  382. this.addPaperSymbolDefinition('reponse', this.setPaperReponseSymbol());
  383. this.addPaperSymbolDefinition('reponse_hover', this.setPaperReponseHoverSymbol());
  384. }
  385. },
  386. setPaperBoussoleBGSymbol(){
  387. // BOUSSOLE
  388. let children = [];
  389. let ray = this.map_item_ray;
  390. let pos = {x:0, y:0};
  391. // big invisible global exterior circle to keep center aligned
  392. children.push(new paper.Path.Circle({
  393. center: [0, 0],
  394. radius: ray*3,
  395. style: {
  396. strokeColor: 'rgba(255,255,255,0)',
  397. strokeWidth: 0.5
  398. }
  399. }));
  400. // cercles
  401. // for (let i = 1; i < 9; i++) {
  402. // let sw = i === 4 || i === 8 ? 0.25 : 0.1; // width
  403. // let da = i === 4 || i === 8 ? null : [5,5]; // dash array
  404. // if (!da) { // draw only 2 main non-dashed circles
  405. // children.push(new paper.Path.Circle({
  406. // center: [pos.x, pos.y],
  407. // radius: ray/8*i,
  408. // strokeColor: '#fff',
  409. // strokeWidth: sw,
  410. // dashArray: da
  411. // }));
  412. // }
  413. // }
  414. // cercle exterieur
  415. let ext_circle_factor = 0.915; // be eware that concernement map item also use this factor
  416. children.push(new paper.Path.Circle({
  417. center: [pos.x, pos.y],
  418. radius: ray*ext_circle_factor,
  419. strokeColor: '#fff',
  420. strokeWidth: 0.25
  421. }));
  422. // cercle interieur
  423. children.push(new paper.Path.Circle({
  424. center: [pos.x, pos.y],
  425. radius: ray*0.51,
  426. strokeColor: '#fff',
  427. strokeWidth: 0.25
  428. }));
  429. // axes
  430. // vertical
  431. children.push(new paper.Path.Line({
  432. from: [pos.x, pos.y - ray*ext_circle_factor],
  433. to: [pos.x, pos.y + ray*ext_circle_factor],
  434. strokeColor: '#fff',
  435. strokeWidth: 0.25
  436. }));
  437. // horizontal
  438. children.push(new paper.Path.Line({
  439. from: [pos.x - ray*ext_circle_factor, pos.y],
  440. to: [pos.x + ray*ext_circle_factor, pos.y],
  441. strokeColor: '#fff',
  442. strokeWidth: 0.25
  443. }))
  444. // fleches
  445. // haute
  446. children.push(new paper.Path({
  447. segments: [
  448. [pos.x - 8, pos.y - ray*ext_circle_factor + 8],
  449. [pos.x, pos.y - ray*ext_circle_factor],
  450. [pos.x + 8, pos.y - ray*ext_circle_factor + 8],
  451. ],
  452. strokeWidth: 0.25,
  453. strokeColor: '#fff',
  454. }));
  455. // milieu
  456. children.push(new paper.Path({
  457. segments: [
  458. [pos.x - 8, pos.y + 8],
  459. [pos.x, pos.y],
  460. [pos.x + 8, pos.y + 8],
  461. ],
  462. strokeWidth: 0.25,
  463. strokeColor: '#fff',
  464. }));
  465. // MOINS - PLUS
  466. // PLUS
  467. // horizontal
  468. children.push(new paper.Path.Line({
  469. from: [pos.x + ray - 5, pos.y - ray],
  470. to: [pos.x + ray + 5, pos.y - ray],
  471. strokeWidth: 2,
  472. strokeColor: '#fff',
  473. }))
  474. // vertical
  475. children.push(new paper.Path.Line({
  476. from: [pos.x + ray, pos.y - ray - 5],
  477. to: [pos.x + ray, pos.y - ray + 5],
  478. strokeWidth: 2,
  479. strokeColor: '#fff',
  480. }))
  481. // MOINS
  482. // horizontal
  483. children.push(new paper.Path.Line({
  484. from: [pos.x - ray - 5, pos.y - ray],
  485. to: [pos.x - ray + 5, pos.y - ray],
  486. strokeWidth: 2,
  487. strokeColor: '#fff',
  488. }))
  489. let fontsize = 3;
  490. let fontFamily = "public_sans";
  491. children.push(new paper.PointText({
  492. point: [pos.x + 4.5, pos.y - ray],
  493. content: `entités qui menacent \u2194 entités qui maintiennent`,
  494. fontSize: fontsize,
  495. fontFamily: fontFamily,
  496. justification: 'center',
  497. fillColor: '#000',
  498. }))
  499. children.push(new paper.PointText({
  500. point: [pos.x - ray, pos.y + 1],
  501. content: "axe d'intensité",
  502. fontSize: fontsize,
  503. fontFamily: fontFamily,
  504. justification: 'right',
  505. fillColor: '#000',
  506. }))
  507. children.push(new paper.PointText({
  508. point: [pos.x + ray, pos.y - 3],
  509. content: "situation future\n\u2195\nsituation actuelle",
  510. fontSize: fontsize,
  511. fontFamily: fontFamily,
  512. justification: 'left',
  513. fillColor: '#000',
  514. }))
  515. let t1 = new paper.PointText({
  516. point: [pos.x - ray/8*2.54, pos.y - ray/8*2.54],
  517. content: "avec prise",
  518. fontSize: fontsize,
  519. fontFamily: fontFamily,
  520. justification: 'center',
  521. fillColor: '#000',
  522. })
  523. t1.rotate(-45)
  524. children.push(t1)
  525. let t2 = new paper.PointText({
  526. point: [pos.x - ray/8*3.1, pos.y - ray/8*3.1],
  527. content: "sans prise",
  528. fontSize: fontsize,
  529. fontFamily: fontFamily,
  530. justification: 'center',
  531. fillColor: '#000',
  532. })
  533. t2.rotate(-45)
  534. children.push(t2)
  535. return new paper.Group({
  536. children: children,
  537. pivot: new paper.Point(pos),
  538. name: 'boussole_bg',
  539. // locked: true,
  540. });
  541. },
  542. setPaperPuissanceagirBGSymbol(){
  543. let children = [];
  544. let ray = this.map_item_ray;
  545. let pos = {x:0,y:0};
  546. // cercles interieur
  547. for (let i = 1; i < 6; i++) {
  548. children.push(new paper.Path.Circle({
  549. center: [pos.x, pos.y],
  550. radius: (ray/5)*i,
  551. strokeWidth: 0.25
  552. }));
  553. }
  554. // rayons
  555. for (let j = 0; j < 16; j++) {
  556. let a = (360 / 16) * j;
  557. let ext_x = Math.cos(a*(Math.PI/180)) * ray;
  558. let ext_y = Math.sin(a*(Math.PI/180)) * ray;
  559. let int_x = Math.cos(a*(Math.PI/180)) * 2;
  560. let int_y = Math.sin(a*(Math.PI/180)) * 2;
  561. children.push(new paper.Path.Line({
  562. from: [pos.x + ext_x, pos.y + ext_y],
  563. to: [pos.x + int_x, pos.y + int_y],
  564. strokeWidth: 0.25,
  565. dashArray: [0.5,1]
  566. }))
  567. }
  568. // cercle exterieur
  569. children.push(new paper.Path.Circle({
  570. center: [pos.x, pos.y],
  571. radius: ray,
  572. strokeWidth: 0.5,
  573. fillColor: `rgba(255,255,255,0.6)`
  574. }));
  575. return new paper.Group({
  576. children: children,
  577. pivot: new paper.Point(pos),
  578. name: 'puissanceagir_bg',
  579. // locked: true,
  580. style: {
  581. strokeColor: '#fff'
  582. }
  583. });
  584. },
  585. // setPaperPuissanceagirICONSymbol(){
  586. // let children = [];
  587. // let svgIcon = paper.project.importSVG(iconPuissanceagir);
  588. // children.push(svgIcon);
  589. // svgIcon.position = this.pos;
  590. // return new paper.Group({
  591. // children: children,
  592. // pivot: new paper.Point(this.pos),
  593. // name: 'puissanceagir_icon',
  594. // locked: true,
  595. // style: {
  596. // strokeColor: '#000',
  597. // strokeWidth: 0.75,
  598. // fillColor: null
  599. // }
  600. // });
  601. // },
  602. setPaperDoleanceBGSymbol(){
  603. let ray = this.map_item_ray;
  604. let pos = {x:0,y:0};
  605. var r = ray * 0.8; // ray
  606. var dr = r/2; // demi ray
  607. var pcr = 3; // petits cercle rayon
  608. // https://fr.wikipedia.org/wiki/Trigonom%C3%A9trie#/media/Fichier:Unit_circle_angles_color.svg
  609. // https://fr.wikipedia.org/wiki/Identit%C3%A9_trigonom%C3%A9trique_pythagoricienne#Preuve_utilisant_le_cercle_unit%C3%A9
  610. // radians = degrees * (pi/180)
  611. // degrees = radians * (180/pi)
  612. // Points for 45° axes
  613. let m = Math.sin(45*(Math.PI/180)) * r; // x = y for rayon
  614. let n = Math.sin(45*(Math.PI/180)) * r/2; // x = y for demi rayon
  615. // console.log('m', m);
  616. // points for legende arcs
  617. var lar = r*1.1; // legendes arcs rayon
  618. let o = Math.cos(22.5*(Math.PI/180)) * lar; // x @ 22.5° for legende arc rayon
  619. let p = Math.sin(22.5*(Math.PI/180)) * lar; // y @ 22.5° for legende arc rayon
  620. let q = Math.sin(45*(Math.PI/180)) * lar; // x = y @ 45° for legende arc rayon
  621. var ltr = lar + 4; // legendes texts rayon
  622. let o_t = Math.cos(22.5*(Math.PI/180)) * ltr; // x @ 22.5° for legende text rayon
  623. let p_t = Math.sin(22.5*(Math.PI/180)) * ltr; // y @ 22.5° for legende text rayon
  624. let q_t = Math.sin(45*(Math.PI/180)) * ltr; // x = y @ 45° for legende text rayon
  625. let style = {strokeColor: '#fff', strokeWidth: 0.25}
  626. let felchesstyle = {strokeColor: '#fff', strokeWidth: 0.5}
  627. let legende_style = {strokeColor: '#000', strokeWidth: 0.25}
  628. let fontsize = 3;
  629. let fontFamily = "public_sans";
  630. let children = [
  631. // big global exterior circle to keep center aligned
  632. new paper.Path.Circle({
  633. center: [0, 0],
  634. radius: r*3,
  635. style: {
  636. strokeColor: 'rgba(255,255,255,0)',
  637. strokeWidth: 0.5
  638. }
  639. }),
  640. //
  641. // ARCS EXTERIEURS
  642. // haut gauche
  643. new paper.Path.Arc({
  644. from: [- r, -pcr],
  645. through: [- m, -m],
  646. to: [ -pcr, -r],
  647. style: style
  648. }),
  649. // haut droite
  650. new paper.Path.Arc({
  651. from: [pcr, -r],
  652. through: [m, -m],
  653. to: [r, -pcr],
  654. style: style
  655. }),
  656. // bas droite
  657. new paper.Path.Arc({
  658. from: [r, pcr],
  659. through: [m, m],
  660. to: [pcr, r],
  661. style: style
  662. }),
  663. // bas gauche
  664. new paper.Path.Arc({
  665. from: [-pcr, r],
  666. through: [-m, m],
  667. to: [-r, pcr],
  668. style: style
  669. }),
  670. //
  671. // cercle interieur
  672. new paper.Path.Circle({
  673. center: [0, 0],
  674. radius: dr,
  675. style: style
  676. }),
  677. //
  678. // petit cercles
  679. new paper.Path.Circle({
  680. center: [0, -r],
  681. radius: pcr,
  682. style: style
  683. }),
  684. new paper.Path.Circle({
  685. center: [0, r],
  686. radius: pcr,
  687. style: {...style, ...{fillColor: 'rgba(255,255,255,0.9)'}},
  688. }),
  689. new paper.Path.Circle({
  690. center: [r, 0],
  691. radius: pcr,
  692. style: style
  693. }),
  694. new paper.Path.Circle({
  695. center: [-r, 0],
  696. radius: pcr,
  697. style: style
  698. }),
  699. //
  700. // AXES
  701. // vertical haut
  702. new paper.Path.Line({
  703. from: [0, -r + pcr],
  704. to: [0, -dr],
  705. style: style
  706. }),
  707. // vertical bas
  708. new paper.Path.Line({
  709. from: [0, r - pcr],
  710. to: [0, dr],
  711. style: style
  712. }),
  713. // horizontal gauche
  714. new paper.Path.Line({
  715. from: [-r + pcr, 0],
  716. to: [-dr, 0],
  717. style: style
  718. }),
  719. // horizontal droite
  720. new paper.Path.Line({
  721. from: [r - pcr, 0],
  722. to: [dr, 0],
  723. style: style
  724. }),
  725. //
  726. // DIAGONALES
  727. // bas droite
  728. new paper.Path.Line({
  729. from: [m, m],
  730. to: [n, n],
  731. style: style
  732. }),
  733. // bas gauche
  734. new paper.Path.Line({
  735. from: [-m, m],
  736. to: [-n, n],
  737. style: style
  738. }),
  739. // fleches
  740. // haut
  741. new paper.Path({
  742. segments: [
  743. [-4, -dr*1.5 - 4],
  744. [0, -dr*1.5],
  745. [-4, -dr*1.5 + 4]
  746. ],
  747. style: felchesstyle
  748. }),
  749. // bas
  750. new paper.Path({
  751. segments: [
  752. [4, dr*1.5 - 4],
  753. [0, dr*1.5],
  754. [4, dr*1.5 + 4]
  755. ],
  756. style: felchesstyle
  757. }),
  758. // gauche
  759. new paper.Path({
  760. segments: [
  761. [-dr*1.5 - 4, 4],
  762. [-dr*1.5, 0],
  763. [-dr*1.5 + 4, 4]
  764. ],
  765. style: felchesstyle
  766. }),
  767. // droite
  768. new paper.Path({
  769. segments: [
  770. [dr*1.5 - 4, -4],
  771. [dr*1.5, 0],
  772. [dr*1.5 + 4, -4]
  773. ],
  774. style: felchesstyle
  775. }),
  776. //
  777. // LEGENDES
  778. //
  779. // arc bas gauche 1
  780. new paper.Path.Arc({
  781. from: [-pcr, lar],
  782. through: [-p, o],
  783. to: [-q + pcr/2, q + pcr/2],
  784. style: legende_style
  785. }),
  786. // tiret
  787. new paper.Path.Line({
  788. from: [-p, o],
  789. to: [-p_t, o_t],
  790. style: legende_style
  791. }),
  792. //text
  793. new paper.PointText({
  794. point: [-p_t - 1, o_t],
  795. content: "2. Enquête menée\nsur le terrain de vie",
  796. fontSize: fontsize,
  797. fontFamily: fontFamily,
  798. justification: 'right'
  799. }),
  800. // arc bas gauche 2
  801. new paper.Path.Arc({
  802. from: [-q - pcr/2, q - pcr/2],
  803. through: [-o, p],
  804. to: [-lar, pcr],
  805. style: legende_style
  806. }),
  807. // tiret
  808. new paper.Path.Line({
  809. from: [-o, p],
  810. to: [-o_t, p_t],
  811. style: legende_style
  812. }),
  813. // texte
  814. new paper.PointText({
  815. point: [-o_t - 1, p_t],
  816. content: "3. Construction de groupes d'intérets\navec qui composer la doléance",
  817. fontSize: fontsize,
  818. fontFamily: fontFamily,
  819. justification: 'right'
  820. }),
  821. // arc haut gauche
  822. new paper.Path.Arc({
  823. from: [-lar, -pcr],
  824. through: [-q, -q],
  825. to: [-pcr, -lar],
  826. style: legende_style
  827. }),
  828. // tiret
  829. new paper.Path.Line({
  830. from: [-q, -q],
  831. to: [-q_t, -q_t],
  832. style: legende_style
  833. }),
  834. // texte
  835. new paper.PointText({
  836. point: [-q_t - 1, -q_t],
  837. content: "5. Réception et traitement\nde la doléance",
  838. fontSize: fontsize,
  839. fontFamily: fontFamily,
  840. justification: 'right'
  841. }),
  842. // arc haut droite
  843. new paper.Path.Arc({
  844. from: [pcr, -lar],
  845. through: [q, -q],
  846. to: [lar, -pcr],
  847. style: legende_style
  848. }),
  849. // tiret
  850. new paper.Path.Line({
  851. from: [q, -q],
  852. to: [q_t, -q_t],
  853. style: legende_style
  854. }),
  855. // texte
  856. new paper.PointText({
  857. point: [q_t + 1, -q_t],
  858. content: "7. Mise-en-œuvre\nde la décision",
  859. fontSize: fontsize,
  860. fontFamily: fontFamily,
  861. justification: 'left'
  862. }),
  863. // arc bas droite 1
  864. new paper.Path.Arc({
  865. from: [lar, pcr],
  866. through: [o, p],
  867. to: [q + pcr/2, q - pcr/2],
  868. style: legende_style
  869. }),
  870. // tiret
  871. new paper.Path.Line({
  872. from: [o, p],
  873. to: [o_t, p_t],
  874. style: legende_style
  875. }),
  876. // texte
  877. new paper.PointText({
  878. point: [o_t + 1, p_t],
  879. content: "9. Réception et application\nde la décision",
  880. fontSize: fontsize,
  881. fontFamily: fontFamily,
  882. justification: 'left'
  883. }),
  884. // arc bas droite 2
  885. new paper.Path.Arc({
  886. from: [q - pcr/2, q + pcr/2],
  887. through: [p, o],
  888. to: [pcr, lar],
  889. style: legende_style
  890. }),
  891. // tiret
  892. new paper.Path.Line({
  893. from: [p, o],
  894. to: [p_t, o_t],
  895. style: legende_style
  896. }),
  897. // texte
  898. new paper.PointText({
  899. point: [p_t + 1, o_t],
  900. content: "10. Réussite / échec / reprise\ndu cercle politique",
  901. fontSize: fontsize,
  902. fontFamily: fontFamily,
  903. justification: 'left'
  904. }),
  905. //
  906. // Points Cardinaux
  907. //
  908. // haut
  909. new paper.Path.Circle({
  910. center: [0, -r],
  911. radius: 0.5,
  912. style: {
  913. fillColor: '#000'
  914. }
  915. }),
  916. new paper.Path.Line({
  917. from: [0, -r],
  918. to: [0, -r - 9],
  919. style: legende_style
  920. }),
  921. new paper.PointText({
  922. point: [0, -r - 11],
  923. content: "6. Décision",
  924. fontSize: fontsize,
  925. fontFamily: fontFamily,
  926. justification: 'center'
  927. }),
  928. // bas
  929. new paper.Path.Circle({
  930. center: [0, r],
  931. radius: 0.5,
  932. style: {
  933. fillColor: '#000'
  934. }
  935. }),
  936. new paper.Path.Line({
  937. from: [0, r],
  938. to: [0, r + 9],
  939. style: legende_style
  940. }),
  941. new paper.PointText({
  942. point: [0, r + 14],
  943. content: "1. Début du cercle\nLe problème\n(injustice, indignation, plainte...)",
  944. fontSize: fontsize,
  945. fontFamily: fontFamily,
  946. justification: 'center'
  947. }),
  948. // droite
  949. new paper.Path.Circle({
  950. center: [r, 0],
  951. radius: 0.5,
  952. style: {
  953. fillColor: '#000'
  954. }
  955. }),
  956. new paper.Path.Line({
  957. from: [r, 0],
  958. to: [r + 8, 0],
  959. style: legende_style
  960. }),
  961. new paper.PointText({
  962. point: [r + 10, -0.5],
  963. content: "8. Adresse de la décision\nà appliquer",
  964. fontSize: fontsize,
  965. fontFamily: fontFamily,
  966. justification: 'left'
  967. }),
  968. // gauche
  969. new paper.Path.Circle({
  970. center: [-r, 0],
  971. radius: 0.5,
  972. style: {
  973. fillColor: '#000'
  974. }
  975. }),
  976. new paper.Path.Line({
  977. from: [-r, 0],
  978. to: [-r - 8, 0],
  979. style: legende_style
  980. }),
  981. new paper.PointText({
  982. point: [-r - 10, 0.4],
  983. content: "4. Adresse de la doléance",
  984. fontSize: fontsize,
  985. fontFamily: fontFamily,
  986. justification: 'right'
  987. }),
  988. ];
  989. return new paper.Group({
  990. children: children,
  991. pivot: new paper.Point(pos),
  992. name: 'doleance_bg',
  993. // locked: true
  994. });
  995. },
  996. // setPaperDoleanceICONSymbol(){
  997. // let children = [];
  998. // let svgIcon = paper.project.importSVG(iconDoleancer);
  999. // children.push(svgIcon);
  1000. // svgIcon.position = this.pos;
  1001. // return new paper.Group({
  1002. // children: children,
  1003. // pivot: new paper.Point(this.pos),
  1004. // name: 'doleance_icon',
  1005. // locked: true,
  1006. // style: {
  1007. // strokeColor: '#000',
  1008. // strokeWidth: 0.75,
  1009. // fillColor: null
  1010. // }
  1011. // });
  1012. // },
  1013. setPaperEntiteSymbol(){
  1014. return new paper.Path.Circle({
  1015. pivot: new paper.Point({x:0,y:0}),
  1016. center: [0,0],
  1017. radius: 0.5, //0.3
  1018. fillColor: '#000',
  1019. strokeColor: 'rgba(255,255,255,0.05)',
  1020. strokeWidth:2
  1021. })
  1022. },
  1023. setPaperEntiteHoverSymbol(){
  1024. return new paper.Path.Circle({
  1025. pivot: new paper.Point({x:0,y:0}),
  1026. center: [0,0],
  1027. radius: 0.5,
  1028. fillColor: '#01ffe2',
  1029. strokeColor: 'rgba(255,255,255,0.05)',
  1030. strokeWidth:2
  1031. })
  1032. },
  1033. setPaperHiddenEntiteSymbol(){
  1034. return new paper.Path.Circle({
  1035. pivot: new paper.Point({x:0,y:0}),
  1036. center: [0,0],
  1037. radius: 0.7, //0.3
  1038. fillColor: '#fff',
  1039. strokeColor: 'rgba(255,255,255,0.05)',
  1040. strokeWidth:2
  1041. })
  1042. },
  1043. setPaperInactiveEntiteSymbol(){
  1044. return new paper.Path.Circle({
  1045. pivot: new paper.Point({x:0,y:0}),
  1046. center: [0,0],
  1047. radius: 0.5, //0.3
  1048. fillColor: '#F00',
  1049. strokeColor: 'rgba(255,0,0,0.05)',
  1050. strokeWidth:2
  1051. })
  1052. },
  1053. setPaperInactiveEntiteHoverSymbol(){
  1054. // let svgIcon = paper.project.importSVG(iconAction);
  1055. // svgIcon.strokeColor = '#01ffe2';
  1056. // svgIcon.strokeWidth = 0.25;
  1057. // svgIcon.scale(0.15);
  1058. // svgIcon.fillColor = null;
  1059. // svgIcon.position = {x:0, y:0};
  1060. // let circle = new paper.Path.Circle({
  1061. // radius: 3,
  1062. // fillColor: 'rgba(255,255,255,0.05)'
  1063. // })
  1064. // return new paper.Group({
  1065. // children: [circle, svgIcon],
  1066. // name: 'action_icon'
  1067. // });
  1068. let children = [];
  1069. let ray = 0.7; //this.map_item_ray;
  1070. // let pos = {x:0, y:0};
  1071. // let strokewidth = 0.4;
  1072. // children.push(new paper.Path.Line({
  1073. // from: [- ray, ray],
  1074. // to: [ray, - ray],
  1075. // strokeColor: '#01ffe2',
  1076. // strokeWidth: strokewidth
  1077. // }));
  1078. // children.push(new paper.Path.Line({
  1079. // from: [ray, ray],
  1080. // to: [- ray, - ray],
  1081. // strokeColor: '#01ffe2',
  1082. // strokeWidth: strokewidth
  1083. // }));
  1084. children.push(new paper.Path.Circle({
  1085. radius: ray/2,
  1086. fillColor: '#F00'
  1087. }))
  1088. children.push(new paper.Path.Circle({
  1089. radius: ray * 1.2,
  1090. strokeColor: '#01ffe2',
  1091. strokeWidth: 0.2,
  1092. fillColor: 'rgba(0,0,0,0)'
  1093. }))
  1094. children.push(new paper.Path.Circle({
  1095. radius: ray,
  1096. fillColor: 'rgba(255,255,255,0.01)'
  1097. }))
  1098. return new paper.Group({
  1099. children: children,
  1100. name: 'action_icon'
  1101. });
  1102. },
  1103. setPaperEntiteActionIconSymbol(){
  1104. // let svgIcon = paper.project.importSVG(iconAction);
  1105. // svgIcon.strokeWidth = 0.8;
  1106. // svgIcon.scale(0.6);
  1107. // svgIcon.strokeColor = '#000';
  1108. // svgIcon.fillColor = null;
  1109. // svgIcon.position = {x:0, y:0};
  1110. let children = [];
  1111. let ray = 2; //this.map_item_ray;
  1112. let pos = {x:0, y:0};
  1113. children.push(new paper.Path.Line({
  1114. from: [- ray, ray],
  1115. to: [ray, - ray],
  1116. strokeColor: '#000',
  1117. strokeWidth: 1.1
  1118. }));
  1119. children.push(new paper.Path.Line({
  1120. from: [ray, ray],
  1121. to: [- ray, - ray],
  1122. strokeColor: '#000',
  1123. strokeWidth: 1.1
  1124. }));
  1125. return new paper.Group({
  1126. children: children,
  1127. name: 'action_icon'
  1128. });
  1129. },
  1130. setPaperEntiteActionSymbol(){
  1131. // let svgIcon = paper.project.importSVG(iconAction);
  1132. // svgIcon.strokeWidth = 0.25;
  1133. // svgIcon.scale(0.15);
  1134. // svgIcon.strokeColor = '#000';
  1135. // svgIcon.fillColor = null;
  1136. // svgIcon.position = {x:0, y:0};
  1137. let children = [];
  1138. let ray = 1; //this.map_item_ray;
  1139. // let pos = {x:0, y:0};
  1140. // children.push(new paper.Path.Line({
  1141. // from: [- ray, ray],
  1142. // to: [ray, - ray],
  1143. // strokeColor: '#000',
  1144. // strokeWidth: strokewidth
  1145. // }));
  1146. // children.push(new paper.Path.Line({
  1147. // from: [ray, ray],
  1148. // to: [- ray, - ray],
  1149. // strokeColor: '#000',
  1150. // strokeWidth: strokewidth
  1151. // }));
  1152. children.push(new paper.Path.Circle({
  1153. radius: ray/2,
  1154. fillColor: 'rgba(0,0,0,1)'
  1155. }))
  1156. children.push(new paper.Path.Circle({
  1157. radius: ray,
  1158. strokeColor: 'rgba(0,0,0,1)',
  1159. strokeWidth: 0.2,
  1160. fillColor: 'rgba(0,0,0,0)'
  1161. }))
  1162. children.push(new paper.Path.Circle({
  1163. radius: ray,
  1164. fillColor: 'rgba(255,255,255,0.01)'
  1165. }))
  1166. return new paper.Group({
  1167. children: children,
  1168. name: 'action_icon'
  1169. });
  1170. },
  1171. setPaperEntiteActionHoverSymbol(){
  1172. // let svgIcon = paper.project.importSVG(iconAction);
  1173. // svgIcon.strokeColor = '#01ffe2';
  1174. // svgIcon.strokeWidth = 0.25;
  1175. // svgIcon.scale(0.15);
  1176. // svgIcon.fillColor = null;
  1177. // svgIcon.position = {x:0, y:0};
  1178. // let circle = new paper.Path.Circle({
  1179. // radius: 3,
  1180. // fillColor: 'rgba(255,255,255,0.05)'
  1181. // })
  1182. // return new paper.Group({
  1183. // children: [circle, svgIcon],
  1184. // name: 'action_icon'
  1185. // });
  1186. let children = [];
  1187. let ray = 0.7; //this.map_item_ray;
  1188. // let pos = {x:0, y:0};
  1189. // let strokewidth = 0.4;
  1190. // children.push(new paper.Path.Line({
  1191. // from: [- ray, ray],
  1192. // to: [ray, - ray],
  1193. // strokeColor: '#01ffe2',
  1194. // strokeWidth: strokewidth
  1195. // }));
  1196. // children.push(new paper.Path.Line({
  1197. // from: [ray, ray],
  1198. // to: [- ray, - ray],
  1199. // strokeColor: '#01ffe2',
  1200. // strokeWidth: strokewidth
  1201. // }));
  1202. children.push(new paper.Path.Circle({
  1203. radius: ray/2,
  1204. fillColor: '#01ffe2'
  1205. }))
  1206. children.push(new paper.Path.Circle({
  1207. radius: ray,
  1208. strokeColor: '#01ffe2',
  1209. strokeWidth: 0.2,
  1210. fillColor: 'rgba(0,0,0,0)'
  1211. }))
  1212. children.push(new paper.Path.Circle({
  1213. radius: ray,
  1214. fillColor: 'rgba(255,255,255,0.01)'
  1215. }))
  1216. return new paper.Group({
  1217. children: children,
  1218. name: 'action_icon'
  1219. });
  1220. },
  1221. setPaperBesoinSymbol(){
  1222. return new paper.Path({
  1223. pivot: new paper.Point(this.pos),
  1224. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  1225. fillColor: '#000'
  1226. })
  1227. },
  1228. setPaperBesoinHoverSymbol(){
  1229. return new paper.Path({
  1230. pivot: new paper.Point(this.pos),
  1231. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  1232. fillColor: '#01ffe2'
  1233. })
  1234. },
  1235. setPaperReponseSymbol(){
  1236. return new paper.Path({
  1237. pivot: new paper.Point(this.pos),
  1238. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  1239. fillColor: '#eee',
  1240. strokeColor: "#000",
  1241. strokeWidth: 0.25,
  1242. })
  1243. },
  1244. setPaperReponseHoverSymbol(){
  1245. return new paper.Path({
  1246. pivot: new paper.Point(this.pos),
  1247. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  1248. fillColor: '#eee',
  1249. strokeColor: "#01ffe2",
  1250. strokeWidth: 0.25,
  1251. })
  1252. },
  1253. async setSuperpositionsMatterConstraints(){
  1254. await nextTick(); // wait for dom to be upadted before applying constraint
  1255. console.log('setSuperpositionsMatterConstraints this.allSuperpositions_clustered', this.allSuperpositions_clustered);
  1256. // loop through all supperposition couple
  1257. for(let [cluster_index, cluster] of Object.entries(this.allSuperpositions_clustered)){
  1258. for(let [i, cid_eid_A] of cluster.entries()){
  1259. // console.log(`i:${i}, cid_eid_A cid:${cid_eid_A.cid}, eid:${cid_eid_A.eid}`);
  1260. let cid_eid_B = i === cluster.length -1 ? cluster[0] : cluster[i+1];
  1261. // console.log(`i:${i}, cid_eid_B cid:${cid_eid_B.cid}, eid:${cid_eid_B.eid}`);
  1262. let concernementA = this.concernementsByID[cid_eid_A.cid];
  1263. // console.log('concernementA', concernementA);
  1264. let concernementB = this.concernementsByID[cid_eid_B.cid];
  1265. // console.log('concernementB', concernementB);
  1266. // console.log('superposition', superposition_id, superposition);
  1267. let mapitemA_id = `${cid_eid_A.cid}___${cluster_index}`
  1268. let mapitemB_id = `${cid_eid_B.cid}___${cluster_index}`
  1269. // console.log(`mapitemA_id: ${mapitemA_id}, mapitemB_id: ${mapitemB_id}`);
  1270. let mapitemA = this.allMapItems_byid[mapitemA_id];
  1271. let mapitemB = this.allMapItems_byid[mapitemB_id];
  1272. console.log('mapitemA', mapitemA);
  1273. console.log('mapitemB', mapitemB);
  1274. // get the concernement matter bodies with id
  1275. let bodyA = Matter.Composite.get(this.world, mapitemA_id, 'body'); // matter body id is the same as mapitem_id
  1276. let bodyB = Matter.Composite.get(this.world, mapitemB_id, 'body'); // matter body id is the same as mapitem_id
  1277. // console.log('bodyA, bodyB', bodyA, bodyB);
  1278. // get the entite coordinates inside the concernement body
  1279. let pointA = null;
  1280. for(let entiteA of concernementA.revisions_byid[concernementA.active_revision].entites){
  1281. if (entiteA.entite && entiteA.entite.id === cid_eid_A.eid && entiteA.display) {
  1282. // console.log('entiteA', entiteA);
  1283. let scale = mapitemA.scale;
  1284. console.log(`mapitemA.scale ${concernementA.id}`, scale);
  1285. pointA = Matter.Vector.create(entiteA.display.pos.x * scale, entiteA.display.pos.y * scale);
  1286. break;
  1287. }
  1288. }
  1289. let pointB = null;
  1290. for(let entiteB of concernementB.revisions_byid[concernementB.active_revision].entites){
  1291. if (entiteB.entite && entiteB.entite.id === cid_eid_B.eid && entiteB.display) {
  1292. // console.log('entiteB', entiteB);
  1293. let scale = mapitemB.scale;
  1294. console.log(`mapitemB.scale ${concernementB.id}`, scale);
  1295. pointB = Matter.Vector.create(entiteB.display.pos.x * scale, entiteB.display.pos.y * scale);
  1296. break;
  1297. }
  1298. }
  1299. // console.log(`pointA:`, pointA,` pointB:`, pointB);
  1300. if (bodyA && bodyB && pointA && pointB) {
  1301. let c = Matter.Constraint.create({
  1302. bodyA: bodyA,
  1303. pointA: pointA,
  1304. bodyB: bodyB,
  1305. pointB: pointB,
  1306. stiffness: 1,
  1307. length: 0,
  1308. damping: 1,
  1309. concernementA: concernementA,
  1310. concernementB: concernementB
  1311. });
  1312. this.superpositions_constraints.push(c);
  1313. Matter.Composite.add(this.world, c);
  1314. // keep a link the constraint into the concernement object (useful for tweening the constraint pointA & pointB in concernementMapItem)
  1315. if(!concernementA.superposition_constraints_id[mapitemA_id]){
  1316. concernementA.superposition_constraints_id[mapitemA_id] = [];
  1317. }
  1318. concernementA.superposition_constraints_id[mapitemA_id].push(c.id);
  1319. if(!concernementB.superposition_constraints_id[mapitemB_id]){
  1320. concernementB.superposition_constraints_id[mapitemB_id] = [];
  1321. }
  1322. concernementB.superposition_constraints_id[mapitemB_id].push(c.id);
  1323. // record all superposed concernements for each concernement
  1324. if (concernementA.all_superposed_concernements_id.indexOf(concernementB.id) < 0) {
  1325. concernementA.all_superposed_concernements_id.push(concernementB.id);
  1326. }
  1327. if (concernementB.all_superposed_concernements_id.indexOf(concernementA.id) < 0) {
  1328. concernementB.all_superposed_concernements_id.push(concernementA.id);
  1329. }
  1330. // record all superposed concernements for each concernement by mapitem_id
  1331. // A
  1332. if (!concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id]) {
  1333. concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id] = []
  1334. }
  1335. if (concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id].indexOf(mapitemB_id) < 0) {
  1336. concernementA.superposed_mapitem_id_by_mapitem_id[mapitemA_id].push(mapitemB_id);
  1337. }
  1338. // B
  1339. if (!concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id]) {
  1340. concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id] = []
  1341. }
  1342. if (concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id].indexOf(mapitemA_id) < 0) {
  1343. concernementB.superposed_mapitem_id_by_mapitem_id[mapitemB_id].push(mapitemA_id);
  1344. }
  1345. }
  1346. }
  1347. }
  1348. },
  1349. clearSuperpositionsMatterConstraints(){
  1350. console.log('clearSuperpositionsMatterConstraints', this.superpositions_constraints);
  1351. for(let constraint of this.superpositions_constraints){
  1352. // Delete superposition constraints ids recorded in concernement object
  1353. ['A', 'B'].forEach(ab => {
  1354. for( let [mapitem_id, constraint_ids] of Object.entries(constraint[`concernement${ab}`].superposition_constraints_id)){
  1355. let indexes = Object.keys(constraint_ids);
  1356. indexes.forEach(i => {
  1357. if(constraint_ids[i] === constraint.id) {
  1358. delete constraint[`concernement${ab}`].superposition_constraints_id[mapitem_id][i];
  1359. }
  1360. })
  1361. }
  1362. });
  1363. Matter.Composite.remove(this.world, constraint, true);
  1364. }
  1365. this.superpositions_constraints = [];
  1366. },
  1367. // resetSuperpositionsMatterConstraints(){
  1368. // this.clearSuperpositionsMatterConstraints();
  1369. // this.setSuperpositionsMatterConstraints();
  1370. // },
  1371. onBeforeEngineUpdate(){
  1372. },
  1373. onAfterEngineUpdate(){
  1374. // // START OF DEBUGGING
  1375. // this.debugDrawConstraints()
  1376. // this.debugDrawWalls()
  1377. // // END OF DEBUGGING
  1378. },
  1379. debugDrawConstraints(){
  1380. // draw lines of constraints for debuging
  1381. let constraints_lines = this.paper.project.getItem({name: 'constraints_lines', class: paper.Group});
  1382. if (constraints_lines) {
  1383. constraints_lines.removeChildren();
  1384. }else{
  1385. constraints_lines = new paper.Group({
  1386. pivot: new paper.Point({x:0,y:0}),
  1387. name: 'constraints_lines',
  1388. });
  1389. }
  1390. let all_constrains = Matter.Composite.allConstraints(this.world);
  1391. let children = [];
  1392. for(let constraint of all_constrains){
  1393. // console.log('constrain', constraint);
  1394. let pointAWorld = Matter.Constraint.pointAWorld(constraint);
  1395. let pointBWorld = Matter.Constraint.pointBWorld(constraint);
  1396. // console.log('pointAWorld, pointBWorld', pointAWorld, pointBWorld);
  1397. children.push(new paper.Path.Line({
  1398. from: [pointAWorld.x, pointAWorld.y],
  1399. to: [pointBWorld.x, pointBWorld.y],
  1400. strokeColor: '#f00',
  1401. strokeWidth: 1
  1402. }));
  1403. }
  1404. constraints_lines.addChildren(children);
  1405. },
  1406. debugDrawWalls(){
  1407. let wall_rects = this.paper.project.getItem({name: 'wall_rects', class: paper.Group});
  1408. if (wall_rects) {
  1409. wall_rects.removeChildren();
  1410. }else{
  1411. wall_rects = new paper.Group({
  1412. pivot: new paper.Point({x:0,y:0}),
  1413. name: 'wall_rects',
  1414. });
  1415. }
  1416. let wallsbody = Matter.Composite.get(this.world, 'walls', 'body');
  1417. if (wallsbody) {
  1418. // console.log('wallsbody', wallsbody.parts);
  1419. let children = [];
  1420. wallsbody.parts.forEach((part, i) => {
  1421. if(i > 0){
  1422. // console.log('part', part.label, part.bounds.min);
  1423. children.push(new paper.Path.Rectangle({
  1424. from: part.bounds.min,
  1425. to: part.bounds.max,
  1426. strokeColor: '#00f',
  1427. strokeWidth: 2
  1428. }));
  1429. }
  1430. });
  1431. wall_rects.addChildren(children);
  1432. }
  1433. }
  1434. },
  1435. beforeUpdate () {
  1436. },
  1437. components: {
  1438. MapGradientBackground,
  1439. ConcernementMapPopup,
  1440. RecitPlayer
  1441. }
  1442. }
  1443. </script>
  1444. <template>
  1445. <div id="map-backgrounds">
  1446. <MapGradientBackground />
  1447. </div>
  1448. <!-- <div id="map-matter">
  1449. <canvas ref="canvas-engine"></canvas>
  1450. </div> -->
  1451. <div id="map-concernements">
  1452. <canvas ref="canvas-map"></canvas>
  1453. <slot></slot>
  1454. </div>
  1455. <nav id="map-nav">
  1456. <ul>
  1457. <li>
  1458. <a
  1459. title="terrain de vie" href="#terraindevie" @click="setMapMode('terraindevie')"
  1460. :class="{active: map_mode === 'terraindevie'}"
  1461. >
  1462. <span class="icon terraindevie"/> <span class="label"> terrain de vie</span>
  1463. </a>
  1464. </li>
  1465. <li>
  1466. <a
  1467. title="proximite" href="#proximite" @click="setMapMode('proximite')"
  1468. :class="{ disabled: opened_concernement && !opened_concernement.has_proximites, active: map_mode === 'proximite'}"
  1469. >
  1470. <span class="icon proximite"/> <span class="label"> proximité</span>
  1471. </a>
  1472. </li>
  1473. <li>
  1474. <a
  1475. title="superposition" href="#superposition" @click="setMapMode('superposition')"
  1476. :class="{ disabled: opened_concernement && !opened_concernement.has_superpositions, active: map_mode === 'superposition'}"
  1477. >
  1478. <span class="icon superposition"/> <span class="label"> superposition</span>
  1479. </a>
  1480. </li>
  1481. <li>
  1482. <a
  1483. title="puissance d'agir" href="#puissancedagir" @click="setMapMode('puissancedagir')"
  1484. :class="{
  1485. disabled: opened_concernement && !opened_concernement.has_puissancedagir && !opened_concernement.can_update,
  1486. active: map_mode === 'puissancedagir'}"
  1487. >
  1488. <span class="icon puissancedagir"/> <span class="label"> puissance d'agir</span>
  1489. </a>
  1490. </li>
  1491. <li>
  1492. <a
  1493. title="action" href="#action" @click="setMapMode('action')"
  1494. :class="{ disabled: opened_concernement && !opened_concernement.has_agissantes, active: map_mode === 'action'}"
  1495. >
  1496. <span class="icon action"/> <span class="label"> action</span>
  1497. </a>
  1498. </li>
  1499. <li>
  1500. <a
  1501. title="cercle politique" href="#doleancer" @click="setMapMode('doleancer')"
  1502. :class="{ disabled: opened_concernement && !opened_concernement.has_doleance, active: map_mode === 'doleancer'}"
  1503. >
  1504. <span class="icon doleancer"/> <span class="label"> cercle politique</span>
  1505. </a>
  1506. </li>
  1507. </ul>
  1508. </nav>
  1509. <RecitPlayer />
  1510. <ConcernementMapPopup
  1511. v-if="hover_elmt && hover_elmt.type !== 'doleance_step' && !hover_elmt.no_popup"
  1512. :infos="hover_elmt"
  1513. />
  1514. </template>
  1515. <style lang="css" scoped>
  1516. </style>