MapConcernements.vue 30 KB

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