MapConcernements.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. <script>
  2. // import { mapActions, mapState } from 'pinia'
  3. import { computed } from 'vue'
  4. import MapBackground from '@components/MapBackground.vue'
  5. // https://brm.io/matter-js/docs/classes/Engine.html
  6. import Matter from "matter-js";
  7. import MatterAttractors from "matter-attractors";
  8. Matter.use(MatterAttractors);
  9. import paper from 'paper';
  10. import { mapState, mapActions } from 'pinia'
  11. import { ConcernementsStore } from '@/stores/concernements'
  12. import { CommonStore } from '@/stores/common'
  13. import ConcernementMapPopup from '@components/ConcernementMapPopup.vue';
  14. // import iconTerraindevie from "@/assets/icons/terraindevie.svg"
  15. // import iconProximite from "@/assets/icons/proximite.svg"
  16. // import iconSuperposition from "@/assets/icons/superposition.svg"
  17. import iconPuissanceagir from "@/assets/icons/puissancedagir.svg"
  18. // import iconAction from "@/assets/icons/action.svg"
  19. import iconDoleancer from "@/assets/icons/doleancer.svg"
  20. export default {
  21. data() {
  22. return {
  23. canvasMap: {
  24. canvas: null,
  25. ctx: null
  26. },
  27. animateEvent: new Event('animate'),
  28. granim: null,
  29. // MATTER
  30. engine: null,
  31. world: null,
  32. // PAPERJS
  33. paper: null,
  34. //
  35. mapPopupData: null,
  36. }
  37. },
  38. provide() {
  39. // https://www.digitalocean.com/community/tutorials/vuejs-vue-html5-canvas
  40. return {
  41. // explicitly provide a computed property
  42. canvasMap: computed(() => this.canvasMap),
  43. matterEngine: computed(() => this.engine)
  44. }
  45. },
  46. computed: {
  47. ...mapState(ConcernementsStore,['map_mode']),
  48. ...mapState(ConcernementsStore,['concernements']),
  49. ...mapState(ConcernementsStore,['concernementsByID']),
  50. ...mapState(ConcernementsStore,['opened_concernement']),
  51. ...mapState(CommonStore,['hover_elmt']),
  52. ...mapState(CommonStore,['paper_symbol_definitions'])
  53. },
  54. created() {
  55. // MATTER
  56. // create an engine
  57. let engineOptions = {
  58. enableSleeping: true,
  59. timing: {
  60. //timestamp: 0.5,
  61. timeScale: 0.5
  62. }
  63. }
  64. this.engine = Matter.Engine.create(engineOptions);
  65. this.engine.gravity.scale = 0;
  66. this.world = this.engine.world;
  67. },
  68. mounted() {
  69. this.canvasMap.canvas = this.$refs['canvas-map'];
  70. this.canvasMap.ctx = this.canvasMap.canvas.getContext('2d');
  71. let canvas_w = this.canvasMap.canvas.width = this.canvasMap.canvas.parentElement.clientWidth;
  72. let canvas_h = this.canvasMap.canvas.height = this.canvasMap.canvas.parentElement.clientHeight;
  73. console.log(`canvas_w: ${canvas_w}, canvas_h: ${canvas_h}`);
  74. // PAPER
  75. this.paper = paper.setup(this.canvasMap.canvas);
  76. // symbol defintions
  77. this.initPaperSymbols();
  78. // use the paper.view click to get back if no items is clicked
  79. this.paper.view.onClick = function(event) {
  80. console.log("view onClick", this, event.target);
  81. if(event.target._id === "paper-view-0") {
  82. this.resetConcernementOpened();
  83. this.$router.push({
  84. name: 'home',
  85. hash: `#${this.map_mode}`
  86. });
  87. }
  88. }.bind(this);
  89. // MATTER
  90. let wall_w = 1000;
  91. Matter.Composite.add(this.world, [
  92. // walls
  93. Matter.Bodies.rectangle(canvas_w/2, -wall_w/2, canvas_w, wall_w, { isStatic: true }), // top
  94. Matter.Bodies.rectangle(canvas_w/2, canvas_h+wall_w/2, canvas_w, wall_w, { isStatic: true }), // bottom
  95. Matter.Bodies.rectangle(-wall_w/2, canvas_h/2, wall_w, canvas_h, { isStatic: true }), // left
  96. Matter.Bodies.rectangle(canvas_w+wall_w/2, canvas_h/2, wall_w, canvas_h, { isStatic: true }), // right
  97. // make the items never goes under menus
  98. Matter.Bodies.rectangle(550, 25, 900, 50, { isStatic: true }), // menu top
  99. Matter.Bodies.rectangle(550, canvas_h-15, 900, 30, { isStatic: true }) // menu bottom
  100. ]);
  101. // add mouse control
  102. // https://github.com/liabru/matter-js/issues/491#issuecomment-331329404
  103. // this.mouse = Matter.Mouse.create(this.canvasMap.canvas);
  104. this.animate()
  105. },
  106. watch: {
  107. hover_elmt: {
  108. handler (n, o) {
  109. console.log(`watch hover_elmt map: o, n`, o, n);
  110. // over highlight effect on paper items
  111. if (n && n.paper_id) {
  112. let nitem = paper.project.getItem({id: n.paper_id});
  113. console.log('watch hover_element nitem', nitem.definition);
  114. if (!nitem.is_symbol_instance) { // not symbol instance
  115. nitem.bringToFront();
  116. if (nitem.strokeColor) {
  117. nitem.data.prevStrokeColor = nitem.strokeColor.toCSS(true);
  118. nitem.strokeColor = "#01ffe2";
  119. } else {
  120. nitem.data.prevFillColor = nitem.fillColor.toCSS(true);
  121. nitem.fillColor = "#01ffe2";
  122. }
  123. } else { // is a symbol instanceof, then swap
  124. console.log(`symbol instance n.type:${n.type}, nitem`, nitem);
  125. switch (n.type) {
  126. case 'entite':
  127. nitem.definition = this.paper_symbol_definitions.entite_hover;
  128. break;
  129. case 'besoin':
  130. nitem.definition = this.paper_symbol_definitions.besoin_hover;
  131. break;
  132. case 'reponse':
  133. nitem.definition = this.paper_symbol_definitions.reponse_hover;
  134. break;
  135. }
  136. }
  137. }
  138. if (o && o.paper_id) {
  139. let oitem = paper.project.getItem({id: o.paper_id})
  140. console.log('watch hover_element oitem', oitem);
  141. if (!oitem.is_symbol_instance) { // not symbol instance
  142. if (oitem.data.prevStrokeColor) {
  143. oitem.strokeColor = oitem.data.prevStrokeColor;
  144. } else {
  145. oitem.fillColor = oitem.data.prevFillColor;
  146. }
  147. } else { // is a symbol instanceof, then swap
  148. console.log(`symbol instance o.type:${o.type}, oitem`, oitem);
  149. switch (o.type) {
  150. case 'entite':
  151. oitem.definition = this.paper_symbol_definitions.entite;
  152. break;
  153. case 'besoin':
  154. oitem.definition = this.paper_symbol_definitions.besoin;
  155. break;
  156. case 'reponse':
  157. oitem.definition = this.paper_symbol_definitions.reponse;
  158. break;
  159. }
  160. }
  161. }
  162. },
  163. deep: true
  164. }
  165. },
  166. methods: {
  167. ...mapActions(ConcernementsStore,['setMapMode']),
  168. ...mapActions(ConcernementsStore,['resetConcernementOpened']),
  169. // ...mapActions(ConcernementsStore,['openCloseConcernements']),
  170. ...mapActions(CommonStore,['addPaperSymbolDefinition']),
  171. animate () {
  172. Matter.Engine.update(this.engine, 1);
  173. window.requestAnimationFrame(this.animate);
  174. },
  175. initPaperSymbols(){
  176. this.addPaperSymbolDefinition('boussole_bg', this.setPaperBoussoleBGSymbol());
  177. this.addPaperSymbolDefinition('puissanceagir_bg', this.setPaperPuissanceagirBGSymbol());
  178. this.addPaperSymbolDefinition('puissanceagir_icon', this.setPaperPuissanceagirICONSymbol());
  179. this.addPaperSymbolDefinition('doleance_bg', this.setPaperDoleanceBGSymbol());
  180. this.addPaperSymbolDefinition('doleance_icon', this.setPaperDoleanceICONSymbol());
  181. //
  182. this.addPaperSymbolDefinition('entite', this.setPaperEntiteSymbol());
  183. this.addPaperSymbolDefinition('entite_hover', this.setPaperEntiteHoverSymbol());
  184. this.addPaperSymbolDefinition('besoin', this.setPaperBesoinSymbol());
  185. this.addPaperSymbolDefinition('besoin_hover', this.setPaperBesoinHoverSymbol());
  186. this.addPaperSymbolDefinition('reponse', this.setPaperReponseSymbol());
  187. this.addPaperSymbolDefinition('reponse_hover', this.setPaperReponseHoverSymbol());
  188. },
  189. setPaperBoussoleBGSymbol(){
  190. // BOUSSOLE
  191. let children = [];
  192. let ray = 100;
  193. let pos = {x:0, y:0};
  194. // cercles pointillés
  195. for (let i = 1; i < 9; i++) {
  196. let sw = i === 4 || i === 8 ? 0.5 : 0.25;
  197. let da = i === 4 || i === 8 ? null : [5,5];
  198. children.push(new paper.Path.Circle({
  199. center: [pos.x, pos.y],
  200. radius: ray/8*i,
  201. strokeColor: '#fff',
  202. strokeWidth: sw,
  203. dashArray: da
  204. }));
  205. }
  206. // axes
  207. // vertical
  208. children.push(new paper.Path.Line({
  209. from: [pos.x, pos.y - ray],
  210. to: [pos.x, pos.y + ray],
  211. strokeColor: '#fff',
  212. strokeWidth: 0.5
  213. }));
  214. // horizontal
  215. children.push(new paper.Path.Line({
  216. from: [pos.x - ray, pos.y],
  217. to: [pos.x + ray, pos.y],
  218. strokeColor: '#fff',
  219. strokeWidth: 0.5
  220. }))
  221. // fleches
  222. // haute
  223. children.push(new paper.Path({
  224. segments: [
  225. [pos.x - 8, pos.y - ray + 8],
  226. [pos.x, pos.y - ray],
  227. [pos.x + 8, pos.y - ray + 8],
  228. ],
  229. strokeWidth: 0.5,
  230. strokeColor: '#fff',
  231. }));
  232. // milieu
  233. children.push(new paper.Path({
  234. segments: [
  235. [pos.x - 8, pos.y + 8],
  236. [pos.x, pos.y],
  237. [pos.x + 8, pos.y + 8],
  238. ],
  239. strokeWidth: 0.5,
  240. strokeColor: '#fff',
  241. }));
  242. // MOINS - PLUS
  243. // PLUS
  244. // horizontal
  245. children.push(new paper.Path.Line({
  246. from: [pos.x + ray - 5, pos.y - ray],
  247. to: [pos.x + ray + 5, pos.y - ray],
  248. strokeWidth: 2,
  249. strokeColor: '#fff',
  250. }))
  251. // vertical
  252. children.push(new paper.Path.Line({
  253. from: [pos.x + ray, pos.y - ray - 5],
  254. to: [pos.x + ray, pos.y - ray + 5],
  255. strokeWidth: 2,
  256. strokeColor: '#fff',
  257. }))
  258. // MOINS
  259. // horizontal
  260. children.push(new paper.Path.Line({
  261. from: [pos.x - ray - 5, pos.y - ray],
  262. to: [pos.x - ray + 5, pos.y - ray],
  263. strokeWidth: 2,
  264. strokeColor: '#fff',
  265. }))
  266. let fontsize = 4;
  267. let fontFamily = "public_sans";
  268. children.push(new paper.PointText({
  269. point: [pos.x + 4.5, pos.y - ray - 5],
  270. content: `entités qui menacent \u2194 entités qui maintiennent`,
  271. fontSize: fontsize,
  272. fontFamily: fontFamily,
  273. justification: 'center',
  274. fillColor: '#000',
  275. }))
  276. children.push(new paper.PointText({
  277. point: [pos.x - ray - 5, pos.y + 1],
  278. content: "axe d'intensité",
  279. fontSize: fontsize,
  280. fontFamily: fontFamily,
  281. justification: 'right',
  282. fillColor: '#000',
  283. }))
  284. children.push(new paper.PointText({
  285. point: [pos.x + ray + 5, pos.y - 3],
  286. content: "situation future\n\u2195\nsituation actuelle",
  287. fontSize: fontsize,
  288. fontFamily: fontFamily,
  289. justification: 'left',
  290. fillColor: '#000',
  291. }))
  292. let t1 = new paper.PointText({
  293. point: [pos.x - ray/8*2.3, pos.y - ray/8*2.3],
  294. content: "avec prise",
  295. fontSize: fontsize,
  296. fontFamily: fontFamily,
  297. justification: 'center',
  298. fillColor: '#000',
  299. })
  300. t1.rotate(-45)
  301. children.push(t1)
  302. let t2 = new paper.PointText({
  303. point: [pos.x - ray/8*2.95, pos.y - ray/8*2.95],
  304. content: "sans prise",
  305. fontSize: fontsize,
  306. fontFamily: fontFamily,
  307. justification: 'center',
  308. fillColor: '#000',
  309. })
  310. t2.rotate(-45)
  311. children.push(t2)
  312. return new paper.Group({
  313. children: children,
  314. pivot: new paper.Point(pos),
  315. name: 'boussole_bg',
  316. // locked: true,
  317. });
  318. },
  319. setPaperPuissanceagirBGSymbol(){
  320. let children = [];
  321. let ray = 100;
  322. let pos = {x:0,y:0};
  323. // cercles interieur
  324. for (let i = 1; i < 6; i++) {
  325. children.push(new paper.Path.Circle({
  326. center: [pos.x, pos.y],
  327. radius: (ray/5)*i,
  328. strokeWidth: 0.25
  329. }));
  330. }
  331. // rayons
  332. for (let j = 0; j < 16; j++) {
  333. let a = (360 / 16) * j;
  334. let ext_x = Math.cos(a*(Math.PI/180)) * ray;
  335. let ext_y = Math.sin(a*(Math.PI/180)) * ray;
  336. let int_x = Math.cos(a*(Math.PI/180)) * 2;
  337. let int_y = Math.sin(a*(Math.PI/180)) * 2;
  338. children.push(new paper.Path.Line({
  339. from: [pos.x + ext_x, pos.y + ext_y],
  340. to: [pos.x + int_x, pos.y + int_y],
  341. strokeWidth: 0.25,
  342. dashArray: [0.5,1]
  343. }))
  344. }
  345. // cercle exterieur
  346. children.push(new paper.Path.Circle({
  347. center: [pos.x, pos.y],
  348. radius: ray,
  349. strokeWidth: 0.5,
  350. fillColor: `rgba(255,255,255,0.6)`
  351. }));
  352. return new paper.Group({
  353. children: children,
  354. pivot: new paper.Point(pos),
  355. name: 'puissanceagir_bg',
  356. // locked: true,
  357. style: {
  358. strokeColor: '#fff'
  359. }
  360. });
  361. },
  362. setPaperPuissanceagirICONSymbol(){
  363. let children = [];
  364. let svgIcon = paper.project.importSVG(iconPuissanceagir);
  365. children.push(svgIcon);
  366. svgIcon.position = this.pos;
  367. return new paper.Group({
  368. children: children,
  369. pivot: new paper.Point(this.pos),
  370. name: 'puissanceagir_icon',
  371. locked: true,
  372. style: {
  373. strokeColor: '#000',
  374. strokeWidth: 0.75,
  375. fillColor: null
  376. }
  377. });
  378. },
  379. setPaperDoleanceBGSymbol(){
  380. let ray = 100;
  381. let pos = {x:0,y:0};
  382. var r = ray * 0.8; // ray
  383. var dr = r/2; // demi ray
  384. var pcr = 2; // petits cercle rayon
  385. // https://fr.wikipedia.org/wiki/Trigonom%C3%A9trie#/media/Fichier:Unit_circle_angles_color.svg
  386. // https://fr.wikipedia.org/wiki/Identit%C3%A9_trigonom%C3%A9trique_pythagoricienne#Preuve_utilisant_le_cercle_unit%C3%A9
  387. // radians = degrees * (pi/180)
  388. // degrees = radians * (180/pi)
  389. // Points for 45° axes
  390. let m = Math.sin(45*(Math.PI/180)) * r; // x = y for rayon
  391. let n = Math.sin(45*(Math.PI/180)) * r/2; // x = y for demi rayon
  392. // console.log('m', m);
  393. // points for legende arcs
  394. var lar = r*1.1; // legendes arcs rayon
  395. let o = Math.cos(22.5*(Math.PI/180)) * lar; // x @ 22.5° for legende arc rayon
  396. let p = Math.sin(22.5*(Math.PI/180)) * lar; // y @ 22.5° for legende arc rayon
  397. let q = Math.sin(45*(Math.PI/180)) * lar; // x = y @ 45° for legende arc rayon
  398. var ltr = lar + 4; // legendes texts rayon
  399. let o_t = Math.cos(22.5*(Math.PI/180)) * ltr; // x @ 22.5° for legende text rayon
  400. let p_t = Math.sin(22.5*(Math.PI/180)) * ltr; // y @ 22.5° for legende text rayon
  401. let q_t = Math.sin(45*(Math.PI/180)) * ltr; // x = y @ 45° for legende text rayon
  402. let style = {strokeColor: '#fff', strokeWidth: 0.25}
  403. let felchesstyle = {strokeColor: '#fff', strokeWidth: 0.5}
  404. let legende_style = {strokeColor: '#000', strokeWidth: 0.25}
  405. let fontsize = 4;
  406. let fontFamily = "public_sans";
  407. let children = [
  408. // big global exterior circle to keep center aligned
  409. new paper.Path.Circle({
  410. center: [0, 0],
  411. radius: r*2,
  412. style: {
  413. strokeColor: 'rgba(255,255,255,0)',
  414. strokeWidth: 0.5
  415. }
  416. }),
  417. //
  418. // ARCS EXTERIEURS
  419. // haut gauche
  420. new paper.Path.Arc({
  421. from: [- r, -pcr],
  422. through: [- m, -m],
  423. to: [ -pcr, -r],
  424. style: style
  425. }),
  426. // haut droite
  427. new paper.Path.Arc({
  428. from: [pcr, -r],
  429. through: [m, -m],
  430. to: [r, -pcr],
  431. style: style
  432. }),
  433. // bas droite
  434. new paper.Path.Arc({
  435. from: [r, pcr],
  436. through: [m, m],
  437. to: [pcr, r],
  438. style: style
  439. }),
  440. // bas gauche
  441. new paper.Path.Arc({
  442. from: [-pcr, r],
  443. through: [-m, m],
  444. to: [-r, pcr],
  445. style: style
  446. }),
  447. //
  448. // cercle interieur
  449. new paper.Path.Circle({
  450. center: [0, 0],
  451. radius: dr,
  452. style: style
  453. }),
  454. //
  455. // petit cercles
  456. new paper.Path.Circle({
  457. center: [0, -r],
  458. radius: pcr,
  459. style: style
  460. }),
  461. new paper.Path.Circle({
  462. center: [0, r],
  463. radius: pcr,
  464. style: style
  465. }),
  466. new paper.Path.Circle({
  467. center: [r, 0],
  468. radius: pcr,
  469. style: style
  470. }),
  471. new paper.Path.Circle({
  472. center: [-r, 0],
  473. radius: pcr,
  474. style: style
  475. }),
  476. //
  477. // AXES
  478. // vertical haut
  479. new paper.Path.Line({
  480. from: [0, -r + pcr],
  481. to: [0, -dr],
  482. style: style
  483. }),
  484. // vertical bas
  485. new paper.Path.Line({
  486. from: [0, r - pcr],
  487. to: [0, dr],
  488. style: style
  489. }),
  490. // horizontal gauche
  491. new paper.Path.Line({
  492. from: [-r + pcr, 0],
  493. to: [-dr, 0],
  494. style: style
  495. }),
  496. // horizontal droite
  497. new paper.Path.Line({
  498. from: [r - pcr, 0],
  499. to: [dr, 0],
  500. style: style
  501. }),
  502. //
  503. // DIAGONALES
  504. // bas droite
  505. new paper.Path.Line({
  506. from: [m, m],
  507. to: [n, n],
  508. style: style
  509. }),
  510. // bas gauche
  511. new paper.Path.Line({
  512. from: [-m, m],
  513. to: [-n, n],
  514. style: style
  515. }),
  516. // fleches
  517. // haut
  518. new paper.Path({
  519. segments: [
  520. [-2, -dr*1.5 - 2],
  521. [0, -dr*1.5],
  522. [-2, -dr*1.5 + 2]
  523. ],
  524. style: felchesstyle
  525. }),
  526. // bas
  527. new paper.Path({
  528. segments: [
  529. [2, dr*1.5 - 2],
  530. [0, dr*1.5],
  531. [2, dr*1.5 + 2]
  532. ],
  533. style: felchesstyle
  534. }),
  535. // gauche
  536. new paper.Path({
  537. segments: [
  538. [-dr*1.5 - 2, 2],
  539. [-dr*1.5, 0],
  540. [-dr*1.5 + 2, 2]
  541. ],
  542. style: felchesstyle
  543. }),
  544. // droite
  545. new paper.Path({
  546. segments: [
  547. [dr*1.5 - 2, -2],
  548. [dr*1.5, 0],
  549. [dr*1.5 + 2, -2]
  550. ],
  551. style: felchesstyle
  552. }),
  553. //
  554. // LEGENDES
  555. //
  556. // arc bas gauche 1
  557. new paper.Path.Arc({
  558. from: [-pcr, lar],
  559. through: [-p, o],
  560. to: [-q + pcr/2, q + pcr/2],
  561. style: legende_style
  562. }),
  563. // tiret
  564. new paper.Path.Line({
  565. from: [-p, o],
  566. to: [-p_t, o_t],
  567. style: legende_style
  568. }),
  569. //text
  570. new paper.PointText({
  571. point: [-p_t - 1, o_t],
  572. content: "Enquête menée\nsur le terrain de vie",
  573. fontSize: fontsize,
  574. fontFamily: fontFamily,
  575. justification: 'right'
  576. }),
  577. // arc bas gauche 2
  578. new paper.Path.Arc({
  579. from: [-q - pcr/2, q - pcr/2],
  580. through: [-o, p],
  581. to: [-lar, pcr],
  582. style: legende_style
  583. }),
  584. // tiret
  585. new paper.Path.Line({
  586. from: [-o, p],
  587. to: [-o_t, p_t],
  588. style: legende_style
  589. }),
  590. // texte
  591. new paper.PointText({
  592. point: [-o_t - 1, p_t],
  593. content: "Construction de groupes d'intérets\navec qui composer la doléance",
  594. fontSize: fontsize,
  595. fontFamily: fontFamily,
  596. justification: 'right'
  597. }),
  598. // arc haut gauche
  599. new paper.Path.Arc({
  600. from: [-lar, -pcr],
  601. through: [-q, -q],
  602. to: [-pcr, -lar],
  603. style: legende_style
  604. }),
  605. // tiret
  606. new paper.Path.Line({
  607. from: [-q, -q],
  608. to: [-q_t, -q_t],
  609. style: legende_style
  610. }),
  611. // texte
  612. new paper.PointText({
  613. point: [-q_t - 1, -q_t],
  614. content: "Réception et traitement\nde la doléance",
  615. fontSize: fontsize,
  616. fontFamily: fontFamily,
  617. justification: 'right'
  618. }),
  619. // arc haut droite
  620. new paper.Path.Arc({
  621. from: [pcr, -lar],
  622. through: [q, -q],
  623. to: [lar, -pcr],
  624. style: legende_style
  625. }),
  626. // tiret
  627. new paper.Path.Line({
  628. from: [q, -q],
  629. to: [q_t, -q_t],
  630. style: legende_style
  631. }),
  632. // texte
  633. new paper.PointText({
  634. point: [q_t + 1, -q_t],
  635. content: "Mise-en-œuvre\nde la décision",
  636. fontSize: fontsize,
  637. fontFamily: fontFamily,
  638. justification: 'left'
  639. }),
  640. // arc bas droite 1
  641. new paper.Path.Arc({
  642. from: [lar, pcr],
  643. through: [o, p],
  644. to: [q + pcr/2, q - pcr/2],
  645. style: legende_style
  646. }),
  647. // tiret
  648. new paper.Path.Line({
  649. from: [o, p],
  650. to: [o_t, p_t],
  651. style: legende_style
  652. }),
  653. // texte
  654. new paper.PointText({
  655. point: [o_t + 1, p_t],
  656. content: "Réception et application\nde la décision",
  657. fontSize: fontsize,
  658. fontFamily: fontFamily,
  659. justification: 'left'
  660. }),
  661. // arc bas droite 2
  662. new paper.Path.Arc({
  663. from: [q - pcr/2, q + pcr/2],
  664. through: [p, o],
  665. to: [pcr, lar],
  666. style: legende_style
  667. }),
  668. // tiret
  669. new paper.Path.Line({
  670. from: [p, o],
  671. to: [p_t, o_t],
  672. style: legende_style
  673. }),
  674. // texte
  675. new paper.PointText({
  676. point: [p_t + 1, o_t],
  677. content: "Réussite / échec / reprise\ndu cercle politique",
  678. fontSize: fontsize,
  679. fontFamily: fontFamily,
  680. justification: 'left'
  681. }),
  682. //
  683. // Points Cardinaux
  684. //
  685. // haut
  686. new paper.Path.Circle({
  687. center: [0, -r],
  688. radius: 0.5,
  689. style: {
  690. fillColor: '#000'
  691. }
  692. }),
  693. new paper.Path.Line({
  694. from: [0, -r],
  695. to: [0, -r - 9],
  696. style: legende_style
  697. }),
  698. new paper.PointText({
  699. point: [0, -r - 11],
  700. content: "Décision",
  701. fontSize: fontsize,
  702. fontFamily: fontFamily,
  703. justification: 'center'
  704. }),
  705. // bas
  706. new paper.Path.Circle({
  707. center: [0, r],
  708. radius: 0.5,
  709. style: {
  710. fillColor: '#000'
  711. }
  712. }),
  713. new paper.Path.Line({
  714. from: [0, r],
  715. to: [0, r + 9],
  716. style: legende_style
  717. }),
  718. new paper.PointText({
  719. point: [0, r + 14],
  720. content: "Début du cercle\nLe problème\n(injustice, indignation, plainte...)",
  721. fontSize: fontsize,
  722. fontFamily: fontFamily,
  723. justification: 'center'
  724. }),
  725. // droite
  726. new paper.Path.Circle({
  727. center: [r, 0],
  728. radius: 0.5,
  729. style: {
  730. fillColor: '#000'
  731. }
  732. }),
  733. new paper.Path.Line({
  734. from: [r, 0],
  735. to: [r + 8, 0],
  736. style: legende_style
  737. }),
  738. new paper.PointText({
  739. point: [r + 10, -0.5],
  740. content: "Adresse de la décision\nà appliquer",
  741. fontSize: fontsize,
  742. fontFamily: fontFamily,
  743. justification: 'left'
  744. }),
  745. // gauche
  746. new paper.Path.Circle({
  747. center: [-r, 0],
  748. radius: 0.5,
  749. style: {
  750. fillColor: '#000'
  751. }
  752. }),
  753. new paper.Path.Line({
  754. from: [-r, 0],
  755. to: [-r - 8, 0],
  756. style: legende_style
  757. }),
  758. new paper.PointText({
  759. point: [-r - 10, 0.4],
  760. content: "Adresse de la doléance",
  761. fontSize: fontsize,
  762. fontFamily: fontFamily,
  763. justification: 'right'
  764. }),
  765. ];
  766. return new paper.Group({
  767. children: children,
  768. pivot: new paper.Point(pos),
  769. name: 'doleance_bg',
  770. // locked: true
  771. });
  772. },
  773. setPaperDoleanceICONSymbol(){
  774. let children = [];
  775. let svgIcon = paper.project.importSVG(iconDoleancer);
  776. children.push(svgIcon);
  777. svgIcon.position = this.pos;
  778. return new paper.Group({
  779. children: children,
  780. pivot: new paper.Point(this.pos),
  781. name: 'doleance_icon',
  782. locked: true,
  783. style: {
  784. strokeColor: '#000',
  785. strokeWidth: 0.75,
  786. fillColor: null
  787. }
  788. });
  789. },
  790. setPaperEntiteSymbol(){
  791. return new paper.Path.Circle({
  792. pivot: new paper.Point({x:0,y:0}),
  793. center: [0,0],
  794. radius: 0.5, //0.3
  795. fillColor: '#000',
  796. strokeColor: 'rgba(255,255,255,0.05)',
  797. strokeWidth:2
  798. })
  799. },
  800. setPaperEntiteHoverSymbol(){
  801. return new paper.Path.Circle({
  802. pivot: new paper.Point({x:0,y:0}),
  803. center: [0,0],
  804. radius: 0.5,
  805. fillColor: '#01ffe2',
  806. strokeColor: 'rgba(255,255,255,0.05)',
  807. strokeWidth:2
  808. })
  809. },
  810. setPaperBesoinSymbol(){
  811. return new paper.Path({
  812. pivot: new paper.Point(this.pos),
  813. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  814. fillColor: '#000'
  815. })
  816. },
  817. setPaperBesoinHoverSymbol(){
  818. return new paper.Path({
  819. pivot: new paper.Point(this.pos),
  820. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  821. fillColor: '#01ffe2'
  822. })
  823. },
  824. setPaperReponseSymbol(){
  825. return new paper.Path({
  826. pivot: new paper.Point(this.pos),
  827. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  828. fillColor: '#eee',
  829. strokeColor: "#000",
  830. strokeWidth: 0.25,
  831. })
  832. },
  833. setPaperReponseHoverSymbol(){
  834. return new paper.Path({
  835. pivot: new paper.Point(this.pos),
  836. segments: [[0, -1],[1, 0],[0, 1],[-1, 0],[0, -1]],
  837. fillColor: '#eee',
  838. strokeColor: "#01ffe2",
  839. strokeWidth: 0.25,
  840. })
  841. }
  842. },
  843. beforeUpdate () {
  844. },
  845. components: {
  846. MapBackground,
  847. ConcernementMapPopup
  848. }
  849. }
  850. </script>
  851. <template>
  852. <div id="map-backgrounds">
  853. <MapBackground />
  854. </div>
  855. <div id="map-matter">
  856. <canvas ref="canvas-engine"></canvas>
  857. </div>
  858. <div id="map-concernements">
  859. <canvas ref="canvas-map"></canvas>
  860. <slot></slot>
  861. </div>
  862. <nav id="map-nav">
  863. <ul>
  864. <li>
  865. <a
  866. href="#terraindevie" @click="setMapMode('terraindevie')"
  867. >
  868. <span class="icon terraindevie"></span> terrain de vie
  869. </a>
  870. </li>
  871. <li>
  872. <a
  873. href="#proximite" @click="setMapMode('proximite')"
  874. :class="{ disabled: opened_concernement && !opened_concernement.has_proximite }"
  875. >
  876. <span class="icon proximite"></span> proximité
  877. </a>
  878. </li>
  879. <li>
  880. <a
  881. href="#superposition" @click="setMapMode('superposition')"
  882. :class="{ disabled: opened_concernement && !opened_concernement.has_superposition }"
  883. >
  884. <span class="icon superposition"></span> superposition
  885. </a>
  886. </li>
  887. <li>
  888. <a
  889. href="#puissancedagir" @click="setMapMode('puissancedagir')"
  890. :class="{ disabled: opened_concernement && !opened_concernement.has_puissancedagir }"
  891. >
  892. <span class="icon puissancedagir"></span> puissance d'agir
  893. </a>
  894. </li>
  895. <li>
  896. <a
  897. href="#action" @click="setMapMode('action')"
  898. :class="{ disabled: opened_concernement && !opened_concernement.has_agissantes }"
  899. >
  900. <span class="icon action"></span> action
  901. </a>
  902. </li>
  903. <li>
  904. <a
  905. href="#doleancer" @click="setMapMode('doleancer')"
  906. :class="{ disabled: opened_concernement && !opened_concernement.has_doleance }"
  907. >
  908. <span class="icon doleancer"></span> cercle politique
  909. </a>
  910. </li>
  911. </ul>
  912. </nav>
  913. <ConcernementMapPopup
  914. v-if="hover_elmt && hover_elmt.type !== 'doleance_step'"
  915. :infos="hover_elmt"
  916. />
  917. </template>
  918. <style lang="css" scoped>
  919. </style>