1
0

ConcernementMapItem.vue 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979
  1. <script>
  2. // https://brm.io/matter-js/docs/classes/Engine.html
  3. // import {
  4. // // Engine,
  5. // // Render,
  6. // // World,
  7. // Bodies,
  8. // Body,
  9. // Events,
  10. // Composite,
  11. // // Composites,
  12. // // Constraint,
  13. // // Vertices,
  14. // // Mouse,
  15. // // MouseConstraint,
  16. // // Query,
  17. // // Common
  18. // } from "matter-js";
  19. import Matter from "matter-js";
  20. import MatterAttractors from "matter-attractors";
  21. // Matter.use(MatterAttractors);
  22. // import polydecomp from "poly-decomp";
  23. import paper from 'paper';
  24. // import { easeInOutQuad, easeInOutQuart } from 'easing-utils';
  25. import Tween from "@tweenjs/tween.js";
  26. import { mapState, mapActions } from 'pinia'
  27. import { ConcernementsStore } from '@/stores/concernements'
  28. import { CommonStore } from '@/stores/common'
  29. import iconAction from "@/assets/icons/action.svg"
  30. import iconDoleancer from "@/assets/icons/doleancer.svg"
  31. import iconProximite from "@/assets/icons/proximite.svg"
  32. import iconPuissanceagir from "@/assets/icons/puissancedagir.svg"
  33. import iconSuperposition from "@/assets/icons/superposition.svg"
  34. import iconTerraindevie from "@/assets/icons/terraindevie.svg"
  35. export default {
  36. inject: ['canvasMap', 'matterEngine'],
  37. data() {
  38. return {
  39. id: null,
  40. entities: null,
  41. canvas: null,
  42. ctx: null,
  43. pos : {
  44. x: 0,
  45. y: 0
  46. },
  47. ray: 100,
  48. time: 0,
  49. salientPoints: [],
  50. scale: 1,
  51. prev_scale: 1,
  52. opacity: 0,
  53. tween: null,
  54. body: null,
  55. body_parts: [],
  56. constraint: null,
  57. is_hover: false,
  58. //
  59. paper_objects: {}
  60. }
  61. },
  62. props: ['concernement', 'is_opened'],
  63. computed: {
  64. ...mapState(ConcernementsStore,['map_mode']),
  65. ...mapState(ConcernementsStore,['concernementsByID']),
  66. ...mapState(ConcernementsStore,['opened']),
  67. ...mapState(ConcernementsStore,['opened_entite_id']),
  68. ...mapState(CommonStore,['hover_elmt'])
  69. },
  70. created () {
  71. // console.log(`ConcernementsMapItem ${this.concernement.id} created`, this.canvasMap, this.matterEngine);
  72. this.id = this.concernement.id
  73. this.entites = this.concernement.entites
  74. this.entites_byid = this.concernement.entites_byid
  75. // console.log(`ConcernementsMapItem ${this.concernement.id} $route`, this.id, this.$route);
  76. // if (this.$route.name === 'concernement'
  77. // && parseInt(this.$route.params.id) === this.id
  78. // && typeof this.$route.params.eid !== "undefined") {
  79. // // console.log("we have an entity");
  80. // this.opened_entite_id = parseInt(this.$route.params.eid);
  81. // }
  82. // disable concernement if less than 3 entite
  83. if(this.entites.length < 3){
  84. this.hideShowConcernement(this.concernement.id, false);
  85. } else{
  86. this.parsePoints()
  87. // this.getSalientPoints()
  88. this.getJarvisEnvelopeConvexe()
  89. if (this.canvasMap) {
  90. this.initCanvasMap()
  91. }
  92. }
  93. // if (this.salientPoints.length > 3) { // do not build item if it doesn't get enougth salient points
  94. // } else {
  95. // this.hideShowConcernement(this.concernement.id, false);
  96. // }
  97. },
  98. // mounted() {
  99. // console.log(`ConcernementsMapItem ${this.concernement.id} mounted`, this.canvasMap.canvas);
  100. // },
  101. watch: {
  102. // canvasMap (n, o) {
  103. // console.log("concernementItem watch canvasMap", o, n);
  104. // }
  105. canvasMap: {
  106. handler (n, o){
  107. // console.log("concernementItem watch canvasMap.ctx", typeof this.canvas, o, n);
  108. if (!this.canvas) {
  109. this.initCanvasMap()
  110. }
  111. },
  112. deep: true
  113. },
  114. is_opened: {
  115. handler (n, o) {
  116. if(n){ // opened
  117. this.openClose(true);
  118. }else{ // closed
  119. this.openClose(false)
  120. }
  121. },
  122. deep: true
  123. },
  124. map_mode: {
  125. handler (n, o) {
  126. console.log('watch map_mode', o, n);
  127. if (n === 'terraindevie' && !this.opened) {
  128. this.applyShuffleForces(); // apply a little force to check the map when returning to terrain de vie
  129. }
  130. },
  131. deep: true
  132. },
  133. hover_elmt: {
  134. handler (n, o) {
  135. // console.log(`watch hover_elmt ${this.id}`, o, n);
  136. if (n && n.type === 'concernement' && n.id === this.id) {
  137. this.is_hover = true;
  138. } else {
  139. this.is_hover = false;
  140. }
  141. },
  142. deep: true
  143. }
  144. },
  145. methods: {
  146. ...mapActions(CommonStore,['setHoverElmt']),
  147. ...mapActions(ConcernementsStore,['openCloseConcernements']),
  148. ...mapActions(ConcernementsStore,['hideShowConcernement']),
  149. parsePoints (){
  150. // converts data (menace/maintien, actuel/future, prise) into atcual position x,y
  151. for (let i = 0; i < this.entites.length; i++) {
  152. let entite = this.entites[i]
  153. // console.log('entite', entite);
  154. this.entites[i].display = {
  155. alpha: null,
  156. ray: null
  157. }
  158. // RAYON
  159. // https://stackoverflow.com/questions/5731863/mapping-a-numeric-range-onto-another
  160. // slope = (output_end - output_start) / (input_end - input_start)
  161. // output = output_start + slope * (input - input_start)
  162. // from range 0 -> 100 to range 0 -> this.ray
  163. let init_max = 100
  164. let slope = this.ray / init_max
  165. this.entites[i].display.ray = slope * (init_max - entite.prise);
  166. // if (this.concernement.id === 28) {
  167. // console.log(`entity prise: ${entite.prise} | ray: ${this.entites[i].display.ray}`);
  168. // }
  169. // ANGLE
  170. // -90 <= mm <= 90
  171. if (entite.actuelfuture) {
  172. // future en haut : 180 <= a <= 360
  173. // from -90 -> 90 to range 180 -> 360
  174. this.entites[i].display.alpha = entite.menacemaintien + 270
  175. } else {
  176. // actuel: en bas : O <= a <= 180
  177. // from -90 -> 90 to range 180 -> 0
  178. this.entites[i].display.alpha = -1 * entite.menacemaintien + 90
  179. }
  180. // POSITION X Y (par rapport au centre du concernement)
  181. this.entites[i].display.pos = {
  182. x: this.entites[i].display.ray * Math.cos(this.entites[i].display.alpha * (Math.PI/180)),
  183. y: this.entites[i].display.ray * Math.sin(this.entites[i].display.alpha * (Math.PI/180))
  184. }
  185. this.entites_byid[entite.entite.id].display = this.entites[i].display;
  186. }
  187. },
  188. getSalientPoints_OLD() {
  189. // debugger
  190. // console.log(this.entites);
  191. let arc = 360/30;
  192. // loop through arcs
  193. // for (let i = 360/arc; i >= 0 ; i--) {
  194. for (let i = 0; i <= 360/arc ; i++) {
  195. // loop through entities to find the farest on the arc
  196. let max_r = 0;
  197. let farest = null;
  198. for (let j = 0; j < this.entites.length; j++) {
  199. let entite = this.entites[j];
  200. if(arc*i <= entite.display.alpha && entite.display.alpha <= arc*i+arc) { // if entity is in arc
  201. if (entite.display.ray > max_r) { // && entite.display.ray > this.ray/2 // and farest from minimu
  202. // if entity is farest from precedent one
  203. max_r = entite.display.ray;
  204. // recalcul x & y to get a little padding between entite and contour by increasing ray
  205. farest = {
  206. alpha: entite.display.alpha,
  207. ray: entite.display.ray,
  208. pos: {
  209. x: (entite.display.ray + 3) * Math.cos(entite.display.alpha * (Math.PI/180)),
  210. y: (entite.display.ray + 3) * Math.sin(entite.display.alpha * (Math.PI/180))
  211. }
  212. };
  213. }
  214. }
  215. }
  216. if (farest) {
  217. this.salientPoints.push(farest)
  218. }
  219. }
  220. // console.log(`this.salientPoints ${this.concernement.id}`, this.salientPoints);
  221. },
  222. getJarvisEnvelopeConvexe(){
  223. console.log(`getJarvisEnvelopeConvexe ${this.id}`, this.entites.length);
  224. // https://www.geeksforgeeks.org/convex-hull-using-jarvis-algorithm-or-wrapping/
  225. // the most left point
  226. let l, min_x = null;
  227. for (let i = 0; i < this.entites.length; i++) {
  228. let entite = this.entites[i];
  229. let x = entite.display.ray * Math.cos(entite.display.alpha * (Math.PI/180));
  230. if(!min_x || min_x > x){
  231. l = i;
  232. min_x = x;
  233. }
  234. }
  235. let p = l, q;
  236. do {
  237. console.log(`do while ${this.id}`, p);
  238. // Add current point to result
  239. let entite = this.entites[p];
  240. let farest = {
  241. alpha: entite.display.alpha,
  242. ray: entite.display.ray,
  243. pos: {
  244. x: (entite.display.ray) * Math.cos(entite.display.alpha * (Math.PI/180)),
  245. y: (entite.display.ray) * Math.sin(entite.display.alpha * (Math.PI/180))
  246. }
  247. };
  248. this.salientPoints.push(farest);
  249. // Search for a point 'q' such that
  250. // orientation(p, q, x) is counterclockwise
  251. // for all points 'x'. The idea is to keep
  252. // track of last visited most counterclock-
  253. // wise point in q. If any point 'i' is more
  254. // counterclock-wise than q, then update q.
  255. q = (p + 1) % this.entites.length;
  256. for (let i = 0; i < this.entites.length; i++) {
  257. let p_x = (this.entites[p].display.ray + 3) * Math.cos(this.entites[p].display.alpha * (Math.PI/180));
  258. let p_y = (this.entites[p].display.ray + 3) * Math.sin(this.entites[p].display.alpha * (Math.PI/180));
  259. let i_x = (this.entites[i].display.ray + 3) * Math.cos(this.entites[i].display.alpha * (Math.PI/180));
  260. let i_y = (this.entites[i].display.ray + 3) * Math.sin(this.entites[i].display.alpha * (Math.PI/180));
  261. let q_x = (this.entites[q].display.ray + 3) * Math.cos(this.entites[q].display.alpha * (Math.PI/180));
  262. let q_y = (this.entites[q].display.ray + 3) * Math.sin(this.entites[q].display.alpha * (Math.PI/180));
  263. let val = (i_y - p_y) * (q_x - i_x) - (i_x - p_x) * (q_y - i_y);
  264. // If i is more counterclockwise than current q, then update q
  265. if (val > 0){
  266. q = i;
  267. }
  268. }
  269. // Now q is the most counterclockwise with
  270. // respect to p. Set p as q for next iteration,
  271. // so that q is added to result 'hull'
  272. p = q;
  273. } while (p != l);
  274. },
  275. initCanvasMap (){
  276. // console.log(`ConcernementsMapItem ${this.concernement.id} initCanvasMap`);
  277. // record canvas and ctx for rendering (drawing)
  278. this.canvas = this.canvasMap.canvas
  279. this.ctx = this.canvasMap.ctx
  280. // this.paper = this.canvasMap.paper
  281. // define init position of the item
  282. this.pos = this.getRandomPos();
  283. //
  284. this.initMatterBody()
  285. //
  286. this.initPaperObjects()
  287. },
  288. getRandomPos(){
  289. let pad = 200;
  290. return {
  291. x: pad + this.ray/2 + Math.random()*(this.canvas.width - this.ray - pad),
  292. y: pad + this.ray/2 + Math.random()*(this.canvas.height - this.ray - pad)
  293. };
  294. },
  295. initMatterBody (){
  296. // MATTER
  297. // create the matter body and add it to the engine
  298. if (!this.body) {
  299. // console.log('concernementItem creating body');
  300. // https://github.com/liabru/matter-attractors/issues/8
  301. // https://github.com/liabru/matter-attractors/blob/master/index.js
  302. // MatterAttractors.Attractors.gravityConstant = -5;
  303. // Create parts of the body : main big circle & entities
  304. this.body_parts = [
  305. Matter.Bodies.circle(0, 0, this.ray, {
  306. item_type: 'concernement',
  307. id: this.concernement.id,
  308. })
  309. ];
  310. // Create parts of the body : entities
  311. for (let i = 0; i < this.entites.length; i++) {
  312. // parts.push(Matter.Bodies.circle(this.pos.x+this.entites[i].display.pos.x, this.pos.y+this.entites[i].display.pos.y, 15, {
  313. // item_type: 'entite',
  314. // id: this.entites[i].id
  315. // }))
  316. this.body_parts.push(Matter.Bodies.circle(this.entites[i].display.pos.x, this.entites[i].display.pos.y, 0.8, {
  317. item_type: 'entite',
  318. id: this.entites[i].entite.id,
  319. cid: this.concernement.id,
  320. agissante: this.entites[i].entite.agissante,
  321. isSensor: true
  322. }))
  323. }
  324. // Create parts of the body : besoins and responses
  325. this.createBesoinsBodyParts();
  326. // create the body
  327. this.body = Matter.Body.create({
  328. parts: this.body_parts,
  329. item_type: 'concernement',
  330. id: this.concernement.id,
  331. frictionAir: 0,
  332. // mass: Math.pow(3, this.entites.length),
  333. mass: 10,
  334. restitution: 0.15,
  335. collisionFilter: {
  336. group: -1
  337. },
  338. plugin: {
  339. attractors: [
  340. // there is a built in helper function for Newtonian gravity!
  341. // you can find out how it works in index.js
  342. MatterAttractors.Attractors.gravity
  343. ]
  344. }
  345. });
  346. Matter.Body.setPosition(this.body, this.pos);
  347. // add init velocity
  348. this.setInitBodyVelocity()
  349. // console.log('concernementItem mass', this.body.mass);
  350. Matter.Composite.add(this.matterEngine.world, this.body);
  351. // console.log('concernement body', this.body);
  352. // // listen for animate event dispatched from parent
  353. // this.canvas.addEventListener('animate', this.animate)
  354. // listen for afterUpdate event from Matter.Engine object
  355. Matter.Events.on(this.matterEngine, "beforeUpdate", this.onBeforeEngineUpdate);
  356. Matter.Events.on(this.matterEngine, "afterUpdate", this.onAfterEngineUpdate);
  357. }
  358. },
  359. setInitBodyVelocity(){
  360. let delta = 10;
  361. Matter.Body.setVelocity(this.body, {
  362. x: -delta + Math.random()*delta*2,
  363. y: -delta + Math.random()*delta*2
  364. });
  365. },
  366. createBesoinsBodyParts(){
  367. let res_fields = ['qui','quoi','ou','avec'];
  368. let arc = (360 / 16); // unit arc
  369. let r = (this.ray * this.scale)/5; // unit ray
  370. let br = r - r/3; // besoin ray
  371. for (let i = 0; i < this.concernement.besoins.length; i++) {
  372. let start_a = arc * i; // angle depart (for reponses)
  373. let center_a = start_a + arc/2; // angle central
  374. let x = Math.cos(center_a*(Math.PI/180)) * br;
  375. let y = Math.sin(center_a*(Math.PI/180)) * br;
  376. this.body_parts.push(Matter.Bodies.circle(x, y, 0.8, {
  377. item_type: 'besoin',
  378. id: this.concernement.besoins[i].id,
  379. cid: this.concernement.id,
  380. isSensor: true
  381. }));
  382. let res_arc = arc / (1 + this.concernement.besoins[i].reponses.length); // unit arc for responses depending responses number
  383. for (let j = 0; j < this.concernement.besoins[i].reponses.length; j++) {
  384. let res_a = start_a + res_arc * (j+1); // angle for response line
  385. for (let f = 0; f < res_fields.length; f++) { // loop through all 4 fields, keep only the last one filled
  386. if( this.concernement.besoins[i].reponses[j][res_fields[f]] // if field filled
  387. && (f === res_fields.length -1 || !this.concernement.besoins[i].reponses[j][res_fields[f+1]]) // and is last field or last field filled
  388. ){
  389. let rr = this.ray * this.scale - r*f - r/2; // reponse field ray
  390. let rx = Math.cos(res_a*(Math.PI/180)) * rr;
  391. let ry = Math.sin(res_a*(Math.PI/180)) * rr;
  392. this.body_parts.push(Matter.Bodies.circle(rx, ry, 0.8, {
  393. item_type: 'reponse',
  394. // field: res_fields[f],
  395. id: this.concernement.besoins[i].reponses[j].id,
  396. bid: this.concernement.besoins[i].id,
  397. cid: this.concernement.id,
  398. isSensor: true
  399. }));
  400. }
  401. }
  402. }
  403. }
  404. },
  405. // PAPER OBJECTS
  406. initPaperObjects(){
  407. this.paper_objects = new paper.Group({
  408. pivot: new paper.Point(this.pos),
  409. cid: this.id
  410. });
  411. this.paper_objects.addChild(this.setPaperBoussoleBG());
  412. this.paper_objects.addChild(this.setPaperContour());
  413. this.paper_objects.addChild(this.setPaperEntites());
  414. if (this.concernement.has_puissancedagir) {
  415. this.paper_objects.addChild(this.setPaperPuissanceagirBG());
  416. this.paper_objects.addChild(this.setPaperPuissanceagirICON());
  417. this.paper_objects.addChild(this.setPaperPuissanceagirBesoins());
  418. }
  419. if (this.concernement.has_agissantes) {
  420. this.paper_objects.addChild(this.setPaperAgissantes());
  421. }
  422. if (this.concernement.has_doleance) {
  423. this.paper_objects.addChild(this.setPaperDoleanceBG());
  424. this.paper_objects.addChild(this.setPaperDoleanceICON());
  425. this.paper_objects.addChild(this.setPaperDoleanceSteps());
  426. }
  427. console.log(`initPaperObjects ${this.id}`, this.paper_objects);
  428. this.initPaperEvents()
  429. },
  430. setPaperBoussoleBG(){
  431. // BOUSSOLE
  432. let children = [];
  433. let ray = this.ray*0.92*this.scale;
  434. // // // exterieur circle
  435. // children.push(new paper.Path.Circle({
  436. // center: [this.pos.x, this.pos.y],
  437. // radius: ray,
  438. // strokeWidth: 2
  439. // }));
  440. // // interieur circle
  441. // children.push(new paper.Path.Circle({
  442. // center: [this.pos.x, this.pos.y],
  443. // radius: this.ray/2*this.scale,
  444. // strokeWidth: 2
  445. // }));
  446. // cercles pointillés
  447. for (let i = 1; i < 9; i++) {
  448. let sw = i === 4 || i === 8 ? 2 : 1;
  449. let da = i === 4 || i === 8 ? null : [5,5];
  450. children.push(new paper.Path.Circle({
  451. center: [this.pos.x, this.pos.y],
  452. radius: ray/8*i,
  453. strokeColor: '#fff',
  454. strokeWidth: sw,
  455. dashArray: da
  456. }));
  457. }
  458. // axes
  459. // vertical
  460. children.push(new paper.Path.Line({
  461. from: [this.pos.x, this.pos.y - ray],
  462. to: [this.pos.x, this.pos.y + ray],
  463. strokeColor: '#fff',
  464. strokeWidth: 2
  465. }));
  466. // horizontal
  467. children.push(new paper.Path.Line({
  468. from: [this.pos.x - ray, this.pos.y],
  469. to: [this.pos.x + ray, this.pos.y],
  470. strokeColor: '#fff',
  471. strokeWidth: 2
  472. }))
  473. // fleches
  474. // haute
  475. children.push(new paper.Path({
  476. segments: [
  477. [this.pos.x - (8*this.scale), this.pos.y - ray + (8*this.scale)],
  478. [this.pos.x, this.pos.y - ray],
  479. [this.pos.x + (8*this.scale), this.pos.y - ray + (8*this.scale)],
  480. ],
  481. strokeWidth: 2,
  482. strokeColor: '#fff',
  483. }));
  484. // milieu
  485. children.push(new paper.Path({
  486. segments: [
  487. [this.pos.x - (8*this.scale), this.pos.y + (8*this.scale)],
  488. [this.pos.x, this.pos.y],
  489. [this.pos.x + (8*this.scale), this.pos.y + (8*this.scale)],
  490. ],
  491. strokeWidth: 2,
  492. strokeColor: '#fff',
  493. }));
  494. // MOINS - PLUS
  495. // PLUS
  496. // horizontal
  497. children.push(new paper.Path.Line({
  498. from: [this.pos.x + ray - (5 * this.scale), this.pos.y - ray],
  499. to: [this.pos.x + ray + (5 * this.scale), this.pos.y - ray],
  500. strokeWidth: 8,
  501. strokeColor: '#fff',
  502. }))
  503. // vertical
  504. children.push(new paper.Path.Line({
  505. from: [this.pos.x + ray, this.pos.y - ray - (5 * this.scale)],
  506. to: [this.pos.x + ray, this.pos.y - ray + (5 * this.scale)],
  507. strokeWidth: 8,
  508. strokeColor: '#fff',
  509. }))
  510. // MOINS
  511. // horizontal
  512. children.push(new paper.Path.Line({
  513. from: [this.pos.x - ray - (5 * this.scale), this.pos.y - ray],
  514. to: [this.pos.x - ray + (5 * this.scale), this.pos.y - ray],
  515. strokeWidth: 8,
  516. strokeColor: '#fff',
  517. }))
  518. let fontsize = 4;
  519. children.push(new paper.PointText({
  520. point: [this.pos.x + 4.5, this.pos.y - ray - 5],
  521. content: `entités qui menacent \u2194 entités qui maintiennent`,
  522. fontSize: fontsize,
  523. justification: 'center',
  524. fillColor: '#000',
  525. }))
  526. children.push(new paper.PointText({
  527. point: [this.pos.x - ray - 5, this.pos.y + 1],
  528. content: "axe d'intensité",
  529. fontSize: fontsize,
  530. justification: 'right',
  531. fillColor: '#000',
  532. }))
  533. children.push(new paper.PointText({
  534. point: [this.pos.x + ray + 5, this.pos.y - 4],
  535. content: "situation future",
  536. fontSize: fontsize,
  537. justification: 'left',
  538. fillColor: '#000',
  539. }))
  540. children.push(new paper.PointText({
  541. point: [this.pos.x + ray + 5, this.pos.y + 6],
  542. content: "situation actuelle",
  543. fontSize: fontsize,
  544. justification: 'left',
  545. fillColor: '#000',
  546. }))
  547. let t1 = new paper.PointText({
  548. point: [this.pos.x - ray/8*2.3, this.pos.y - ray/8*2.3],
  549. content: "avec prise",
  550. fontSize: fontsize,
  551. justification: 'center',
  552. fillColor: '#000',
  553. })
  554. t1.rotate(-45)
  555. children.push(t1)
  556. let t2 = new paper.PointText({
  557. point: [this.pos.x - ray/8*2.95, this.pos.y - ray/8*2.95],
  558. content: "sans prise",
  559. fontSize: fontsize,
  560. justification: 'center',
  561. fillColor: '#000',
  562. })
  563. t2.rotate(-45)
  564. children.push(t2)
  565. return new paper.Group({
  566. children: children,
  567. pivot: new paper.Point(this.pos),
  568. name: 'boussole_bg',
  569. locked: true,
  570. });
  571. },
  572. setPaperContour(){
  573. let getPaddedRoundedSegments = (b,a,c) => {
  574. const ac = { x: c.x - a.x, y: c.y - a.y } // get ac vecteur
  575. const lac = Math.sqrt(Math.pow(ac.x, 2) + Math.pow(ac.y, 2)); // get ac longueur ac
  576. const ab = { x: b.x - a.x, y: b.y - a.y } // get ab vecteur
  577. const lab = Math.sqrt(Math.pow(ab.x, 2) + Math.pow(ab.y, 2)); // get ab longeur
  578. const vab = { x: ab.x/lab, y: ab.y/lab } // get unit vecteur ab
  579. const an = { x: vab.x*lac, y: vab.y*lac } // get an vecteur
  580. const n = { x: a.x + an.x, y: a.y+an.y } // get n point
  581. const m = { x: (c.x + n.x)/2, y: (c.y + n.y)/2 } // get nc midle point
  582. const ma = { x:a.x - m.x, y: a.y - m.y } // get ma vecteur
  583. const lma = Math.sqrt(Math.pow(ma.x, 2)+Math.pow(ma.y, 2)) // get longeur m->a
  584. const vma = { x: ma.x/lma, y: ma.y / lma } // get ma vecteur unitaire
  585. const pad = 4; // exterior padding
  586. // the final padded point
  587. const pa = [
  588. this.pos.x+(a.x+vma.x*pad)*this.scale,
  589. this.pos.y+(a.y+vma.y*pad)*this.scale
  590. ]
  591. // handles
  592. const delta = 0.25;
  593. // handle IN
  594. const hli = Math.abs(lab)*delta; // handle longeur
  595. const vnai = { x: -vma.y, y: vma.x } // get the ma normal unit vector IN
  596. const hai = [ vnai.x*hli, vnai.y*hli ]; // get the handleIn point
  597. // handle OUT
  598. const hlo = Math.abs(lac)*delta; // handle longeur
  599. const vnao = { x: vma.y, y: -vma.x } // get the ma normal vector Out
  600. const hao = [ vnao.x*hlo, vnao.y*hlo ]; // get the handleOut point
  601. return new paper.Segment({
  602. point: pa,
  603. // handleIn: hai,
  604. // handleOut: hao
  605. })
  606. }
  607. const first_point = getPaddedRoundedSegments(
  608. this.salientPoints[this.salientPoints.length-1].pos,
  609. this.salientPoints[0].pos,
  610. this.salientPoints[1].pos
  611. );
  612. let segments = [first_point];
  613. for (let j = 1; j < this.salientPoints.length-1; j++) {
  614. // segments.push([this.pos.x+this.salientPoints[j].pos.x*this.scale*gap, this.pos.y+this.salientPoints[j].pos.y*this.scale*gap])
  615. segments.push(getPaddedRoundedSegments(
  616. this.salientPoints[j-1].pos,
  617. this.salientPoints[j].pos,
  618. this.salientPoints[j+1].pos,
  619. ))
  620. }
  621. const last_point = getPaddedRoundedSegments(
  622. this.salientPoints[this.salientPoints.length-2].pos,
  623. this.salientPoints[this.salientPoints.length-1].pos,
  624. this.salientPoints[0].pos
  625. );
  626. segments.push(last_point)
  627. segments.push(first_point)
  628. const contrs = new paper.Path({
  629. name: 'contours',
  630. segments: segments,
  631. fillColor: 'rgba(255,255,255,0.4)',
  632. // selected: true,
  633. strokeColor: '#fff',
  634. strokeWidth: 1,
  635. pivot: new paper.Point(this.pos),
  636. cid: this.id
  637. });
  638. // contrs.segments[0].selected = true;
  639. // contrs.segments[1].selected = true;
  640. return contrs;
  641. },
  642. setPaperEntites(){
  643. let g = new paper.Group({
  644. pivot: new paper.Point(this.pos),
  645. name: 'entites'
  646. });
  647. for (let i = 0; i < this.body.parts.length; i++) {
  648. if (this.body.parts[i].item_type === 'entite') {
  649. let part = this.body.parts[i];
  650. g.addChild(new paper.Path.Circle({
  651. center: [part.position.x, part.position.y],
  652. radius: 0.5, //0.3
  653. fillColor: '#000',
  654. item_id: part.id,
  655. item_type: 'entite'
  656. }))
  657. }
  658. }
  659. return g;
  660. },
  661. setPaperPuissanceagirBG(){
  662. let children = [];
  663. for (let i = 1; i < 6; i++) {
  664. children.push(new paper.Path.Circle({
  665. center: [this.pos.x, this.pos.y],
  666. radius: ((this.ray*this.scale)/5)*i,
  667. strokeWidth: 0.5
  668. }));
  669. }
  670. for (let j = 0; j < 4; j++) {
  671. let a = (90 / 4) * j;
  672. // diagonale
  673. // https://fr.wikipedia.org/wiki/Trigonom%C3%A9trie#/media/Fichier:Unit_circle_angles_color.svg
  674. // https://fr.wikipedia.org/wiki/Identit%C3%A9_trigonom%C3%A9trique_pythagoricienne#Preuve_utilisant_le_cercle_unit%C3%A9
  675. // radians = degrees * (pi/180)
  676. // degrees = radians * (180/pi)
  677. let x = Math.cos(a*(Math.PI/180)) * this.ray * this.scale;
  678. let y = Math.sin(a*(Math.PI/180)) * this.ray * this.scale;
  679. children.push(new paper.Path.Line({
  680. from: [this.pos.x + x, this.pos.y + y],
  681. to: [this.pos.x - x, this.pos.y - y],
  682. strokeWidth: 1,
  683. dashArray: [5,5]
  684. }))
  685. children.push(new paper.Path.Line({
  686. from: [this.pos.x - y, this.pos.y + x],
  687. to: [this.pos.x + y, this.pos.y - x],
  688. strokeWidth: 1,
  689. dashArray: [5,5]
  690. }))
  691. }
  692. children.push(new paper.Path.Circle({
  693. center: [this.pos.x, this.pos.y],
  694. radius: this.ray*this.scale,
  695. strokeWidth: 2,
  696. fillColor: `rgba(255,255,255,0.6)`
  697. }));
  698. return new paper.Group({
  699. children: children,
  700. pivot: new paper.Point(this.pos),
  701. name: 'puissanceagir_bg',
  702. // locked: true,
  703. style: {
  704. strokeColor: '#fff'
  705. }
  706. });
  707. },
  708. setPaperPuissanceagirICON(){
  709. let children = [];
  710. let svgIcon = paper.project.importSVG(iconPuissanceagir);
  711. children.push(svgIcon);
  712. svgIcon.position = this.pos;
  713. return new paper.Group({
  714. children: children,
  715. pivot: new paper.Point(this.pos),
  716. name: 'puissanceagir_icon',
  717. locked: true,
  718. style: {
  719. strokeColor: '#000',
  720. strokeWidth: 1,
  721. fillColor: null
  722. }
  723. });
  724. },
  725. setPaperPuissanceagirBesoins(){
  726. let g = new paper.Group({
  727. pivot: new paper.Point(this.pos),
  728. name: 'puissanceagir_besoins'
  729. });
  730. for (let i = 0; i < this.body.parts.length; i++) {
  731. if (this.body.parts[i].item_type === 'besoin' || this.body.parts[i].item_type === 'reponse') {
  732. let part = this.body.parts[i];
  733. switch (part.item_type) {
  734. case 'besoin':
  735. g.addChild(
  736. new paper.Path({
  737. segments: this.getDiamondSegments(part.position.x, part.position.y, 1),
  738. fillColor: '#000',
  739. pivot: new paper.Point(this.pos),
  740. item_id: part.id,
  741. item_type: 'besoin'
  742. })
  743. )
  744. break;
  745. case 'reponse':
  746. g.addChild(
  747. new paper.Path({
  748. segments: this.getDiamondSegments(part.position.x, part.position.y, 1),
  749. fillColor: '#eee',
  750. strokeColor: "#000",
  751. strokeWidth: 1,
  752. pivot: new paper.Point(this.pos),
  753. item_id: part.id,
  754. item_bid: part.bid,
  755. item_cid: part.cid,
  756. item_type: 'reponse'
  757. })
  758. )
  759. break;
  760. }
  761. }
  762. }
  763. return g;
  764. },
  765. getDiamondSegments(x,y,r){
  766. return [
  767. [x, y - r],
  768. [x + r, y],
  769. [x, y + r],
  770. [x - r, y],
  771. [x, y - r]
  772. ];
  773. },
  774. setPaperAgissantes(){
  775. let g = new paper.Group({
  776. pivot: new paper.Point(this.pos),
  777. name: 'agissantes'
  778. });
  779. for (let i = 0; i < this.body.parts.length; i++) {
  780. if (this.body.parts[i].item_type === 'entite' && this.body.parts[i].agissante) {
  781. let part = this.body.parts[i];
  782. g.addChild(new paper.Path.Circle({
  783. center: [part.position.x, part.position.y],
  784. radius: 0.3, //0.3
  785. fillColor: '#000',
  786. strokeColor: '#000',
  787. strokeWidth: 3,
  788. item_id: part.id,
  789. item_type: 'entite'
  790. }))
  791. }
  792. }
  793. return g;
  794. },
  795. setPaperDoleanceBG(){
  796. var r = this.ray * this.scale * 0.8; // ray
  797. var dr = r/2; // demi ray
  798. var pcr = 2*this.scale; // petits cercle rayon
  799. // https://fr.wikipedia.org/wiki/Trigonom%C3%A9trie#/media/Fichier:Unit_circle_angles_color.svg
  800. // https://fr.wikipedia.org/wiki/Identit%C3%A9_trigonom%C3%A9trique_pythagoricienne#Preuve_utilisant_le_cercle_unit%C3%A9
  801. // radians = degrees * (pi/180)
  802. // degrees = radians * (180/pi)
  803. // Points for 45° axes
  804. let m = Math.sin(45*(Math.PI/180)) * r; // x = y for rayon
  805. let n = Math.sin(45*(Math.PI/180)) * r/2; // x = y for demi rayon
  806. // console.log('m', m);
  807. // points for legende arcs
  808. var lar = r*1.1; // legendes arcs rayon
  809. let o = Math.cos(22.5*(Math.PI/180)) * lar; // x @ 22.5° for legende arc rayon
  810. let p = Math.sin(22.5*(Math.PI/180)) * lar; // y @ 22.5° for legende arc rayon
  811. let q = Math.sin(45*(Math.PI/180)) * lar; // x = y @ 45° for legende arc rayon
  812. var ltr = lar + 4; // legendes texts rayon
  813. let o_t = Math.cos(22.5*(Math.PI/180)) * ltr; // x @ 22.5° for legende text rayon
  814. let p_t = Math.sin(22.5*(Math.PI/180)) * ltr; // y @ 22.5° for legende text rayon
  815. let q_t = Math.sin(45*(Math.PI/180)) * ltr; // x = y @ 45° for legende text rayon
  816. let style = {
  817. strokeColor: '#fff',
  818. strokeWidth: 1
  819. }
  820. let felchesstyle = {
  821. strokeColor: '#fff',
  822. strokeWidth: 2
  823. }
  824. let legende_style = {
  825. strokeColor: '#000',
  826. strokeWidth: 1
  827. }
  828. let fontsize = 4;
  829. let children = [
  830. // ARCS EXTERIEURS
  831. // haut gauche
  832. new paper.Path.Arc({
  833. from: [this.pos.x - r, this.pos.y - pcr],
  834. through: [this.pos.x - m, this.pos.y - m],
  835. to: [this.pos.x - pcr, this.pos.y - r],
  836. style: style
  837. }),
  838. // haut droite
  839. new paper.Path.Arc({
  840. from: [this.pos.x + pcr, this.pos.y - r],
  841. through: [this.pos.x + m, this.pos.y - m],
  842. to: [this.pos.x + r, this.pos.y - pcr],
  843. style: style
  844. }),
  845. // bas droite
  846. new paper.Path.Arc({
  847. from: [this.pos.x + r, this.pos.y + pcr],
  848. through: [this.pos.x + m, this.pos.y + m],
  849. to: [this.pos.x + pcr, this.pos.y + r],
  850. style: style
  851. }),
  852. // bas gauche
  853. new paper.Path.Arc({
  854. from: [this.pos.x - pcr, this.pos.y + r],
  855. through: [this.pos.x - m, this.pos.y + m],
  856. to: [this.pos.x - r, this.pos.y + pcr],
  857. style: style
  858. }),
  859. //
  860. // cercle interieur
  861. new paper.Path.Circle({
  862. center: [this.pos.x, this.pos.y],
  863. radius: dr,
  864. style: style
  865. }),
  866. //
  867. // petit cercles
  868. new paper.Path.Circle({
  869. center: [this.pos.x, this.pos.y -r],
  870. radius: pcr,
  871. style: style
  872. }),
  873. new paper.Path.Circle({
  874. center: [this.pos.x, this.pos.y + r],
  875. radius: pcr,
  876. style: style
  877. }),
  878. new paper.Path.Circle({
  879. center: [this.pos.x + r, this.pos.y],
  880. radius: pcr,
  881. style: style
  882. }),
  883. new paper.Path.Circle({
  884. center: [this.pos.x -r, this.pos.y],
  885. radius: pcr,
  886. style: style
  887. }),
  888. //
  889. // AXES
  890. // vertical haut
  891. new paper.Path.Line({
  892. from: [this.pos.x, this.pos.y - r + pcr],
  893. to: [this.pos.x , this.pos.y - dr],
  894. style: style
  895. }),
  896. // vertical bas
  897. new paper.Path.Line({
  898. from: [this.pos.x, this.pos.y + r - pcr],
  899. to: [this.pos.x , this.pos.y + dr],
  900. style: style
  901. }),
  902. // horizontal gauche
  903. new paper.Path.Line({
  904. from: [this.pos.x - r + pcr, this.pos.y],
  905. to: [this.pos.x - dr, this.pos.y],
  906. style: style
  907. }),
  908. // horizontal droite
  909. new paper.Path.Line({
  910. from: [this.pos.x + r - pcr, this.pos.y],
  911. to: [this.pos.x + dr, this.pos.y],
  912. style: style
  913. }),
  914. //
  915. // DIAGONALES
  916. // bas droite
  917. new paper.Path.Line({
  918. from: [this.pos.x + m, this.pos.y + m],
  919. to: [this.pos.x + n, this.pos.y + n],
  920. style: style
  921. }),
  922. // bas gauche
  923. new paper.Path.Line({
  924. from: [this.pos.x - m, this.pos.y + m],
  925. to: [this.pos.x - n, this.pos.y + n],
  926. style: style
  927. }),
  928. // // haut droite
  929. // new paper.Path.Line({
  930. // from: [this.pos.x + m, this.pos.y - m],
  931. // to: [this.pos.x + n, this.pos.y - n],
  932. // style: style
  933. // }),
  934. // // haut gauche
  935. // new paper.Path.Line({
  936. // from: [this.pos.x - m, this.pos.y - m],
  937. // to: [this.pos.x - n, this.pos.y - n],
  938. // style: style
  939. // }),
  940. // fleches
  941. // haut
  942. new paper.Path({
  943. segments: [
  944. [this.pos.x - 2, this.pos.y - dr*1.5 - 2],
  945. [this.pos.x, this.pos.y - dr*1.5],
  946. [this.pos.x - 2, this.pos.y - dr*1.5 + 2]
  947. ],
  948. style: felchesstyle
  949. }),
  950. // bas
  951. new paper.Path({
  952. segments: [
  953. [this.pos.x + 2, this.pos.y + dr*1.5 - 2],
  954. [this.pos.x, this.pos.y + dr*1.5],
  955. [this.pos.x + 2, this.pos.y + dr*1.5 + 2]
  956. ],
  957. style: felchesstyle
  958. }),
  959. // gauche
  960. new paper.Path({
  961. segments: [
  962. [this.pos.x - dr*1.5 - 2, this.pos.y + 2],
  963. [this.pos.x - dr*1.5, this.pos.y],
  964. [this.pos.x - dr*1.5 + 2, this.pos.y + 2]
  965. ],
  966. style: felchesstyle
  967. }),
  968. // droite
  969. new paper.Path({
  970. segments: [
  971. [this.pos.x + dr*1.5 - 2, this.pos.y - 2],
  972. [this.pos.x + dr*1.5, this.pos.y],
  973. [this.pos.x + dr*1.5 + 2, this.pos.y - 2]
  974. ],
  975. style: felchesstyle
  976. }),
  977. //
  978. // LEGENDES
  979. //
  980. // arc bas gauche 1
  981. new paper.Path.Arc({
  982. from: [this.pos.x - pcr, this.pos.y + lar],
  983. through: [this.pos.x - p, this.pos.y + o],
  984. to: [this.pos.x - q + pcr/2, this.pos.y + q + pcr/2],
  985. style: legende_style
  986. }),
  987. // tiret
  988. new paper.Path.Line({
  989. from: [this.pos.x - p, this.pos.y + o],
  990. to: [this.pos.x - p_t, this.pos.y + o_t],
  991. style: legende_style
  992. }),
  993. //text
  994. new paper.PointText({
  995. point: [this.pos.x - p_t - 1, this.pos.y + o_t],
  996. content: "Enquête menée\nsur le terrain de vie",
  997. fontSize: fontsize,
  998. justification: 'right'
  999. }),
  1000. // arc bas gauche 2
  1001. new paper.Path.Arc({
  1002. from: [this.pos.x - q - pcr/2, this.pos.y + q - pcr/2],
  1003. through: [this.pos.x - o, this.pos.y + p],
  1004. to: [this.pos.x - lar, this.pos.y + pcr],
  1005. style: legende_style
  1006. }),
  1007. // tiret
  1008. new paper.Path.Line({
  1009. from: [this.pos.x - o, this.pos.y + p],
  1010. to: [this.pos.x - o_t, this.pos.y + p_t],
  1011. style: legende_style
  1012. }),
  1013. // texte
  1014. new paper.PointText({
  1015. point: [this.pos.x - o_t - 1, this.pos.y + p_t],
  1016. content: "Construction de groupes d'intérets\navec qui composer la doléance",
  1017. fontSize: fontsize,
  1018. justification: 'right'
  1019. }),
  1020. // arc haut gauche
  1021. new paper.Path.Arc({
  1022. from: [this.pos.x - lar, this.pos.y - pcr],
  1023. through: [this.pos.x - q, this.pos.y - q],
  1024. to: [this.pos.x - pcr, this.pos.y - lar],
  1025. style: legende_style
  1026. }),
  1027. // tiret
  1028. new paper.Path.Line({
  1029. from: [this.pos.x - q, this.pos.y - q],
  1030. to: [this.pos.x - q_t, this.pos.y - q_t],
  1031. style: legende_style
  1032. }),
  1033. // texte
  1034. new paper.PointText({
  1035. point: [this.pos.x - q_t - 1, this.pos.y - q_t],
  1036. content: "Réception et traitement\nde la doléance",
  1037. fontSize: fontsize,
  1038. justification: 'right'
  1039. }),
  1040. // arc haut droite
  1041. new paper.Path.Arc({
  1042. from: [this.pos.x + pcr, this.pos.y - lar],
  1043. through: [this.pos.x + q, this.pos.y - q],
  1044. to: [this.pos.x + lar, this.pos.y - pcr],
  1045. style: legende_style
  1046. }),
  1047. // tiret
  1048. new paper.Path.Line({
  1049. from: [this.pos.x + q, this.pos.y - q],
  1050. to: [this.pos.x + q_t, this.pos.y - q_t],
  1051. style: legende_style
  1052. }),
  1053. // texte
  1054. new paper.PointText({
  1055. point: [this.pos.x + q_t + 1, this.pos.y - q_t],
  1056. content: "Mise-en-œuvre\nde la décision",
  1057. fontSize: fontsize,
  1058. justification: 'left'
  1059. }),
  1060. // arc bas droite 1
  1061. new paper.Path.Arc({
  1062. from: [this.pos.x + lar, this.pos.y + pcr],
  1063. through: [this.pos.x + o, this.pos.y + p],
  1064. to: [this.pos.x + q + pcr/2, this.pos.y + q - pcr/2],
  1065. style: legende_style
  1066. }),
  1067. // tiret
  1068. new paper.Path.Line({
  1069. from: [this.pos.x + o, this.pos.y + p],
  1070. to: [this.pos.x + o_t, this.pos.y + p_t],
  1071. style: legende_style
  1072. }),
  1073. // texte
  1074. new paper.PointText({
  1075. point: [this.pos.x + o_t + 1, this.pos.y + p_t],
  1076. content: "Réception et application\nde la décision",
  1077. fontSize: fontsize,
  1078. justification: 'left'
  1079. }),
  1080. // arc bas droite 2
  1081. new paper.Path.Arc({
  1082. from: [this.pos.x + q - pcr/2, this.pos.y + q + pcr/2],
  1083. through: [this.pos.x + p, this.pos.y + o],
  1084. to: [this.pos.x + pcr, this.pos.y + lar],
  1085. style: legende_style
  1086. }),
  1087. // tiret
  1088. new paper.Path.Line({
  1089. from: [this.pos.x + p, this.pos.y + o],
  1090. to: [this.pos.x + p_t, this.pos.y + o_t],
  1091. style: legende_style
  1092. }),
  1093. // texte
  1094. new paper.PointText({
  1095. point: [this.pos.x + p_t + 1, this.pos.y + o_t],
  1096. content: "Réussite / échec / reprise\ndu cercle politique",
  1097. fontSize: fontsize,
  1098. justification: 'left'
  1099. }),
  1100. //
  1101. // Points Cardinaux
  1102. //
  1103. // haut
  1104. new paper.Path.Circle({
  1105. center: [this.pos.x, this.pos.y -r],
  1106. radius: 0.5,
  1107. style: {
  1108. fillColor: '#000'
  1109. }
  1110. }),
  1111. new paper.Path.Line({
  1112. from: [this.pos.x, this.pos.y -r],
  1113. to: [this.pos.x, this.pos.y - r - 8],
  1114. style: legende_style
  1115. }),
  1116. new paper.PointText({
  1117. point: [this.pos.x, this.pos.y - r - 9],
  1118. content: "Décision",
  1119. fontSize: fontsize,
  1120. justification: 'center'
  1121. }),
  1122. // bas
  1123. // new paper.Path.Circle({
  1124. // center: [this.pos.x, this.pos.y + r],
  1125. // radius: 0.5,
  1126. // style: {
  1127. // fillColor: '#000'
  1128. // }
  1129. // }),
  1130. // new paper.Path.Line({
  1131. // from: [this.pos.x, this.pos.y + r],
  1132. // to: [this.pos.x, this.pos.y + r + 8],
  1133. // style: legende_style
  1134. // }),
  1135. // new paper.PointText({
  1136. // point: [this.pos.x, this.pos.y + r + 10],
  1137. // content: "Début du cercle\nLe problème\n(injustice, indignation, plainte...)",
  1138. // fontSize: fontsize,
  1139. // justification: 'center'
  1140. // }),
  1141. // droite
  1142. new paper.Path.Circle({
  1143. center: [this.pos.x + r, this.pos.y],
  1144. radius: 0.5,
  1145. style: {
  1146. fillColor: '#000'
  1147. }
  1148. }),
  1149. new paper.Path.Line({
  1150. from: [this.pos.x + r, this.pos.y],
  1151. to: [this.pos.x + r + 8, this.pos.y],
  1152. style: legende_style
  1153. }),
  1154. new paper.PointText({
  1155. point: [this.pos.x + r + 9, this.pos.y - 0.5],
  1156. content: "Adresse de la décision\nà appliquer",
  1157. fontSize: fontsize,
  1158. justification: 'left'
  1159. }),
  1160. // gauche
  1161. new paper.Path.Circle({
  1162. center: [this.pos.x -r, this.pos.y],
  1163. radius: 0.5,
  1164. style: {
  1165. fillColor: '#000'
  1166. }
  1167. }),
  1168. new paper.Path.Line({
  1169. from: [this.pos.x - r, this.pos.y],
  1170. to: [this.pos.x - r - 8, this.pos.y],
  1171. style: legende_style
  1172. }),
  1173. new paper.PointText({
  1174. point: [this.pos.x - r - 9, this.pos.y + 0.4],
  1175. content: "Adresse de la doléance",
  1176. fontSize: fontsize,
  1177. justification: 'right'
  1178. }),
  1179. ];
  1180. return new paper.Group({
  1181. children: children,
  1182. pivot: new paper.Point(this.pos),
  1183. name: 'doleance_bg',
  1184. locked: true
  1185. });
  1186. },
  1187. setPaperDoleanceICON(){
  1188. let children = [];
  1189. let svgIcon = paper.project.importSVG(iconDoleancer);
  1190. children.push(svgIcon);
  1191. svgIcon.position = this.pos;
  1192. return new paper.Group({
  1193. children: children,
  1194. pivot: new paper.Point(this.pos),
  1195. name: 'doleance_icon',
  1196. locked: true,
  1197. style: {
  1198. strokeColor: '#000',
  1199. strokeWidth: 1,
  1200. fillColor: null
  1201. }
  1202. });
  1203. },
  1204. setPaperDoleanceSteps(){
  1205. let g = new paper.Group({
  1206. pivot: new paper.Point(this.pos),
  1207. name: 'doleance_steps'
  1208. });
  1209. let doleance = this.concernement.doleances[0];
  1210. let all_fields = [
  1211. [
  1212. 'leprobleme',
  1213. 'lenquete',
  1214. {
  1215. fieldname: 'groupesinterets',
  1216. fields: [
  1217. 'groupe_interets',
  1218. 'accorder_interets',
  1219. 'formuler',
  1220. ]
  1221. }
  1222. ],
  1223. [
  1224. 'entite_addresse_doleance',
  1225. 'comment_ennonce_doleance',
  1226. 'aqui_addresse_doleance',
  1227. {
  1228. fieldname: 'reception_traitement',
  1229. fields: [
  1230. 'entite_adressee',
  1231. 'doleance_formulee',
  1232. 'traite_doleance',
  1233. 'entite_recoit_doleance',
  1234. ]
  1235. }
  1236. ],
  1237. [
  1238. 'entites_decisionnaires',
  1239. 'decision_formule',
  1240. {
  1241. fieldname: 'mise_en_oeuvre_decision',
  1242. fields: [
  1243. 'entite_adresse_decision',
  1244. 'formule_decision',
  1245. 'entite_metenoeuvre_decisio',
  1246. ]
  1247. }
  1248. ],
  1249. [
  1250. 'entite_adresse_application',
  1251. 'aqui_adresse_decision',
  1252. 'comment_formule_decision',
  1253. {
  1254. fieldname: 'receptions_et_applications',
  1255. fields: [
  1256. 'applique_decision',
  1257. 'formule_decision_applic',
  1258. 'entite_recoit_decision',
  1259. ]
  1260. },
  1261. 'probleme_initial_resolu',
  1262. 'oui_nouvelle_situation',
  1263. 'non_adresse_doleance',
  1264. ]
  1265. ];
  1266. var r = this.ray * this.scale * 0.8; // ray
  1267. var dr = r/2; // demi ray
  1268. var pcr = 2*this.scale; // petits cercle rayon
  1269. // https://fr.wikipedia.org/wiki/Trigonom%C3%A9trie#/media/Fichier:Unit_circle_angles_color.svg
  1270. // https://fr.wikipedia.org/wiki/Identit%C3%A9_trigonom%C3%A9trique_pythagoricienne#Preuve_utilisant_le_cercle_unit%C3%A9
  1271. // radians = degrees * (pi/180)
  1272. // degrees = radians * (180/pi)
  1273. // Points for 45° axes
  1274. let m = Math.sin(45*(Math.PI/180)) * r; // x = y for rayon
  1275. let n = Math.sin(45*(Math.PI/180)) * r/2; // x = y for demi rayon
  1276. let o = Math.cos(22.5*(Math.PI/180)) * r; // x @ 22.5° for rayon
  1277. let p = Math.sin(22.5*(Math.PI/180)) * r; // y @ 22.5° for rayon
  1278. let o_d = Math.cos(22.5*(Math.PI/180)) * r/2; // x @ 22.5° for demi rayon
  1279. let p_d = Math.sin(22.5*(Math.PI/180)) * r/2; // y @ 22.5° for demi rayon
  1280. let fontsize = 2.1;
  1281. //
  1282. // POINTS CARDINAUX
  1283. //
  1284. // le problème
  1285. //
  1286. g.addChild(new paper.Path.Circle({
  1287. center: [this.pos.x, this.pos.y + r],
  1288. radius: 0.5,
  1289. style: {
  1290. fillColor: '#fff'
  1291. }
  1292. }));
  1293. g.addChild(new paper.Path.Line({
  1294. from: [this.pos.x, this.pos.y + r],
  1295. to: [this.pos.x, this.pos.y + r + 8],
  1296. strokeColor: '#fff'
  1297. }));
  1298. g.addChild(new paper.PointText({
  1299. point: [this.pos.x, this.pos.y + r + 10],
  1300. content: "Début du cercle\nLe problème (injustice, indignation, plainte...)",
  1301. fontSize: fontsize,
  1302. fillColor: '#000',
  1303. justification: 'center'
  1304. }));
  1305. g.addChild(new paper.PointText({
  1306. point: [this.pos.x, this.pos.y + r + 16],
  1307. content: doleance['leprobleme'],
  1308. fontSize: 2.3,
  1309. fillColor: '#fff',
  1310. justification: 'center'
  1311. }));
  1312. //
  1313. // CAMENBERT STATIQUES
  1314. //
  1315. // l'enquete
  1316. //
  1317. // camenbert
  1318. let cam = new paper.Path({
  1319. strokeColor: '#fff',
  1320. strokeWidth: 2,
  1321. fillColor: "rgba(255, 255, 255, 0.4)",
  1322. item_type: 'doleance_step',
  1323. item_id: 'lenquete'
  1324. });
  1325. cam.add({x: this.pos.x , y: this.pos.y + dr});
  1326. cam.lineTo({x: this.pos.x, y: this.pos.y + r});
  1327. cam.arcTo({x: this.pos.x - p, y: this.pos.y + o}, {x: this.pos.x - m, y: this.pos.y + m});
  1328. cam.lineTo({x: this.pos.x - n, y: this.pos.y + n});
  1329. cam.arcTo({x: this.pos.x - p_d, y: this.pos.y + o_d}, {x: this.pos.x , y: this.pos.y + dr});
  1330. // texte
  1331. // enquete.addChild(new paper.PointText({
  1332. // point: {
  1333. // x:this.pos.x + Math.sin(22.5*(Math.PI/180)) * r*0.75,
  1334. // y:this.pos.y + Math.cos(22.5*(Math.PI/180)) * r*0.75
  1335. // },
  1336. // content: doleance['lenquete'],
  1337. // fontSize: fontsize,
  1338. // fillColor: '#fff',
  1339. // justification: 'center',
  1340. // locked: true
  1341. // }));
  1342. g.addChild(cam);
  1343. //
  1344. // probleme_initial_resolu
  1345. //
  1346. // camenbert
  1347. let rescam = new paper.Path({
  1348. strokeColor: '#fff',
  1349. strokeWidth: 2,
  1350. fillColor: "rgba(255, 255, 255, 0.4)",
  1351. closed: true,
  1352. item_type: 'doleance_step',
  1353. item_id: 'probleme_initial_resolu',
  1354. });
  1355. rescam.add({x: this.pos.x + n, y: this.pos.y + n});
  1356. rescam.lineTo({x: this.pos.x + m , y: this.pos.y + m});
  1357. rescam.arcTo({x: this.pos.x + p, y: this.pos.y + o}, {x: this.pos.x, y: this.pos.y + r});
  1358. rescam.lineTo({x: this.pos.x, y: this.pos.y + dr});
  1359. rescam.arcTo({x: this.pos.x + p_d, y: this.pos.y + o_d}, {x: this.pos.x + n, y: this.pos.y + n});
  1360. // texte
  1361. // resolution.addChild(new paper.PointText({
  1362. // point: {
  1363. // x:this.pos.x - Math.sin(22.5*(Math.PI/180)) * r*0.75,
  1364. // y:this.pos.y + Math.cos(22.5*(Math.PI/180)) * r*0.75
  1365. // },
  1366. // content: doleance['probleme_initial_resolu'] ? doleance['oui_nouvelle_situation'] : doleance['non_adresse_doleance'],
  1367. // fontSize: fontsize,
  1368. // fillColor: '#fff',
  1369. // justification: 'center'
  1370. // }));
  1371. g.addChild(rescam)
  1372. //
  1373. // MULTIPLE FIELDS
  1374. //
  1375. let multiple_fields = [
  1376. { field_name: 'groupesinterets', arc: 45, decalage: -45 },
  1377. { field_name: 'reception_traitement', arc: 90, decalage: -90 },
  1378. { field_name: 'mise_en_oeuvre_decision', arc: 90, decalage: -180 },
  1379. { field_name: 'receptions_et_applications', arc: 45, decalage: 90 }
  1380. ]
  1381. multiple_fields.forEach((mf, j) => {
  1382. for (let i = 0, l = doleance[mf.field_name].length, a = mf.arc/l; i < l; i++) {
  1383. // let gi = new paper.Group({
  1384. // item_type: 'doleance_step',
  1385. // item_id: 'lenquete',
  1386. // item_field: mf.field_name,
  1387. // item_index: i
  1388. // });
  1389. //camenbert
  1390. let x1= this.pos.x + Math.sin((mf.decalage- a*i)*(Math.PI/180)) * dr,
  1391. y1= this.pos.y + Math.cos((mf.decalage- a*i)*(Math.PI/180)) * dr;
  1392. let x2= this.pos.x + Math.sin((mf.decalage- a*i)*(Math.PI/180)) * r,
  1393. y2= this.pos.y + Math.cos((mf.decalage- a*i)*(Math.PI/180)) * r;
  1394. let x3= this.pos.x + Math.sin((mf.decalage- a*(i+1))*(Math.PI/180)) * r,
  1395. y3= this.pos.y + Math.cos((mf.decalage- a*(i+1))*(Math.PI/180)) * r;
  1396. let x3t= this.pos.x + Math.sin((mf.decalage- a*(i+0.5))*(Math.PI/180)) * r,
  1397. y3t= this.pos.y + Math.cos((mf.decalage- a*(i+0.5))*(Math.PI/180)) * r;
  1398. let x4= this.pos.x + Math.sin((mf.decalage- a*(i+1))*(Math.PI/180)) * dr,
  1399. y4= this.pos.y + Math.cos((mf.decalage- a*(i+1))*(Math.PI/180)) * dr;
  1400. let x4t= this.pos.x + Math.sin((mf.decalage- a*(i+0.5))*(Math.PI/180)) * dr,
  1401. y4t= this.pos.y + Math.cos((mf.decalage- a*(i+0.5))*(Math.PI/180)) * dr;
  1402. let x5= this.pos.x + Math.sin((mf.decalage- a*(i+0.5))*(Math.PI/180)) * r*0.75,
  1403. y5= this.pos.y + Math.cos((mf.decalage- a*(i+0.5))*(Math.PI/180)) * r*0.75;
  1404. let p = new paper.Path({
  1405. strokeColor: '#fff',
  1406. strokeWidth: 2,
  1407. fillColor: "rgba(255, 255, 255, 0.4)",
  1408. item_type: 'doleance_step',
  1409. item_id: `${mf.field_name}-${i}`,
  1410. item_field: mf.field_name
  1411. });
  1412. p.add([x1,y1]);
  1413. p.lineTo([x2,y2]);
  1414. p.arcTo([x3t,y3t], [x3,y3]);
  1415. p.lineTo([x4,y4]);
  1416. p.arcTo([x4t,y4t], [x1,y1]);
  1417. g.addChild(p);
  1418. // gi.addChild(p);
  1419. // // text
  1420. // gi.addChild(new paper.PointText({
  1421. // point: {x:x5,y:y5},
  1422. // content: `${j}-${i}`,
  1423. // fontSize: fontsize,
  1424. // fillColor: '#fff',
  1425. // justification: 'center'
  1426. // }))
  1427. // g.addChild(gi)
  1428. }
  1429. });
  1430. return g;
  1431. },
  1432. // PAPER EVENTS
  1433. initPaperEvents(){
  1434. this.paper_objects.onMouseEnter = function(event){
  1435. if (!this.opened && this.isFocused()) { // only if no concernement is opened and is this focused
  1436. this.setHoverElmt({
  1437. type: 'concernement',
  1438. id: this.id
  1439. });
  1440. document.body.style.cursor = "pointer";
  1441. }
  1442. }.bind(this);
  1443. this.paper_objects.onMouseLeave = function(event){
  1444. if (!this.opened && this.isFocused()) { // only if no concernement is opened
  1445. this.resetHoverElmt();
  1446. document.body.style.cursor = "auto";
  1447. }
  1448. }.bind(this);
  1449. this.paper_objects.onMouseMove = function(event){
  1450. // console.log(`onmousemove ${this.id}`);
  1451. // TODO besoins & actions & doleances
  1452. if (this.is_opened) {
  1453. // lets define some options regarding the map_mode
  1454. let paper_group_tohit;
  1455. switch (this.map_mode) {
  1456. case "terraindevie":
  1457. paper_group_tohit = 'entites';
  1458. break;
  1459. case "action":
  1460. paper_group_tohit = 'agissantes';
  1461. break;
  1462. case "puissancedagir":
  1463. paper_group_tohit = 'puissanceagir_besoins';
  1464. break;
  1465. case "doleancer":
  1466. paper_group_tohit = 'doleance_steps';
  1467. break;
  1468. }
  1469. let result = this.paper_objects.children[paper_group_tohit].hitTest(event.point);
  1470. // console.log('move result', result);
  1471. if (result && result.item.item_id) {
  1472. // console.log('move has result', result);
  1473. let new_hover_elmt = {
  1474. paper_id: result.item.id,
  1475. type: result.item.item_type,
  1476. id: result.item.item_id
  1477. };
  1478. switch (result.item.item_type) {
  1479. case "reponse":
  1480. new_hover_elmt.bid = result.item.item_bid;
  1481. new_hover_elmt.cid = result.item.item_cid;
  1482. break;
  1483. }
  1484. if (!this.hover_elmt || new_hover_elmt.paper_id !== this.hover_elmt.paper_id) {
  1485. // console.log(`before setHoverElmt ${this.id}`);
  1486. this.setHoverElmt(new_hover_elmt);
  1487. }
  1488. document.body.style.cursor = "pointer";
  1489. } else {
  1490. // console.log('move no result');
  1491. this.resetHoverElmt();
  1492. document.body.style.cursor = "auto";
  1493. }
  1494. }
  1495. }.bind(this);
  1496. this.paper_objects.onClick = function(event){
  1497. console.log('paper concernement onClick');
  1498. if (!this.is_opened) {
  1499. if (!this.opened) {
  1500. console.log(`Open me ${this.id}`);
  1501. // open/close all concernements
  1502. this.openCloseConcernements(this.id)
  1503. // push route (keep the hash for map_mode)
  1504. this.$router.push({
  1505. name: 'concernement',
  1506. hash: `#${this.map_mode}`,
  1507. params: {id: this.id}
  1508. });
  1509. // reset the mousehover
  1510. this.resetHoverElmt();
  1511. }
  1512. } else {
  1513. // lets define some options regarding the map_mode
  1514. // debugger;
  1515. let op = {pg: null};
  1516. switch (this.map_mode) {
  1517. case "terraindevie":
  1518. op = {
  1519. pg: 'entites', // paper group to hittest
  1520. }
  1521. break;
  1522. case "action":
  1523. op = {
  1524. pg: 'agissantes', // paper group to hittest
  1525. }
  1526. break;
  1527. }
  1528. if (op.pg) {
  1529. let result = this.paper_objects.children[op.pg].hitTest(event.point);
  1530. // console.log('click result', result);
  1531. if (result) {
  1532. // we have clicked on an entite
  1533. this.$router.push({
  1534. name: 'concernement',
  1535. hash: `#${this.map_mode}`,
  1536. params: {id: this.opened.id, eid: result.item.item_id}
  1537. });
  1538. } else {
  1539. // otherwise we close the entite and come back to the concernement
  1540. this.$router.push({
  1541. name: 'concernement',
  1542. hash: `#${this.map_mode}`,
  1543. params: {id: this.id}
  1544. });
  1545. // reset the mousehover
  1546. this.resetHoverElmt();
  1547. }
  1548. }
  1549. }
  1550. }.bind(this);
  1551. },
  1552. resetHoverElmt(){
  1553. // console.log('resetHoverElmt');
  1554. setTimeout(()=>{
  1555. this.setHoverElmt(null);
  1556. }, 100);
  1557. },
  1558. openClose(open) {
  1559. // console.log(`ConcernementsMapItem ${this.concernement.id} openClose: ${open}`);
  1560. if (this.tween) {
  1561. this.tween.stop();
  1562. }
  1563. if (open) {
  1564. // paper bring to front
  1565. this.paper_objects.bringToFront();
  1566. // calcul opened size regarding window size
  1567. // let ch = this.canvas.height;
  1568. let s = this.canvas.height / (this.ray*2.8)
  1569. // debugger;
  1570. // opening tweening
  1571. this.tween = new Tween.Tween({s: this.scale, x: this.pos.x, y: this.pos.y, o: 0})
  1572. .to({
  1573. s: s,
  1574. x: (this.canvas.width - 450) / 2,
  1575. y: this.canvas.height / 2,
  1576. o: 0.8
  1577. }, 800)
  1578. .onUpdate((obj) => {
  1579. // https://github.com/liabru/matter-js/issues/986#issuecomment-812488873
  1580. // revert to the original size (by reverting the previous scale)
  1581. Matter.Body.scale(this.body, 1 / this.scale, 1 / this.scale)
  1582. this.paper_objects.scale(1 / this.scale);
  1583. // then scale again to new scale
  1584. Matter.Body.scale(this.body, obj.s, obj.s)
  1585. this.paper_objects.scale(obj.s);
  1586. // record new scale
  1587. this.prev_scale = this.scale;
  1588. this.scale = obj.s;
  1589. this.opacity = obj.o;
  1590. Matter.Body.setPosition(this.body, {x:obj.x, y:obj.y});
  1591. this.pos = {x:obj.x, y:obj.y};
  1592. })
  1593. .onComplete((obj) => {
  1594. this.constraint = Matter.Constraint.create({
  1595. pointA: this.pos,
  1596. bodyB: this.body,
  1597. stiffness: 1,
  1598. damping: 0,
  1599. length: 0
  1600. });
  1601. Matter.Composite.add(this.matterEngine.world, [this.body, this.constraint]);
  1602. this.prev_scale = this.scale;
  1603. });
  1604. // recreate the matter engine event to get it a the end of the events stack
  1605. Matter.Events.off(this.matterEngine, "afterUpdate", this.onAfterEngineUpdate);
  1606. Matter.Events.on(this.matterEngine, "afterUpdate", this.onAfterEngineUpdate);
  1607. } else {
  1608. // closing
  1609. if(this.constraint){
  1610. Matter.Composite.remove(this.matterEngine.world, this.constraint);
  1611. }
  1612. this.tween = new Tween.Tween({s: this.scale, o: 1})
  1613. .to({s: 1, o: 0}, 500)
  1614. .onUpdate((obj) => {
  1615. // https://github.com/liabru/matter-js/issues/986#issuecomment-812488873
  1616. // revert to the original size (by reverting the previous scale)
  1617. Matter.Body.scale(this.body, 1 / this.scale, 1 / this.scale)
  1618. this.paper_objects.scale(1 / this.scale);
  1619. // then scale again to new scale
  1620. Matter.Body.scale(this.body, obj.s, obj.s)
  1621. this.paper_objects.scale(obj.s);
  1622. // record new scale
  1623. this.prev_scale = this.scale;
  1624. this.scale = obj.s;
  1625. this.opacity = obj.o;
  1626. })
  1627. .onComplete((obj) => {
  1628. this.prev_scale = this.scale = 1;
  1629. });
  1630. }
  1631. this.tween.easing(Tween.Easing.Quadratic.InOut).start();
  1632. },
  1633. // ENGINE UPDATE
  1634. onBeforeEngineUpdate (event) {
  1635. // update the opening/closing tweening
  1636. if (this.tween) {
  1637. this.tween.update();
  1638. }
  1639. if (this.opened) {
  1640. if (this.opened.id !== this.id) {
  1641. this.pushAside()
  1642. }
  1643. } else {
  1644. // apply focus forces : move unfocused on the sides and focused on the center
  1645. if (this.map_mode === 'action'
  1646. || this.map_mode === 'puissancedagir'
  1647. || this.map_mode === 'doleancer'){
  1648. this.applyFocusForces(); //
  1649. }
  1650. }
  1651. // reset all matter rotation forces otherwise items will spin when colide
  1652. Matter.Body.setAngle(this.body, 0);
  1653. Matter.Body.setAngularSpeed(this.body, 0);
  1654. },
  1655. applyFocusForces(){
  1656. if(!this.isFocused()) {
  1657. this.pushAside()
  1658. }else{
  1659. this.bringToCenter()
  1660. }
  1661. },
  1662. pushAside(){
  1663. // apply a force in direction of one side or an other depending of the start position
  1664. // the force is exponentialy proportional to the distance from the side
  1665. let dir = this.pos.x > this.canvas.width/2 ? 1 : -1; // get the direction to the closest side
  1666. let dist = (dir < 0 ? this.pos.x : this.canvas.width - this.pos.x); // get the distance from the side
  1667. let ori_pos = {x:this.canvas.width/2, y:this.body.position.y};
  1668. let x_force = Math.pow(dist/700,10) * dir;
  1669. Matter.Body.applyForce(
  1670. this.body,
  1671. ori_pos,
  1672. {
  1673. x: x_force,
  1674. y: 0
  1675. }
  1676. );
  1677. },
  1678. bringToCenter(){
  1679. // bring to the centre
  1680. let dir = this.pos.x > this.canvas.width/2 ? -1 : 1; // get the direction to the centre
  1681. let dist = (dir < 0 ? this.pos.x - this.canvas.width/2 : this.canvas.width/2 - this.pos.x); // get the distance from the side
  1682. let ori_pos = dir < 0 ? {x:this.canvas.width, y:this.body.position.y} : {x:0, y:this.body.position.y}
  1683. let x_force = Math.pow(dist/800,10) * dir;
  1684. this.body.frictionAir = 0.05;
  1685. Matter.Body.applyForce(
  1686. this.body,
  1687. ori_pos,
  1688. {
  1689. x: x_force,
  1690. y: 0
  1691. }
  1692. );
  1693. },
  1694. applyShuffleForces() {
  1695. var dist, dir, x_velocity;
  1696. dir = this.pos.x > this.canvas.width/2 ? -1 : 1; // get the direction to the centre
  1697. dist = (dir < 0 ? this.pos.x - this.canvas.width/2 : this.canvas.width/2 - this.pos.x); // get the distance from the side
  1698. x_velocity = Math.pow(dist/650,10) * dir;
  1699. Matter.Body.setVelocity(this.body, {x: x_velocity, y: 0});
  1700. },
  1701. onAfterEngineUpdate (event) {
  1702. // respawn element if outside screen
  1703. // if(this.pos.x < 0
  1704. // || this.pos.x > this.canvas.width
  1705. // || this.pos.y < 0
  1706. // || this.pos.y > this.canvas.height){
  1707. // this.pos = this.getRandomPos()
  1708. // Matter.Body.setPosition(this.body, {x:this.pos.x, y:this.pos.y});
  1709. // this.setInitBodyVelocity();
  1710. // }
  1711. this.paper_objects.position = this.pos = this.body.position;
  1712. // this.draw()
  1713. this.handlePaperVisibility()
  1714. },
  1715. // PAPER VISIBILITY
  1716. handlePaperVisibility(){
  1717. // contours focused
  1718. if (!this.isFocused()){
  1719. this.paper_objects.children['contours'].fillColor = "rgba(255,255,255,0.1)";
  1720. }else{
  1721. this.paper_objects.children['contours'].fillColor = "rgba(255,255,255,0.4)";
  1722. if (this.is_hover) {
  1723. this.paper_objects.children['contours'].strokeColor = "#01ffe2";
  1724. this.paper_objects.children['contours'].strokeWidth = 2;
  1725. }else{
  1726. this.paper_objects.children['contours'].strokeColor = "#fff";
  1727. this.paper_objects.children['contours'].strokeWidth = 1;
  1728. }
  1729. }
  1730. // contours visibility
  1731. if (!this.is_opened
  1732. || (this.is_opened && this.map_mode !== "puissancedagir" && this.map_mode !== "doleancer")) {
  1733. this.paper_objects.children['contours'].visible = true;
  1734. } else {
  1735. this.paper_objects.children['contours'].visible = false;
  1736. }
  1737. // backgrounds
  1738. if (this.is_opened) {
  1739. // hide all bgs
  1740. this.paper_objects.children.boussole_bg.visible = false;
  1741. if (this.concernement.has_puissancedagir) {
  1742. this.paper_objects.children.puissanceagir_bg.visible = false;
  1743. }
  1744. if (this.concernement.has_doleance) {
  1745. this.paper_objects.children.doleance_bg.visible = false;
  1746. }
  1747. // choose wich one to show, if one
  1748. switch (this.map_mode) {
  1749. case 'terraindevie':
  1750. this.paper_objects.children.boussole_bg.visible = true;
  1751. break;
  1752. case 'puissancedagir':
  1753. if (this.concernement.has_puissancedagir) {
  1754. this.paper_objects.children.puissanceagir_bg.visible = true;
  1755. }
  1756. break;
  1757. case 'doleancer':
  1758. if (this.concernement.has_doleance) {
  1759. this.paper_objects.children.doleance_bg.visible = true;
  1760. }
  1761. break;
  1762. }
  1763. }else{
  1764. this.paper_objects.children.boussole_bg.visible = false;
  1765. if (this.concernement.has_puissancedagir) {
  1766. this.paper_objects.children.puissanceagir_bg.visible = false;
  1767. }
  1768. if (this.concernement.has_doleance) {
  1769. this.paper_objects.children.doleance_bg.visible = false;
  1770. }
  1771. }
  1772. // entites
  1773. if (this.is_opened
  1774. && this.map_mode !== 'puissancedagir'
  1775. && this.map_mode !== 'doleancer'
  1776. && this.map_mode !== 'action' ) {
  1777. this.paper_objects.children.entites.visible = true;
  1778. // if (this.opened_entite_id) {
  1779. // // console.log('this.paper_objects.children.entites', this.paper_objects.children.entites);
  1780. // this.paper_objects.children.entites.children.forEach((entite) => {
  1781. // // console.log('entite', entite);
  1782. // if (entite.item_id === this.opened_entite_id) {
  1783. // entite.style.fillColor = '#01ffe2';
  1784. // } else {
  1785. // entite.style.fillColor = '#000';
  1786. // }
  1787. // });
  1788. // } else {
  1789. // this.paper_objects.children.entites.children.forEach((entite) => {
  1790. // entite.style.fillColor = '#000';
  1791. // })
  1792. // }
  1793. } else {
  1794. this.paper_objects.children.entites.visible = false;
  1795. }
  1796. // puissance d'agir
  1797. if (this.concernement.has_puissancedagir) {
  1798. if (this.map_mode === "puissancedagir") {
  1799. if (!this.is_opened) {
  1800. this.paper_objects.children.puissanceagir_icon.visible = true; // if not opened and has_puissancedagir draw the puissance d'agir icone
  1801. this.paper_objects.children.puissanceagir_besoins.visible = false;
  1802. } else {
  1803. this.paper_objects.children.puissanceagir_icon.visible = false;
  1804. this.paper_objects.children.puissanceagir_besoins.visible = true;
  1805. // this.drawBesoins();
  1806. }
  1807. } else {
  1808. this.paper_objects.children.puissanceagir_icon.visible = false;
  1809. this.paper_objects.children.puissanceagir_besoins.visible = false;
  1810. }
  1811. }
  1812. // agissantes
  1813. // console.log('this.concernement.has_agissantes', this.concernement.has_agissantes);
  1814. if (this.concernement.has_agissantes) {
  1815. if (this.map_mode === "action") {
  1816. this.paper_objects.children.agissantes.visible = true;
  1817. } else {
  1818. this.paper_objects.children.agissantes.visible = false;
  1819. }
  1820. }
  1821. // doleance
  1822. if (this.concernement.has_doleance) {
  1823. if (this.map_mode === "doleancer") {
  1824. if (!this.is_opened) {
  1825. this.paper_objects.children.doleance_icon.visible = true;
  1826. this.paper_objects.children.doleance_steps.visible = false;
  1827. } else {
  1828. this.paper_objects.children.doleance_icon.visible = false;
  1829. this.paper_objects.children.doleance_steps.visible = true;
  1830. }
  1831. } else {
  1832. this.paper_objects.children.doleance_icon.visible = false;
  1833. this.paper_objects.children.doleance_steps.visible = false;
  1834. }
  1835. }
  1836. },
  1837. isFocused(){
  1838. return this.map_mode === 'terraindevie'
  1839. || (this.map_mode === 'action' && this.concernement.has_agissantes)
  1840. || (this.map_mode === 'puissancedagir' && this.concernement.has_puissancedagir)
  1841. || (this.map_mode === 'doleancer' && this.concernement.has_doleance);
  1842. },
  1843. },
  1844. render() {
  1845. // console.log('render()', this.ctx);
  1846. },
  1847. }
  1848. </script>