123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097 |
- <script>
- import { nextTick } from 'vue'
- import Matter from "matter-js";
- import MatterAttractors from "matter-attractors";
- // Matter.use(MatterAttractors);
- // import polydecomp from "poly-decomp";
- import paper from 'paper';
- // import { easeInOutQuad, easeInOutQuart } from 'easing-utils';
- import Tween from "@tweenjs/tween.js";
- import { mapState, mapActions } from 'pinia'
- import { ConcernementsStore } from '@/stores/concernements'
- import { CommonStore } from '@/stores/common'
- import { mdiPictureInPictureBottomRight } from '@mdi/js';
- export default {
- inject: ['canvasMap', 'matterEngine'],
- data() {
- return {
- id: null,
- cid: null,
- concernement: null,
- active_revision: null,
- entities: null,
- superposedEntitesIDsList: [],
- canvas: null,
- ctx: null,
- pos : {
- x: 0,
- y: 0
- },
- ray: 100,
- time: 0,
- salientPoints: [],
- scale: 1,
- prev_scale: 1,
- opacity: 0,
- tween: null,
- is_open: false,
- is_opening: false,
- is_closing: false,
- is_hover: false,
- //
- body: null,
- body_parts: [],
- constraint: null,
- //
- paper_main_object: {},
- paper_groups: {}
- }
- },
- props: ['mapitem'],
- computed: {
- ...mapState(ConcernementsStore,['map_mode',
- 'concernementsByID',
- 'allSuperpositions_byid',
- 'allMapItems_byid',
- 'opened_concernement',
- 'opened_entite_id']),
- ...mapState(CommonStore,['hover_elmt',
- 'map_item_ray',
- 'cartouch_width',
- 'cartouch_is_opened',
- 'paper_symbol_definitions'])
- },
- created () {
- console.log('ConcernementMapItem created', this.mapitem);
- // this.id = this.superposition_id ? `${this.cid}___${this.superposition_id}` : this.cid;
- this.id = this.mapitem.id;
- this.concernement = this.mapitem.concernement;
- this.cid = this.concernement.id;
- console.log('mapitem this.cid', this.cid);
- this.active_revision = this.concernement.active_revision;
- // console.log(`ConcernementsMapItem ${this.id} created`);
- // this.entites = this.concernement.entites
- this.entites = this.concernement.revisions_byid[this.concernement.revision_id].entites;
-
- // disable concernement if less than 3 entite
- if(this.entites.length < 3){
- this.hideShowConcernement(this.concernement.id, false);
- } else{
- // record canvas and ctx for rendering (drawing)
- this.canvas = this.canvasMap.canvas
- this.ctx = this.canvasMap.ctx
-
- // define the ray regarding the width and height of screen
- this.ray = this.map_item_ray;
- // console.log(`this.ray: ${this.ray}`);
- //
- this.parseEntityPointsValues()
- // this.getSalientPoints()
- this.getJarvisEnvelopeConvexe()
- // define init position of the item
- this.pos = this.getRandomPos();
- //
- this.getSuperposedEntitesIDsList();
- //
- this.initMatterBody()
- //
- this.initPaperObjects()
- }
- // this.setConcernementMapItem(this.cid, this);
- },
- // mounted() {
- // console.log(`ConcernementsMapItem ${this.concernement.id} mounted`, this.canvasMap.canvas);
-
- // },
- // beforeUnmount () {
- unmounted () {
- // console.log(`mapitem ${this.id} unmounted`);
- if(this.mapitem.clone) {
- // console.log(`this.paper_main_object ${this.paper_main_object.id}`, this.paper_main_object);
- paper.project.getItem({id:this.paper_main_object.id}).remove();
- };
- if (this.body) {
- Matter.Composite.remove(this.matterEngine.world, this.body);
- }
- },
- watch: {
- // canvasMap (n, o) {
- // console.log("concernementItem watch canvasMap", o, n);
- // }
- canvasMap: {
- handler (n, o){
- // console.log("concernementItem watch canvasMap.ctx", typeof this.canvas, o, n);
- if (!this.canvas) {
- this.initCanvasMap()
- }
- },
- deep: true
- },
- opened_concernement: {
- handler (n, o) {
- if (!n) { // if there is no opened concernement
- this.is_open = false;
- this.applyShuffleForces();
- } else {
- if(this.cid === n.id && this.id === n.opened_mapitem_id){
- this.is_open = true;
- }else{
- this.is_open = false;
- }
- }
- },
- deep: true
- },
- is_open: {
- handler (n, o) {
- // console.log('mapItem watch is_open', n, this.is_open);
- if(n){ // opened
- this.openClose(true);
- }else if(o) { // closed if was opened
- this.openClose(false);
- }
- },
- deep: true
- },
- map_mode: {
- handler (n, o) {
- console.log('concernementMapItem watch map_mode', o, n);
- if (n === 'terraindevie' && !this.opened_concernement) {
- this.applyShuffleForces(); // apply a little force to check the map when returning to terrain de vie
- }
- if (this.is_open & n !== o) {
- this.setPaperContents();
- }
- if (n !== o) {
- this.handlePaperVisibilityOnMapMode()
- }
- },
- deep: true
- },
- hover_elmt: {
- handler (n, o) {
- // console.log(`watch hover_elmt ${this.id}`, o, n);
- if (n && (n.type === 'concernement' || n.type === 'superposition') && n.id === this.id) {
- this.is_hover = true;
- } else {
- this.is_hover = false;
- }
- },
- deep: true
- },
- is_hover: {
- handler (n, o) {
- this.onIsHover(n);
- },
- deep: true
- },
- active_revision: {
- handler (n, o) {
- console.log(`concernementMapItem watch active_revision o:${o}, n:${n}`);
- if(o & n){ // do not trigger on first variable filling (if o is null)
- this.resetPaperActiveRevision();
- }
- },
- deep: true
- }
- },
- methods: {
- ...mapActions(CommonStore,['setHoverElmt']),
- ...mapActions(ConcernementsStore,['openCloseConcernements',
- // 'setConcernementMapItem',
- 'hideShowConcernement',
- 'setBesoinPaperId',
- 'setOpenedDoleanceField',
- 'setOpenedRecit']),
-
- // getResponsiveRay(){
- // return Math.min(this.canvas.width, this.canvas.height) * 0.08;
- // },
- parseEntityPointsValues (){
- // converts data (menace/maintien, actuel/future, prise) into atcual position x,y
- for (let r = 0; r < this.concernement.revisions.length; r++) { // loop through all revisions
- for (let i = 0; i < this.concernement.revisions[r].entites.length; i++) { // loop through all entite for each revision
- let entite = this.concernement.revisions[r].entites[i]
- // console.log('entite', entite);
-
- entite.display = {
- alpha: null,
- ray: null
- }
- // RAYON
- // https://stackoverflow.com/questions/5731863/mapping-a-numeric-range-onto-another
- // slope = (output_end - output_start) / (input_end - input_start)
- // output = output_start + slope * (input - input_start)
- // from range 0 -> 100 to range 0 -> this.ray
- let init_max = 100
- let slope = this.ray / init_max
- entite.display.ray = slope * (init_max - entite.prise);
- // if (this.concernement.id === 28) {
- // console.log(`entity prise: ${entite.prise} | ray: ${entite.display.ray}`);
- // }
-
- // ANGLE
- // -90 <= mm <= 90
- if (entite.actuelfuture) {
- // future en haut : 180 <= a <= 360
- // from -90 -> 90 to range 180 -> 360
- entite.display.alpha = entite.menacemaintien + 270
- } else {
- // actuel: en bas : O <= a <= 180
- // from -90 -> 90 to range 180 -> 0
- entite.display.alpha = -1 * entite.menacemaintien + 90
- }
- // POSITION X Y (par rapport au centre du concernement)
- entite.display.pos = {
- x: entite.display.ray * Math.cos(entite.display.alpha * (Math.PI/180)),
- y: entite.display.ray * Math.sin(entite.display.alpha * (Math.PI/180))
- }
- // if (entite.entite) {
- // this.entites_byid[entite.entite.id].display = entite.display;
- // }
- }
- }
- },
- getSalientPoints_OLD() {
- // debugger
- // console.log(this.entites);
- let arc = 360/30;
- // loop through arcs
- // for (let i = 360/arc; i >= 0 ; i--) {
- for (let i = 0; i <= 360/arc ; i++) {
- // loop through entities to find the farest on the arc
- let max_r = 0;
- let farest = null;
- for (let j = 0; j < this.entites.length; j++) {
- let entite = this.entites[j];
- if(arc*i <= entite.display.alpha && entite.display.alpha <= arc*i+arc) { // if entity is in arc
- if (entite.display.ray > max_r) { // && entite.display.ray > this.ray/2 // and farest from minimu
- // if entity is farest from precedent one
- max_r = entite.display.ray;
- // recalcul x & y to get a little padding between entite and contour by increasing ray
- farest = {
- alpha: entite.display.alpha,
- ray: entite.display.ray,
- pos: {
- x: (entite.display.ray + 3) * Math.cos(entite.display.alpha * (Math.PI/180)),
- y: (entite.display.ray + 3) * Math.sin(entite.display.alpha * (Math.PI/180))
- }
- };
- }
- }
- }
- if (farest) {
- this.salientPoints.push(farest)
- }
- }
- // console.log(`this.salientPoints ${this.concernement.id}`, this.salientPoints);
- },
- getJarvisEnvelopeConvexe(){
- this.salientPoints = [];
- let entites = this.concernement.revisions_byid[this.concernement.active_revision].entites;
- // console.log(`getJarvisEnvelopeConvexe ${this.id}`, this.entites.length);
- // https://www.geeksforgeeks.org/convex-hull-using-jarvis-algorithm-or-wrapping/
- // find the most left point
- let l, min_x = null;
- for (let i = 0; i < entites.length; i++) {
- let entite = entites[i];
- let x = entite.display.ray * Math.cos(entite.display.alpha * (Math.PI/180));
- if(!min_x || min_x > x){
- l = i;
- min_x = x;
- }
- }
- // Start from leftmost point, keep moving clockwise
- // until reach the start point again. This loop runs O(h)
- // times where h is number of points in result or output.
- let p = l, q;
- do {
- // console.log(`do while ${this.id}`, p);
- // Add current point to result
- let entite = entites[p];
- let farest = {
- alpha: entite.display.alpha,
- ray: entite.display.ray,
- pos: {
- x: (entite.display.ray) * Math.cos(entite.display.alpha * (Math.PI/180)),
- y: (entite.display.ray) * Math.sin(entite.display.alpha * (Math.PI/180))
- }
- };
- this.salientPoints.push(farest);
- // Search for a point 'q' such that
- // orientation(p, q, x) is clockwise
- // for all points 'x'. The idea is to keep
- // track of last visited most clockwise
- // point in q. If any point 'i' is more
- // clockwise than q, then update q.
- q = (p + 1) % entites.length;
- for (let i = 0; i < entites.length; i++) {
- let p_x = (entites[p].display.ray) * Math.cos(entites[p].display.alpha * (Math.PI/180));
- let p_y = (entites[p].display.ray) * Math.sin(entites[p].display.alpha * (Math.PI/180));
- let i_x = (entites[i].display.ray) * Math.cos(entites[i].display.alpha * (Math.PI/180));
- let i_y = (entites[i].display.ray) * Math.sin(entites[i].display.alpha * (Math.PI/180));
- let q_x = (entites[q].display.ray) * Math.cos(entites[q].display.alpha * (Math.PI/180));
- let q_y = (entites[q].display.ray) * Math.sin(entites[q].display.alpha * (Math.PI/180));
-
- let val = (i_y - p_y) * (q_x - i_x) - (i_x - p_x) * (q_y - i_y);
-
- // If i is more clockwise than current q, then update q
- if (val > 0){
- q = i;
- }
- }
- // Now q is the most clockwise with
- // respect to p. Set p as q for next iteration,
- // so that q is added to result 'hull'
- p = q;
- } while (p != l);
- },
- getRandomPos(){
- let pad = 200;
- // if (this.concernement.id === 56) {
- // return {
- // x: Math.random() > 0.5 ? pad : this.canvas.width - pad,
- // y: pad + this.ray/2 + Math.random()*(this.canvas.height - this.ray - pad)
- // };
- // } else {
- return {
- x: pad + this.getGaussianRandom()*(this.canvas.width - pad*2),
- y: pad + this.getGaussianRandom()*(this.canvas.height - pad*2)
- };
- // }
- },
- getGaussianRandom(){
- // INFO https://stackoverflow.com/a/49434653
- let u = 0, v = 0;
- while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
- while(v === 0) v = Math.random();
- let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
- num = num / 10.0 + 0.5; // Translate to 0 -> 1
- if (num > 1 || num < 0) return this.getGaussianRandom() // resample between 0 and 1
- return num
- },
- getSuperposedEntitesIDsList(){
- if (this.concernement.superpositions) {
- // loop through all concernement superpositions couples of this concernement
- for(let [couple_id, superpositions] of Object.entries(this.concernement.superpositions)){
- // loop through all superpositions of each couple
- for(let [superposition_id, superposition] of Object.entries(superpositions)){
- if (this.mapitem.superposition_ids.indexOf(superposition_id) >= 0) {
- switch (this.cid) { // get the right eid regarding the cid
- case superposition[0].cid:
- this.superposedEntitesIDsList.push(superposition[0].eid);
- break;
- case superposition[1].cid:
- this.superposedEntitesIDsList.push(superposition[1].eid);
- break;
- }
- }
- }
- }
- }
- console.log('superposedEntitesIDsList', this.superposedEntitesIDsList);
- },
- // MATTER BODY
- initMatterBody (){
-
- // MATTER
- // create the matter body and add it to the engine
- if (!this.body) {
- // console.log('concernementItem creating body');
- // INFO https://github.com/liabru/matter-attractors/issues/8
- // INFO https://github.com/liabru/matter-attractors/blob/master/index.js
- // INFO https://github.com/liabru/matter-attractors/blob/master/build/matter-attractors.js#L180
- MatterAttractors.Attractors.gravityConstant = -20;
- // Create parts of the body : main big circle & entities
- // INFO map a range of numbers to another range of numbers https://stackoverflow.com/a/46462321
- let entite_range = [3, 100];
- let ray_range = [this.ray*0.8,this.ray*1.2];
- let ray = ray_range[0] + (this.entites.length - entite_range[0]) * (ray_range[1] - ray_range[0]) / (entite_range[1] - entite_range[0]);
- this.body_parts = [
- Matter.Bodies.circle(0, 0, ray, {
- // item_type: 'concernement',
- // id: this.concernement.id,
- })
- ];
-
- // INFO map a range of numbers to another range of numbers https://stackoverflow.com/a/46462321
- let mass_range = [5,15];
- let mass = mass_range[0] + (this.entites.length - entite_range[0]) * (mass_range[1] - mass_range[0]) / (entite_range[1] - entite_range[0]);
- // create the body
- this.body = Matter.Body.create({
- parts: this.body_parts,
- item_type: 'concernement',
- id: this.id,
- frictionAir: 0,
- // mass: Math.pow(3, this.entites.length),
- // mass: 10,
- mass: mass,
- restitution: 0.06,
- collisionFilter: {
- group: -1
- },
- plugin: {
- attractors: [
- // // there is a built in helper function for Newtonian gravity!
- // // you can find out how it works in index.js
- MatterAttractors.Attractors.gravity
-
- // function(bodyA, bodyB) {
- // var force = {
- // x: (bodyA.position.x - bodyB.position.x) * 1e-6,
- // y: (bodyA.position.y - bodyB.position.y) * 1e-6
- // }
- // // apply force to both bodies
- // Matter.Body.applyForce(bodyA, bodyA.position, force);
- // Matter.Body.applyForce(bodyB, bodyB.position, Matter.Vector.neg(force));
- // }
- // INFO https://github.com/liabru/matter-attractors/blob/master/build/matter-attractors.js#L192
- // function (bodyA, bodyB){
- // // use Newton's law of gravitation
- // var bToA = Matter.Vector.sub(bodyB.position, bodyA.position),
- // distanceSq = Matter.Vector.magnitudeSquared(bToA) || 0.0001,
- // normal = Matter.Vector.normalise(bToA),
- // magnitude = -MatterAttractors.Attractors.gravityConstant * (bodyA.mass * bodyB.mass / distanceSq),
- // force = Matter.Vector.mult(normal, magnitude);
- // // to apply forces to both bodies
- // Matter.Body.applyForce(bodyA, bodyA.position, Matter.Vector.neg(force));
- // Matter.Body.applyForce(bodyB, bodyB.position, force);
- // }
- ]
- }
- });
- Matter.Body.setPosition(this.body, this.pos);
- // add init velocity
- this.setInitBodyVelocity()
- // console.log('concernementItem mass', this.body.mass);
- Matter.Composite.add(this.matterEngine.world, this.body);
- // console.log('concernement body', this.body);
- // listen for afterUpdate event from Matter.Engine object
- Matter.Events.on(this.matterEngine, "beforeUpdate", this.onBeforeEngineUpdate);
- Matter.Events.on(this.matterEngine, "afterUpdate", this.onAfterEngineUpdate);
- }
- },
- setInitBodyVelocity(){
- let delta = 50;
- Matter.Body.setVelocity(this.body, {
- x: -delta + Math.random()*delta*2,
- y: -delta + Math.random()*delta*2
- });
- },
- // PAPER OBJECTS
- initPaperObjects(){
- // the main paper group containing all paper graphical items for one concernement
- this.paper_main_object = new paper.Group({
- pivot: new paper.Point(this.pos),
- name: `main_${this.id}`,
- cid: this.cid,
- superposition_id: this.mapitem.superposition_ids[0] // TODO what to do with multiples superpositions ids
- });
- // the sub items for one concernement
- this.paper_main_object.addChild(this.setPaperContour());
- if (this.concernement.has_superpositions) {
- this.paper_main_object.addChild(this.setPaperEntitesSuperposees());
- }
- if (this.concernement.has_puissancedagir) {
- this.addNewPaperSymbolInstance('puissanceagir_icon', false, 0.7);
- }
- if (this.concernement.has_agissantes) {
- this.paper_main_object.addChild(this.setPaperAgissantesIcons());
- }
- if (this.concernement.has_doleance) {
- this.addNewPaperSymbolInstance('doleance_icon', false, 0.7);
- }
-
- this.initPaperEvents()
- },
- setPaperContents(){
- // trigered once opening tween is complete
- this.clearPaperContents();
- switch(this.map_mode){
- case 'terraindevie':
- this.addNewPaperSymbolInstance('boussole_bg', true);
- this.paper_main_object.addChild(this.setPaperEntites());
- break;
- case 'superposition':
- this.addNewPaperSymbolInstance('boussole_bg', true);
- break;
- case 'puissancedagir':
- this.addNewPaperSymbolInstance('puissanceagir_bg', true);
- this.paper_main_object.addChild(this.setPaperPuissanceagirBesoins());
- break;
- case 'action':
- this.addNewPaperSymbolInstance('boussole_bg', true);
- this.paper_main_object.addChild(this.setPaperAgissantes());
- break;
- case 'doleancer':
- this.addNewPaperSymbolInstance('doleance_bg');
- this.paper_main_object.addChild(this.setPaperDoleances());
- break;
- }
- },
- resetPaperActiveRevision(){
- this.getJarvisEnvelopeConvexe();
- // remove contours if already exists
- if (this.paper_main_object.children.contours) {
- this.paper_main_object.children.contours.remove();
- }
- this.paper_main_object.addChild(this.setPaperContour());
- // remove entites if already exists
- if (this.paper_main_object.children.entites) {
- this.paper_main_object.children.entites.remove();
- }
- this.paper_main_object.addChild(this.setPaperEntites());
- },
- clearPaperContents(){
- let clearable_children = ['boussole_bg', 'entites',
- 'puissanceagir_bg','puissanceagir_besoins',
- 'agissantes',
- 'doleance_bg', 'doleances'];
- clearable_children.forEach(child_name => {
- if (this.paper_main_object.children[child_name]) {
- this.paper_main_object.children[child_name].remove();
- }
- });
- },
- addNewPaperSymbolInstance(name, back, scale){
- let instance = new paper.SymbolItem(this.paper_symbol_definitions[name]); // , {x:0,y:0}
- instance.name = name;
- // instance.pivot = new paper.Point({x:0,y:0});
- instance.position = this.pos;
- let s = scale ? this.scale * scale : this.scale;
- instance.scale(s);
- // instance.locked = true;
- this.paper_main_object.addChild(instance);
- if (back) {
- this.paper_main_object.children[name].sendToBack();
- } else {
- this.paper_main_object.children[name].bringToFront();
- }
- },
- setPaperContour(){
- // console.log(`setPaperContour ${this.concernement.id}`);
- let getPaddedRoundedSegments = (b,a,c,d) => {
- const ac = { x: c.x - a.x, y: c.y - a.y } // get ac vecteur
- const lac = Math.sqrt(Math.pow(ac.x, 2) + Math.pow(ac.y, 2)); // get ac longueur ac
- const ab = { x: b.x - a.x, y: b.y - a.y } // get ab vecteur
- const lab = Math.sqrt(Math.pow(ab.x, 2) + Math.pow(ab.y, 2)); // get ab longeur
- const vab = { x: ab.x/lab, y: ab.y/lab } // get unit vecteur ab
- const an = { x: vab.x*lac, y: vab.y*lac } // get an vecteur
- const n = { x: a.x + an.x, y: a.y+an.y } // get n point
- const m = { x: (c.x + n.x)/2, y: (c.y + n.y)/2 } // get nc midle point
- const ma = { x:a.x - m.x, y: a.y - m.y } // get ma vecteur
- const lma = Math.sqrt(Math.pow(ma.x, 2)+Math.pow(ma.y, 2)) // get longeur m->a
- const vma = { x: ma.x/lma, y: ma.y/lma } // get ma vecteur unitaire
- // console.log(`vma x:${vma.x}, y:${vma.y}`);
- const pad = 4; // exterior padding
- // the final padded point
- const pa = [
- this.pos.x+(a.x+vma.x*pad)*this.scale,
- this.pos.y+(a.y+vma.y*pad)*this.scale
- ]
-
- // handles
- const delta = 0.05;
- // handle IN
- const hli = Math.abs(lab)*delta; // handle longeur
- const vnai = { x: -vma.y, y: vma.x } // get the ma normal unit vector IN
- const hai = [ vnai.x*hli, vnai.y*hli ]; // get the handleIn point
- // handle OUT
- const hlo = Math.abs(lac)*delta; // handle longeur
- const vnao = { x: vma.y, y: -vma.x } // get the ma normal vector Out
- const hao = [ vnao.x*hlo, vnao.y*hlo ]; // get the handleOut point
- return new paper.Segment({
- point: pa,
- handleIn: hai,
- handleOut: hao
- })
-
- }
- const first_point = getPaddedRoundedSegments(
- this.salientPoints[this.salientPoints.length-1].pos,
- this.salientPoints[0].pos,
- this.salientPoints[1].pos
- );
- let segments = [first_point];
- for (let j = 1; j < this.salientPoints.length-1; j++) {
- // segments.push([this.pos.x+this.salientPoints[j].pos.x*this.scale*gap, this.pos.y+this.salientPoints[j].pos.y*this.scale*gap])
- segments.push(getPaddedRoundedSegments(
- this.salientPoints[j-1].pos,
- this.salientPoints[j].pos,
- this.salientPoints[j+1].pos
- ))
- }
- const last_point = getPaddedRoundedSegments(
- this.salientPoints[this.salientPoints.length-2].pos,
- this.salientPoints[this.salientPoints.length-1].pos,
- this.salientPoints[0].pos
- );
- segments.push(last_point)
- segments.push(first_point)
-
- const contrs = new paper.Path({
- name: 'contours',
- segments: segments,
- fillColor: 'rgba(255,255,255,0.4)',
- // selected: true,
- strokeColor: '#fff',
- strokeWidth: 1,
- pivot: new paper.Point(this.pos),
- cid: this.cid
- });
- return contrs;
- },
- setPaperEntites(){
- let g = new paper.Group({
- pivot: new paper.Point(this.pos),
- name: 'entites'
- });
- // for (let i = 0; i < this.entites.length; i++) {
- for (let i = 0; i < this.concernement.revisions_byid[this.concernement.active_revision].entites.length; i++) {
- let entite = this.concernement.revisions_byid[this.concernement.active_revision].entites[i];
- // use paper symbol
- let symbol_name = entite.entite ? entite.entite.agissante ? 'entite_action' : 'entite' : 'entite_hidden';
- let instance = new paper.SymbolItem(this.paper_symbol_definitions[symbol_name]);
- instance.name = 'entite';
- instance.position = new paper.Point([this.pos.x + entite.display.pos.x * this.scale, this.pos.y + entite.display.pos.y * this.scale]);
- instance.scale(this.scale);
- instance.fillColor = '#000';
- instance.item_id = entite.entite ? entite.entite.id : null;
- instance.item_type = symbol_name;
- instance.is_symbol_instance = true;
- g.addChild(instance)
- }
- return g;
- },
- setPaperEntitesSuperposees(){
- // console.log('setPaperSuperpositions, superpositions', this.concernement.superpositions);
- let g = new paper.Group({
- pivot: new paper.Point(this.pos),
- name: 'entites_superposes'
- });
- for (let i = 0; i < this.concernement.revisions_byid[this.concernement.active_revision].entites.length; i++) {
- let entite = this.concernement.revisions_byid[this.concernement.active_revision].entites[i];
- if (entite.entite // check if we have an entite object with all the contents
- && this.superposedEntitesIDsList.indexOf(entite.entite.id) >= 0) // check if entite id is in the list builded above
- {
- // console.log(`entite ${entite.entite.id}`, entite, entite.entite.superposition);
- // use paper symbol
- let instance = new paper.SymbolItem(this.paper_symbol_definitions['entite']);
- instance.name = 'entite';
- instance.position = new paper.Point([this.pos.x + entite.display.pos.x * this.scale, this.pos.y + entite.display.pos.y * this.scale]);
- // instance.scale(this.scale);
- instance.scale(3);
- instance.fillColor = '#000';
- instance.item_id = entite.entite.id;
- instance.item_type = 'entite_superpose';
- instance.is_symbol_instance = true;
- g.addChild(instance)
- }
- }
- return g;
- },
- setPaperAgissantes(){
- console.log('setPaperAgissantes');
- let g = new paper.Group({
- pivot: new paper.Point(this.pos),
- name: 'agissantes'
- });
-
- for (let i = 0; i < this.concernement.revisions_byid[this.concernement.revision_id].entites.length; i++) {
- let entite = this.concernement.revisions_byid[this.concernement.revision_id].entites[i];
- console.log('agissantes', entite);
- if (entite.entite && entite.entite.agissante) {
- let instance = new paper.SymbolItem(this.paper_symbol_definitions['entite_action']);
- instance.name = 'entite_action';
- instance.position = new paper.Point([this.pos.x + entite.display.pos.x * this.scale, this.pos.y + entite.display.pos.y * this.scale]);
- instance.fillColor = '#000';
- // instance.scale(0.2);
- instance.scale(this.scale);
- instance.item_id = entite.entite.id;
- instance.item_type = 'entite_action';
- instance.is_symbol_instance = true;
- g.addChild(instance)
- }
- }
- return g;
- },
- setPaperAgissantesIcons(){
- let g = new paper.Group({
- pivot: new paper.Point(this.pos),
- name: 'agissantes_icons'
- });
- for (let i = 0; i < this.concernement.revisions_byid[this.concernement.revision_id].entites.length; i++) {
- let entite = this.concernement.revisions_byid[this.concernement.active_revision].entites[i];
- if (entite.entite && entite.entite.agissante) {
- let instance = new paper.SymbolItem(this.paper_symbol_definitions['entite_action_icon']);
- instance.name = 'entite_action';
- instance.position = new paper.Point([this.pos.x + entite.display.pos.x * this.scale, this.pos.y + entite.display.pos.y * this.scale]);
- instance.fillColor = '#000';
- // instance.scale(0.2);
- instance.scale(this.scale);
- instance.item_id = entite.entite.id;
- instance.item_type = 'entite_action';
- instance.is_symbol_instance = true;
- g.addChild(instance)
- }
- }
- return g;
- },
- setPaperPuissanceagirBesoins(){
- let g = new paper.Group({
- pivot: new paper.Point(this.pos),
- name: 'puissanceagir_besoins'
- });
- let res_fields = ['qui','quoi','ou','avec'];
- let arc = (360 / 16); // unit arc
- let r = (this.ray * this.scale)/5; // unit ray
- let br = r - r/3; // besoin ray
- for (let i = 0; i < this.concernement.besoins.length; i++) {
- let start_a = arc * i; // angle depart (for reponses)
- let center_a = start_a + arc/2; // angle central
- let x = Math.cos(center_a*(Math.PI/180)) * br;
- let y = Math.sin(center_a*(Math.PI/180)) * br;
- // use paper symbol
- let besoin = new paper.SymbolItem(this.paper_symbol_definitions['besoin']);
- besoin.position = new paper.Point([this.pos.x + x, this.pos.y + y]);
- besoin.scale(this.scale);
- besoin.item_id = this.concernement.besoins[i].id;
- besoin.item_cid = this.concernement.id;
- besoin.item_type = 'besoin';
- besoin.is_symbol_instance = true;
- console.log(`paper besoin id:${besoin.id}`);
- this.setBesoinPaperId(besoin.id, this.cid, this.concernement.besoins[i].id);
- g.addChild(besoin)
- let res_arc = arc / (1 + this.concernement.besoins[i].reponses.length); // unit arc for responses depending responses number
- for (let j = 0; j < this.concernement.besoins[i].reponses.length; j++) {
- let res_a = start_a + res_arc * (j+1); // angle for response line
- for (let f = 0; f < res_fields.length; f++) { // loop through all 4 fields, keep only the last one filled
- if( this.concernement.besoins[i].reponses[j][res_fields[f]] // if field filled
- && (f === res_fields.length -1 || !this.concernement.besoins[i].reponses[j][res_fields[f+1]]) // and is last field or last field filled
- ){
- let rr = this.ray * this.scale - r*f - r/2; // reponse field ray
- let rx = Math.cos(res_a*(Math.PI/180)) * rr;
- let ry = Math.sin(res_a*(Math.PI/180)) * rr;
- // use paper symbol
- let reponse = new paper.SymbolItem(this.paper_symbol_definitions['reponse']);
- reponse.position = new paper.Point([this.pos.x + rx, this.pos.y + ry]);
- reponse.scale(this.scale);
- reponse.item_id = this.concernement.besoins[i].reponses[j].id;
- reponse.item_bid = this.concernement.besoins[i].id;
- reponse.item_cid = this.concernement.id;
- reponse.item_type = 'reponse';
- reponse.is_symbol_instance = true;
- this.setBesoinPaperId(reponse.id, this.cid, this.concernement.besoins[i].id, this.concernement.besoins[i].reponses[j].id);
- g.addChild(reponse)
- }
- }
- }
- }
- return g;
- },
- setPaperDoleances(){
- let g = new paper.Group({
- pivot: new paper.Point({x:0,y:0}),
- name: `doleances`
- });
- this.concernement.doleances.forEach((d) => {
- g.addChild(this.setPaperDoleanceSteps(d))
- });
- return g;
- },
- setPaperDoleanceSteps(doleance){
- let g = new paper.Group({
- pivot: new paper.Point({x:0,y:0}),
- name: `doleance_${doleance.id}`,
- doleance_id: doleance.id
- });
- // let doleance = this.concernement.doleances[0];
- let all_fields = [
- [
- 'leprobleme',
- 'lenquete',
- {
- fieldname: 'groupesinterets',
- fields: [
- 'groupe_interets',
- 'accorder_interets',
- 'formuler',
- ]
- }
- ],
- [
- 'entite_addresse_doleance',
- 'comment_ennonce_doleance',
- 'aqui_addresse_doleance',
- {
- fieldname: 'reception_traitement',
- fields: [
- 'entite_adressee',
- 'doleance_formulee',
- 'traite_doleance',
- 'entite_recoit_doleance',
- ]
- }
- ],
- [
- 'entites_decisionnaires',
- 'decision_formule',
- {
- fieldname: 'mise_en_oeuvre_decision',
- fields: [
- 'entite_adresse_decision',
- 'formule_decision',
- 'entite_metenoeuvre_decisio',
- ]
- }
- ],
- [
- 'entite_adresse_application',
- 'aqui_adresse_decision',
- 'comment_formule_decision',
- {
- fieldname: 'receptions_et_applications',
- fields: [
- 'applique_decision',
- 'formule_decision_applic',
- 'entite_recoit_decision',
- ]
- },
- 'probleme_initial_resolu',
- 'oui_nouvelle_situation',
- 'non_adresse_doleance',
- ]
- ];
-
- var r = this.ray * this.scale * 0.8; // ray
- var dr = r/2; // demi ray
- // var pcr = 2*this.scale; // petits cercle rayon
- // https://fr.wikipedia.org/wiki/Trigonom%C3%A9trie#/media/Fichier:Unit_circle_angles_color.svg
- // https://fr.wikipedia.org/wiki/Identit%C3%A9_trigonom%C3%A9trique_pythagoricienne#Preuve_utilisant_le_cercle_unit%C3%A9
- // radians = degrees * (pi/180)
- // degrees = radians * (180/pi)
- // Points for 45° axes
- let m = Math.sin(45*(Math.PI/180)) * r; // x = y for rayon
- let n = Math.sin(45*(Math.PI/180)) * r/2; // x = y for demi rayon
- let o = Math.cos(22.5*(Math.PI/180)) * r; // x @ 22.5° for rayon
- let p = Math.sin(22.5*(Math.PI/180)) * r; // y @ 22.5° for rayon
- let o_d = Math.cos(22.5*(Math.PI/180)) * r/2; // x @ 22.5° for demi rayon
- let p_d = Math.sin(22.5*(Math.PI/180)) * r/2; // y @ 22.5° for demi rayon
- // let fontsize = 4;
-
- //
- // CAMENBERT STATIQUES
- //
- // l'enquete
- //
- // camenbert
- let cam = new paper.Path({
- strokeColor: '#fff',
- strokeWidth: 2,
- fillColor: "rgba(255, 255, 255, 0.4)",
- item_type: 'doleance_step',
- item_id: `lenquete`,
- did: doleance.id,
- field: 'lenquete',
- field_index: null
- });
- cam.add({x: this.pos.x , y: this.pos.y + dr});
- cam.lineTo({x: this.pos.x, y: this.pos.y + r});
- cam.arcTo({x: this.pos.x - p, y: this.pos.y + o}, {x: this.pos.x - m, y: this.pos.y + m});
- cam.lineTo({x: this.pos.x - n, y: this.pos.y + n});
- cam.arcTo({x: this.pos.x - p_d, y: this.pos.y + o_d}, {x: this.pos.x , y: this.pos.y + dr});
- // texte
- // enquete.addChild(new paper.PointText({
- // point: {
- // x:this.pos.x + Math.sin(22.5*(Math.PI/180)) * r*0.75,
- // y:this.pos.y + Math.cos(22.5*(Math.PI/180)) * r*0.75
- // },
- // content: doleance['lenquete'],
- // fontSize: fontsize,
- // fillColor: '#fff',
- // justification: 'center',
- // locked: true
- // }));
- g.addChild(cam);
-
- //
- // probleme_initial_resolu
- //
- // camenbert
- let rescam = new paper.Path({
- strokeColor: '#fff',
- strokeWidth: 2,
- fillColor: "rgba(255, 255, 255, 0.4)",
- closed: true,
- item_type: 'doleance_step',
- item_id: `probleme_initial_resolu`,
- did: doleance.id,
- field: 'probleme_initial_resolu',
- field_index: null
- });
- rescam.add({x: this.pos.x + n, y: this.pos.y + n});
- rescam.lineTo({x: this.pos.x + m , y: this.pos.y + m});
- rescam.arcTo({x: this.pos.x + p, y: this.pos.y + o}, {x: this.pos.x, y: this.pos.y + r});
- rescam.lineTo({x: this.pos.x, y: this.pos.y + dr});
- rescam.arcTo({x: this.pos.x + p_d, y: this.pos.y + o_d}, {x: this.pos.x + n, y: this.pos.y + n});
- // texte
- // resolution.addChild(new paper.PointText({
- // point: {
- // x:this.pos.x - Math.sin(22.5*(Math.PI/180)) * r*0.75,
- // y:this.pos.y + Math.cos(22.5*(Math.PI/180)) * r*0.75
- // },
- // content: doleance['probleme_initial_resolu'] ? doleance['oui_nouvelle_situation'] : doleance['non_adresse_doleance'],
- // fontSize: fontsize,
- // fillColor: '#fff',
- // justification: 'center'
- // }));
- g.addChild(rescam)
-
- //
- // MULTIPLE FIELDS
- //
- let multiple_fields = [
- { field_name: 'groupesinterets', arc: 45, decalage: -45 },
- { field_name: 'reception_traitement', arc: 90, decalage: -90 },
- { field_name: 'mise_en_oeuvre_decision', arc: 90, decalage: -180 },
- { field_name: 'receptions_et_applications', arc: 45, decalage: 90 }
- ]
- multiple_fields.forEach((mf, j) => {
- for (let i = 0, l = doleance[mf.field_name].length, a = mf.arc/l; i < l; i++) {
- // let gi = new paper.Group({
- // item_type: 'doleance_step',
- // item_id: 'lenquete',
- // item_field: mf.field_name,
- // item_index: i
- // });
- //camenbert
- let x1= this.pos.x + Math.sin((mf.decalage- a*i)*(Math.PI/180)) * dr,
- y1= this.pos.y + Math.cos((mf.decalage- a*i)*(Math.PI/180)) * dr;
- let x2= this.pos.x + Math.sin((mf.decalage- a*i)*(Math.PI/180)) * r,
- y2= this.pos.y + Math.cos((mf.decalage- a*i)*(Math.PI/180)) * r;
- let x3= this.pos.x + Math.sin((mf.decalage- a*(i+1))*(Math.PI/180)) * r,
- y3= this.pos.y + Math.cos((mf.decalage- a*(i+1))*(Math.PI/180)) * r;
- let x3t= this.pos.x + Math.sin((mf.decalage- a*(i+0.5))*(Math.PI/180)) * r,
- y3t= this.pos.y + Math.cos((mf.decalage- a*(i+0.5))*(Math.PI/180)) * r;
- let x4= this.pos.x + Math.sin((mf.decalage- a*(i+1))*(Math.PI/180)) * dr,
- y4= this.pos.y + Math.cos((mf.decalage- a*(i+1))*(Math.PI/180)) * dr;
- let x4t= this.pos.x + Math.sin((mf.decalage- a*(i+0.5))*(Math.PI/180)) * dr,
- y4t= this.pos.y + Math.cos((mf.decalage- a*(i+0.5))*(Math.PI/180)) * dr;
- let x5= this.pos.x + Math.sin((mf.decalage- a*(i+0.5))*(Math.PI/180)) * r*0.75,
- y5= this.pos.y + Math.cos((mf.decalage- a*(i+0.5))*(Math.PI/180)) * r*0.75;
- let p = new paper.Path({
- strokeColor: '#fff',
- strokeWidth: 2,
- fillColor: "rgba(255, 255, 255, 0.4)",
- item_type: 'doleance_step',
- item_id: `${mf.field_name}-${i}`,
- did: doleance.id,
- field: mf.field_name,
- field_index: i
- });
- p.add([x1,y1]);
- p.lineTo([x2,y2]);
- p.arcTo([x3t,y3t], [x3,y3]);
- p.lineTo([x4,y4]);
- p.arcTo([x4t,y4t], [x1,y1]);
- g.addChild(p);
- // gi.addChild(p);
- // // text
- // gi.addChild(new paper.PointText({
- // point: {x:x5,y:y5},
- // content: `${j}-${i}`,
- // fontSize: fontsize,
- // fillColor: '#fff',
- // justification: 'center'
- // }))
- // g.addChild(gi)
- }
- });
- // POINTS CARDINAUX
- //
- // // leprobleme
- // g.addChild(new paper.Path.Circle({
- // center: [this.pos.x, this.pos.y + r],
- // radius: 3,
- // style: {
- // strokeColor: '#fff',
- // strokeWidth: 2,
- // fillColor: "rgba(255, 255, 255, 0.4)",
- // },
- // item_type: 'doleance_step',
- // item_id: `leprobleme`,
- // did: doleance.id,
- // field: 'leprobleme'
- // }));
- // adresse de la doleance
- g.addChild(new paper.Path.Circle({
- center: [this.pos.x - r, this.pos.y],
- radius: 3 * this.scale,
- style: {
- strokeColor: '#fff',
- strokeWidth: 2,
- fillColor: "rgba(255, 255, 255, 0.9)",
- },
- item_type: 'doleance_step',
- item_id: `adresse_de_la_doleance`,
- did: doleance.id,
- field: 'adresse_de_la_doleance'
- }));
-
- // decision
- g.addChild(new paper.Path.Circle({
- center: [this.pos.x, this.pos.y - r],
- radius: 3 * this.scale,
- style: {
- strokeColor: '#fff',
- strokeWidth: 2,
- fillColor: "rgba(255, 255, 255, 0.9)",
- },
- item_type: 'doleance_step',
- item_id: `decision`,
- did: doleance.id,
- field: 'decision'
- }));
- // adresse_de_la_decision
- g.addChild(new paper.Path.Circle({
- center: [this.pos.x + r, this.pos.y],
- radius: 3 * this.scale,
- style: {
- strokeColor: '#fff',
- strokeWidth: 2,
- fillColor: "rgba(255, 255, 255, 0.9)",
- },
- item_type: 'doleance_step',
- item_id: `adresse_de_la_decision`,
- did: doleance.id,
- field: 'adresse_de_la_decision'
- }));
-
- return g;
- },
- // PAPER VISIBILITY
- handlePaperVisibilityOnBeforeOpen(){
- // agissantes
- if (this.concernement.has_agissantes && this.map_mode === "action") {
- if (!this.is_open) {
- this.paper_main_object.children.agissantes_icons.visible = true;
- } else {
- this.paper_main_object.children.agissantes_icons.visible = false;
- }
- }
- // superposition
- // scale down superposed entites on open
- let entites_superposes = this.paper_main_object.children['entites_superposes'];
- // console.log('entites_superposes.children', entites_superposes.children);
- if(entites_superposes){
- for(let paper_item of entites_superposes.children) {
- // paper_item.definition = this.paper_symbol_definitions.entite_hover;
- paper_item.scale(0.25)
- }
- }
- },
- handlePaperVisibilityOnOpened(){},
- handlePaperVisibilityOnBeforeClose(){
- // superposition
- // scale up superposed entites on open
- let entites_superposes = this.paper_main_object.children['entites_superposes'];
- // console.log('entites_superposes.children', entites_superposes.children);
- if(entites_superposes){
- for(let paper_item of entites_superposes.children) {
- // paper_item.definition = this.paper_symbol_definitions.entite_hover;
- paper_item.scale(4)
- }
- }
- },
- handlePaperVisibilityOnClosed(){
- // agissantes
- if (this.concernement.has_agissantes && this.map_mode === "action") {
- if (!this.is_open) {
- this.paper_main_object.children.agissantes_icons.visible = true;
- } else {
- this.paper_main_object.children.agissantes_icons.visible = false;
- }
- }
- },
- handlePaperVisibilityOnMapMode(){},
- handlePaperVisibilityOnAfterEnginUpdate(){
- // contours focused
- if (!this.isFocused()){
- this.paper_main_object.children['contours'].fillColor = "rgba(255,255,255,0.1)"; //this.mapitem.clone ? "rgba(255,0,0,0.1)" : "rgba(255,255,255,0.1)";
- }else{
- this.paper_main_object.children['contours'].fillColor = "rgba(255,255,255,0.4)"; //this.mapitem.clone ? "rgba(255,0,0,0.4)" : "rgba(255,255,255,0.4)";
- if (this.is_hover) {
- this.paper_main_object.children['contours'].strokeColor = "#01ffe2";
- this.paper_main_object.children['contours'].strokeWidth = 2;
- }else{
- this.paper_main_object.children['contours'].strokeColor = "#fff";
- this.paper_main_object.children['contours'].strokeWidth = 1;
- }
- }
- // contours visibility
- if (!this.is_open
- || (this.is_open && this.map_mode !== "puissancedagir" && this.map_mode !== "doleancer")) {
- this.paper_main_object.children['contours'].visible = true;
- } else {
- this.paper_main_object.children['contours'].visible = false;
- }
- // proximite
- // superposition
- if (this.concernement.has_superpositions) {
- if (this.map_mode === "superposition") {
- this.paper_main_object.children.entites_superposes.visible = true;
- // highlight of entite part of opened superposition
- let group = this.paper_main_object.children['entites_superposes'];
- if(group){
- if (this.$route.query.superposition_id) {
- let superposition_id = this.$route.query.superposition_id;
- if(superposition_id){
- let ids = superposition_id.match(/(\d+)_(\d+)__(\d+)_(\d+)/i)
- group.children.forEach((item) => {
- if ( (this.cid === parseInt(ids[1]) && item.item_id === parseInt(ids[2]))
- || (this.cid === parseInt(ids[3]) && item.item_id === parseInt(ids[4])) ) {
- item.definition = this.paper_symbol_definitions.entite_hover;
- if(!item.focused){
- item.scale(2)
- item.focused = true;
- }
- } else if(!this.is_hover) {
- item.definition = this.paper_symbol_definitions.entite;
- if (item.focused) {
- item.scale(0.5)
- item.focused = false;
- }
- }
- })
- }
- }else{
- group.children.forEach((item) => {
- if(!this.is_hover) {
- item.definition = this.paper_symbol_definitions.entite;
- if (item.focused) {
- item.scale(0.5)
- item.focused = false;
- }
- }
- })
- }
- }
- } else {
- this.paper_main_object.children.entites_superposes.visible = false;
- }
- }
- // puissance d'agir
- if (this.concernement.has_puissancedagir) {
- if (this.map_mode === "puissancedagir") {
- if (!this.is_open) {
- this.paper_main_object.children.puissanceagir_icon.visible = true; // if not opened and has_puissancedagir draw the puissance d'agir icone
- } else {
- this.paper_main_object.children.puissanceagir_icon.visible = false;
- }
- } else {
- this.paper_main_object.children.puissanceagir_icon.visible = false;
- }
- }
-
- // agissantes
- if (this.concernement.has_agissantes) {
- if (this.map_mode !== "action") {
- this.paper_main_object.children.agissantes_icons.visible = false;
- } else if(!this.is_open && !this.is_closing){
- this.paper_main_object.children.agissantes_icons.visible = true;
- }
- }
- // doleance
- if (this.concernement.has_doleance) {
- if (this.map_mode === "doleancer") {
- if (!this.is_open) {
- this.paper_main_object.children.doleance_icon.visible = true;
- } else {
- this.paper_main_object.children.doleance_icon.visible = false;
- // display the right (opened) doleance
- this.concernement.doleances.forEach((d) => {
- this.paper_main_object.children.doleances.children[`doleance_${d.id}`].visible = d.id === this.concernement.opened_doleance.id;
- })
- }
- } else {
- this.paper_main_object.children.doleance_icon.visible = false;
- }
- }
-
- // focus on opened entite
- if (this.is_open && this.opened_entite_id && (this.map_mode === 'terraindevie' || this.map_mode === 'action')) {
- let group = this.map_mode === 'terraindevie' ? this.paper_main_object.children['entites'] : this.paper_main_object.children['agissantes'];
- if(group){
- group.children.forEach((item) => {
- if (item.item_id === this.opened_entite_id) {
- item.definition = item.item_type === 'entite' ? this.paper_symbol_definitions.entite_hover : this.paper_symbol_definitions.entite_action_hover;
- } else {
- if (!this.hover_elmt || item.item_id !== this.hover_elmt.id) {
- item.definition = item.item_type === 'entite' ? this.paper_symbol_definitions.entite : this.paper_symbol_definitions.entite_action;
- }
- }
- })
- }
- }
-
-
- },
- onIsHover(){
- // handle layer z-index
- if (this.is_hover) {
- this.paper_main_object.bringToFront();
- } else {
- // mapitem can be hover while an other mapitem is open if it is superposed (superposition) to the currently opened mapitem
- // in this case don't send it back
- if (!this.opened_concernement) {
- this.paper_main_object.sendToBack();
- }
- }
- // hightlight superposed entites on focus
- let entites_superposes = this.paper_main_object.children['entites_superposes'];
- // console.log('entites_superposes.children', entites_superposes.children);
- if(entites_superposes){
- for(let paper_item of entites_superposes.children) {
- if (this.is_hover) {
- paper_item.definition = this.paper_symbol_definitions.entite_hover;
- // paper_item.scale(2)
- } else {
- paper_item.definition = this.paper_symbol_definitions.entite;
- // paper_item.scale(0.5)
- }
- }
- }
- },
- // PAPER EVENTS
- initPaperEvents(){
- this.paper_main_object.onMouseLeave = function(event){
- if (!this.opened_concernement && this.isFocused()) { // only if no concernement is opened
- this.resetHoverElmt();
- document.body.style.cursor = "auto";
- }
- }.bind(this);
- this.paper_main_object.onMouseMove = function(event){
- console.log(`onmousemove ${this.id}`, this.cartouch_is_opened);
- // prevent hover map item mouse event if cartouch is opened
- if (this.cartouch_is_opened && this.map_mode !== "superposition") return;
-
- if (!this.is_open) {
- if (!this.opened_concernement) { // only if no concernement is opened and is this focused
- if(this.isFocused()){
- if (this.map_mode === 'superposition') {
- // get the superposed entite
- this.setHoverElmt({
- type: 'superposition',
- id: this.id,
- cid: this.cid,
- eids: this.superposedEntitesIDsList
- });
- } else{
- this.setHoverElmt({
- type: 'concernement',
- id: this.id,
- cid: this.cid
- });
- }
- document.body.style.cursor = "pointer";
- }
- } else if (this.map_mode === 'superposition'){
- // if this mapitem is superposed to the opened mapitem
- if(this.opened_concernement.all_superposed_concernements_id.indexOf(this.cid) >= 0){
- this.setHoverElmt({
- type: 'superposition',
- id: this.id,
- cid: this.cid,
- eids: this.superposedEntitesIDsList
- });
- document.body.style.cursor = "pointer";
- }
- }
- } else {
-
- // lets define some options regarding the map_mode
- let paper_group_tohit;
- switch (this.map_mode) {
- case "terraindevie":
- paper_group_tohit = this.paper_main_object.children['entites'];
- break;
- case "superposition":
- paper_group_tohit = this.paper_main_object.children['entites_superposes'];
- break;
- case "action":
- paper_group_tohit = this.paper_main_object.children['agissantes'];
- break;
- case "puissancedagir":
- paper_group_tohit = this.paper_main_object.children['puissanceagir_besoins'];
- break;
- case "doleancer":
- if(this.paper_main_object.children['doleances']){
- paper_group_tohit = this.paper_main_object.children['doleances'].children[`doleance_${this.concernement.opened_doleance.id}`];
- }
- break;
- }
- let result = paper_group_tohit ? paper_group_tohit.hitTest(event.point) : null;
- // console.log('move result', result);
- if (result && result.item.item_id) {
- // console.log('move has result', result);
- let new_hover_elmt = {
- paper_id: result.item.id,
- type: result.item.item_type,
- id: result.item.item_id
- };
- switch (result.item.item_type) {
- case "besoin":
- new_hover_elmt.no_popup = true;
- break;
- case "reponse":
- new_hover_elmt.bid = result.item.item_bid;
- new_hover_elmt.cid = result.item.item_cid;
- new_hover_elmt.no_popup = true;
- break;
- }
- if (!this.hover_elmt || new_hover_elmt.paper_id !== this.hover_elmt.paper_id) {
- // console.log(`before setHoverElmt ${this.id}`);
- this.setHoverElmt(new_hover_elmt);
- }
- document.body.style.cursor = "pointer";
- } else {
- // console.log('move no result');
- this.resetHoverElmt();
- document.body.style.cursor = "auto";
- }
- }
- }.bind(this);
-
- this.paper_main_object.onClick = async function(event){
- console.log('paper concernement onClick');
-
- // prevent hover map item mouse event if cartouch is opened
- if (this.cartouch_is_opened) return;
-
- if (!this.is_open) { // si ce concernement n'est pas ouvet
- console.log('mapitem is NOT opened');
- if (!this.opened_concernement) { // si aucun concernement n'est ouvert
- console.log(`Open me ${this.id}`);
- // push route (keep the hash for map_mode)
- // wait for routing to be finished before opening the mapItem
- await this.$router.push({
- name: 'concernement',
- params: {cid: parseInt(this.cid)},
- query: {
- mapitemid: this.id,
- superposition_id: this.mapitem.superposition_ids[0]
- },
- hash: `#${this.map_mode}`
- });
- // open/close all concernements
- this.openCloseConcernements(this.cid, this.id)
- // reset the mousehover
- this.resetHoverElmt();
- } else if (this.map_mode === 'superposition'){
- // if this mapitem is superposed to the opened mapitem
- if(this.opened_concernement.all_superposed_concernements_id.indexOf(this.cid) >= 0){
- // push route (keep the hash for map_mode)
- // wait for routing to be finished before opening the mapItem
- console.log('click on superposed this.mapitem.superposition_ids', this.mapitem.superposition_ids);
- await this.$router.push({
- name: 'concernement',
- params: {cid: this.opened_concernement.cid},
- query: {
- mapitemid: this.opened_concernement.opened_mapitem_id,
- superposition_id: this.mapitem.superposition_ids[0]
- },
- hash: `#${this.map_mode}`
- });
- }
- }
- } else { // si ce concernement est ouvert
- console.log('mapitem is opened');
- // lets define some options regarding the map_mode
- let group_to_hit = null;
- switch (this.map_mode) {
- case "terraindevie":
- group_to_hit = this.paper_main_object.children['entites'];
- break;
- case "superposition":
- group_to_hit = this.paper_main_object.children['entites_superposes'];
- break;
- case "action":
- group_to_hit = this.paper_main_object.children['agissantes'];
- break;
- case "doleancer":
- group_to_hit = this.paper_main_object.children['doleances'].children[`doleance_${this.concernement.opened_doleance.id}`];
- break;
- }
- if (group_to_hit) {
- let result = group_to_hit.hitTest(event.point);
- console.log('click result', result);
- if (result) {
- switch (this.map_mode) {
- case "terraindevie":
- case "superposition":
- case "action":
- // we have clicked on an entite
- this.$router.push({
- name: 'concernement',
- params: {cid: this.cid, eid: result.item.item_id},
- query: {
- mapitemid: this.id,
- superposition_id: this.mapitem.superposition_ids[0]
- },
- hash: `#${this.map_mode}`,
- });
- break;
- case "doleancer":
- this.setOpenedDoleanceField(this.cid, result.item.did, result.item.field, result.item.field_index);
- break;
- }
-
- } else {
- // otherwise we close the entite and come back to the concernement
- this.$router.push({
- name: 'concernement',
- hash: `#${this.map_mode}`,
- params: {id: this.cid, mapitemid: this.id}
- });
- // reset the mousehover
- this.resetHoverElmt();
- }
- }
- }
- }.bind(this);
- },
- resetHoverElmt(){
- // console.log('resetHoverElmt');
- setTimeout(()=>{
- this.setHoverElmt(null);
- }, 100);
- },
- // OPEN / CLOSE (with tween)
- openClose(open) { // async
- // await nextTick(); // not working
- console.log(`ConcernementsMapItem ${this.id} openClose: ${open}`);
- if (this.tween) {
- this.tween.stop();
- }
- if (open) {
- this.is_opening = true;
- // create the paper objects to display (like entite, besoin, etc)
- this.setPaperContents();
- this.handlePaperVisibilityOnBeforeOpen();
- // calcul opened size regarding window size and surounding contents
- let header = document.querySelector('header#header');
- let header_height = header.clientHeight;
- let map_nav = document.querySelector('nav#map-nav');
- let map_nav_height = map_nav.clientHeight;
- let s_h = (this.canvas.height - header_height - map_nav_height) / (this.ray*2*1.15);
- let s_w = (this.canvas.width - this.cartouch_width) / (this.ray*2*1.7);
- let s = Math.min(s_h, s_w)
-
- // create once the opening tweening
- this.tween = new Tween.Tween({s: this.scale, x: this.pos.x, y: this.pos.y, o: 0})
- .to({
- s: s,
- x: (this.canvas.width - this.cartouch_width) / 2,
- y: this.canvas.height / 2,
- o: 0.8
- }, 800)
- .onUpdate((obj) => {
- // https://github.com/liabru/matter-js/issues/986#issuecomment-812488873
- // revert to the original size (by reverting the previous scale)
- Matter.Body.scale(this.body, 1 / this.scale, 1 / this.scale)
- this.paper_main_object.scale(1 / this.scale);
- // then scale again to new scale
- Matter.Body.scale(this.body, obj.s, obj.s)
- this.paper_main_object.scale(obj.s);
- // update superposition constraints points poisitions
- if (this.concernement.superposition_constraints_id
- && this.concernement.superposition_constraints_id[this.id]
- && this.concernement.superposition_constraints_id[this.id].length)
- {
- // get all the constraints of the world
- let all_constrains = Matter.Composite.allConstraints(this.matterEngine.world);
- // loop through all constraint ids recorded in the concernement
- // get only the constraint of this concernement mapitem
- for(let constraint_id of this.concernement.superposition_constraints_id[this.id]) {
- // get the right constraint object from matter
- let constraint;
- for (const c of all_constrains) {
- if (c.id === constraint_id) {
- constraint = c;
- break;
- }
- }
- if (constraint) {
- // tween the constraint point
- let ab = this.cid === constraint.concernementA.id ? 'A' : 'B';
- let point = constraint[`point${ab}`];
- // revert to the original point
- let oripoint = Matter.Vector.create(point.x / this.scale, point.y / this.scale)
- // newpoint from original point
- let newpoint = Matter.Vector.create(oripoint.x * obj.s, oripoint.y * obj.s)
- constraint[`point${ab}`] = newpoint;
- }
- }
- }
- // record new scale
- this.prev_scale = this.scale;
- this.scale = obj.s;
- this.opacity = obj.o;
- // console.log('tween update obj.s', obj.s);
- this.pos = {x:obj.x, y:obj.y};
- Matter.Body.setPosition(this.body, this.pos);
- })
- .onComplete((obj) => {
- // console.log('tween complete obj.s', obj.s);
- // record tween one last time
- this.prev_scale = this.scale = obj.s;
- this.opacity = obj.o;
- this.pos = {x:obj.x, y:obj.y};
- Matter.Body.setPosition(this.body, this.pos);
-
- this.handlePaperVisibilityOnOpened();
- // fix the concernement position with a constraint
- this.constraint = Matter.Constraint.create({
- pointA: this.pos,
- bodyB: this.body,
- stiffness: 1,
- damping: 0,
- length: 0
- });
- Matter.Composite.add(this.matterEngine.world, [this.body, this.constraint]);
-
- // paper bring to front
- // this.paper_main_object.bringToFront();
- this.paper_main_object.sendToBack();
- this.is_opening = false;
- });
- // recreate the matter engine event to get it a the end of the events stack
- Matter.Events.off(this.matterEngine, "afterUpdate", this.onAfterEngineUpdate);
- Matter.Events.on(this.matterEngine, "afterUpdate", this.onAfterEngineUpdate);
- } else {
- // closing
- this.is_closing = true;
- if(this.constraint){
- Matter.Composite.remove(this.matterEngine.world, this.constraint);
- }
- this.concernement.active_revision = this.concernement.revision_id;
- this.handlePaperVisibilityOnBeforeClose();
- // this.setOpenedRecit(null);
- // create once the closing tween
- this.tween = new Tween.Tween({s: this.scale, o: 1})
- .to({s: 1, o: 0}, 500)
- .onUpdate((obj) => {
- // https://github.com/liabru/matter-js/issues/986#issuecomment-812488873
- // revert to the original size (by reverting the previous scale)
- Matter.Body.scale(this.body, 1 / this.scale, 1 / this.scale)
- this.paper_main_object.scale(1 / this.scale);
- // then scale again to new scale
- Matter.Body.scale(this.body, obj.s, obj.s)
- this.paper_main_object.scale(obj.s);
-
- // update superposition constraints points positions
- if (this.concernement.superposition_constraints_id
- && this.concernement.superposition_constraints_id[this.id]
- && this.concernement.superposition_constraints_id[this.id].length)
- {
- // get all the constraints of the world
- let all_constrains = Matter.Composite.allConstraints(this.matterEngine.world);
- // loop through all constraint ids recorded in the concernement
- // get only the constraint of this concernement mapitem
- for(let constraint_id of this.concernement.superposition_constraints_id[this.id]) {
- // get the right constraint object from matter
- let constraint;
- for (const c of all_constrains) {
- if (c.id === constraint_id) {
- constraint = c;
- break;
- }
- }
- if (constraint) {
- // tween the constraint point
- let ab = this.cid === constraint.concernementA.id ? 'A' : 'B';
- let point = constraint[`point${ab}`];
- // revert to the original point
- let oripoint = Matter.Vector.create(point.x / this.scale, point.y / this.scale)
- // newpoint from original point
- let newpoint = Matter.Vector.create(oripoint.x * obj.s, oripoint.y * obj.s)
- constraint[`point${ab}`] = newpoint;
- }
- }
- }
- // record new scale
- this.prev_scale = this.scale;
- this.scale = obj.s;
- this.opacity = obj.o;
- })
- .onComplete((obj) => {
- this.prev_scale = this.scale = 1;
- this.handlePaperVisibilityOnClosed();
- this.clearPaperContents();
- this.is_closing = false;
- });
- }
- this.tween.easing(Tween.Easing.Quadratic.InOut).start();
- },
- // ENGINE UPDATE
- onBeforeEngineUpdate (event) {
- // update the opening/closing tweening
- if (this.tween) {
- this.tween.update();
- }
- if (this.opened_concernement) {
- // console.log("try to push aside", this.opened_concernement.opened_mapitem_id, this.id, this.opened_concernement.superposed_mapitem_id_by_mapitem_id[this.opened_concernement.opened_mapitem_id]);
- // console.log(this.id, this.opened_concernement.superposed_mapitem_id_by_mapitem_id[this.opened_concernement.opened_mapitem_id].indexOf(this.id));
- if (this.opened_concernement.opened_mapitem_id !== this.id) {
- // push all aside mapitems not superposed the the opened mapitem
- let pushaside = true;
- // BUT NOT push aside mapitems superposed to superposed mapitems
- // opened_mapitem <-- superposed_mapitems <-- superposed_mapitem
- if (this.opened_concernement.superposed_mapitem_id_by_mapitem_id
- && this.opened_concernement.superposed_mapitem_id_by_mapitem_id[this.opened_concernement.opened_mapitem_id])
- { // if opened mapitem has superposed mapitems
- let superposed_ids = this.opened_concernement.superposed_mapitem_id_by_mapitem_id[this.opened_concernement.opened_mapitem_id]
- if (superposed_ids.indexOf(this.id) >= 0) { //this mapitem is directly superposed to the opened mapitem
- pushaside = false;
- } else { // else we look for second stage of the rockette ... superposed to superposed to opened
- superposed_ids.forEach(mapitem_id => { // for each superposed map_item, check if this mapitem is in their superposed
- let mapitem = this.allMapItems_byid[mapitem_id]; // get the superposed (stage 1) mapitem
- mapitem.superposition_ids.forEach(sup_id => { // for each superposed (stage 2) of the superposed (stage 1)
- if (this.mapitem.superposition_ids.indexOf(sup_id) >= 0) {
- pushaside = false;
- }
- });
- });
- }
- }
- if (pushaside) {
- this.pushAside()
- }
- }
- } else if (!this.is_hover){
- if (this.map_mode === 'proximite'
- || this.map_mode === 'superposition'
- || this.map_mode === 'puissancedagir'
- || this.map_mode === 'action'
- || this.map_mode === 'doleancer'){ // apply focus forces : move unfocused on the sides and focused on the center
- this.applyFocusForces(); //
- } else {
- this.applyNormalForces(); // if terrain de vie apply force to gently reject items from the sides and so create a continuasly mvmt
- }
- } else {
- // stop movement if is mouse hover
- Matter.Body.setVelocity(this.body, {x:0, y:0})
- }
-
- // reset all matter rotation forces otherwise items will spin when colide
- Matter.Body.setAngle(this.body, 0);
- Matter.Body.setAngularSpeed(this.body, 0);
- },
- applyFocusForces(){
- if(!this.isFocused()) {
- this.pushAside()
- }else{
- this.bringToCenter()
- }
- },
- isFocused(){
- return this.map_mode === 'terraindevie'
- || (this.map_mode === 'proximite' && this.concernement.has_proximites)
- || (this.map_mode === 'superposition' && this.concernement.has_superpositions)
- || (this.map_mode === 'action' && this.concernement.has_agissantes)
- || (this.map_mode === 'puissancedagir' && this.concernement.has_puissancedagir)
- || (this.map_mode === 'doleancer' && this.concernement.has_doleance);
- },
- pushAside(){
- // console.log('pushAside');
- // apply a force in direction of one side or an other depending of the start position
- // the force is exponentialy proportional to the distance from the side
- // INFO logarithmic force : https://stackoverflow.com/questions/846221/logarithmic-slider/846249#846249
- // TODO cartouch width should change regarding actual cartouch is opened or not (and how many cartouch are opened)
- let pseudo_center_x = this.opened_concernement
- ? (this.canvas.width - this.cartouch_width) / 2
- : this.canvas.width / 2;
- // get the direction to the closest side
- let dir = this.map_mode === 'superposition'
- && this.concernement.superposition_constraints_id
- && this.concernement.superposition_constraints_id[this.id]
- && this.concernement.superposition_constraints_id[this.id].length // go to the right if has superposition constraint applied
- ? 1 // to the right
- : this.pos.x > pseudo_center_x // else
- ? 1 // to the right
- : -1; // to the left
- // max and min item position
- let minp = 0;
- let maxp = dir < 0
- ? pseudo_center_x
- : this.canvas.width - pseudo_center_x;
- // max and min force
- let minf = 0;
- let maxf = 6;
- // scale factor
- let scale = (maxf-minf) / (maxp-minp);
- // get the inversed distance
- let dist = dir < 0
- ? this.pos.x
- : this.canvas.width - this.pos.x; // get the distance from the side
- // // calculate the force
- // let x_force = Math.pow(dist/700,100) * dir;
- // calculate the logarithmic force
- let x_force = Math.exp(minf + scale*(dist-minp)) * dir;
- let ori_pos = {x:pseudo_center_x, y:this.body.position.y};
- Matter.Body.applyForce(
- this.body,
- ori_pos,
- {
- x: x_force,
- y: 0
- }
- );
- this.body.frictionAir = 0.01;
- },
- bringToCenter(){
- // bring to the centre
- // apply a force in direction of one side or an other depending of the start position
- // the force is exponentialy inversed proportional to the distance from the side
- // INFO logarithmic force : https://stackoverflow.com/questions/846221/logarithmic-slider/846249#846249
- // TODO cartouch width should change regarding actual cartouch is opened or not (and how many cartouch are opened)
- let pseudo_center_x = this.opened_concernement
- ? (this.canvas.width - this.cartouch_width) / 2
- : this.canvas.width / 2;
- let dir = this.pos.x > pseudo_center_x
- ? -1 // to left
- : 1; // to right
- // get the inversed distance from the side
- let dist = dir < 0
- ? this.pos.x - pseudo_center_x
- : pseudo_center_x - this.pos.x;
- if (dist > this.canvas.width/6) { // apply decreasing forces and increasing friction air only out of center to let the items float in the center zone
- // max & min item position
- let minp = 0;
- let maxp = dir < 0
- ? this.canvas.width - pseudo_center_x
- : pseudo_center_x;
-
- // X force decrsinsing near the center
- // max and min force
- let xminf = 0;
- let xmaxf = 1 + Math.random()*4;
- // scale factor
- let xscale = (xmaxf-xminf) / (maxp-minp);
- let x_force = Math.exp(xminf + xscale*(dist-minp)) * dir;
- let ori_pos = dir < 0
- ? {x:this.canvas.width, y:this.body.position.y}
- : {x:0, y:this.body.position.y};
- Matter.Body.applyForce(
- this.body,
- ori_pos,
- {
- x: x_force,
- y: 0
- }
- );
-
- // Friction air fa (increasing near the center)
- let fa_minf = 0;
- let fa_maxf = 6;
- // scale factor
- let fa_scale = (fa_maxf-fa_minf) / (maxp-minp);
- let fa = Math.exp(fa_minf + fa_scale*(dist-minp)*-1);
- this.body.frictionAir = fa;
-
- // console.log(`bringToCenter dist:${dist}, x_force:${x_force}, friction air:${fa}`);
- } else { // in the ceneter zone let items floats freely
- let fa = 0.01;
- let velocity = Matter.Body.getVelocity(this.body);
- if (velocity.x) {
- let velocityx = Math.abs(velocity.x);
- // map a range of numbers to another range of numbers
- // INFO https://stackoverflow.com/a/46462321
- let velocity_range = [50, 1000];
- let fa_range = [0,3];
- fa = fa_range[0] + (velocityx - velocity_range[0]) * (fa_range[1] - fa_range[0]) / (velocity_range[1] - velocity_range[0]);
- // console.log(`bringToCenter velocityx:${velocityx}, fa:${fa}, velocity`, velocity);
- } else {
- console.warn(`bringToCenter no velocity`, velocity);
- }
- this.body.frictionAir = fa;
- }
- },
- applyShuffleForces() {
- // console.log('applyShuffleForces');
- // var dist, dir, x_velocity;
- // dir = this.pos.x > this.canvas.width/2 ? -1 : 1; // get the direction to the centre
- // dist = (dir < 0 ? this.pos.x - this.canvas.width/2 : this.canvas.width/2 - this.pos.x); // get the distance from the side
- // x_velocity = Math.pow(dist/650,10) * dir;
- // TODO cartouch width should change regarding actual cartouch is opened or not (and how many cartouch are opened)
- let pseudo_center_x = this.opened_concernement
- ? (this.canvas.width - this.cartouch_width) / 2
- : this.canvas.width / 2;
- // get the direction to the centre
- let dir = this.pos.x > pseudo_center_x
- ? -1 // to left
- : 1; // to right
- // get the inversed distance from the side
- let dist = dir < 0
- ? this.pos.x - pseudo_center_x
- : pseudo_center_x - this.pos.x;
- dist = dist > 1000 ? 1000 : dist;
-
- if (dist > this.canvas.width/6) { // apply decreasing forces and increasing friction air only out of center to let the items float in the center zone
- // max & min item position
- let minp = 0;
- let maxp = dir < 0
- ? this.canvas.width - pseudo_center_x
- : pseudo_center_x;
- // X max and min force
- let xminf = 0;
- let xmaxf = 4 + Math.random()*3;
- // scale factor
- let xscale = (xmaxf-xminf) / (maxp-minp);
-
- let x_velocity = Math.exp(xminf + xscale*(dist-minp))*dir;
- // let y_velocity = 30 + Math.random() * 50;
- // y_velocity = Math.random() > 0.5 ? -y_velocity : y_velocity;
- // X max and min force
- let yminf = 1;
- let ymaxf = 2 + Math.random()*4;
- // scale factor
- let yscale = (ymaxf-yminf) / (maxp-minp);
-
- let y_velocity = Math.exp(yminf + yscale*(dist-minp)) * (Math.random() > 0.5 ? 1 : -1); // let ori_pos = dir < 0
- // ? {x:this.canvas.width, y:this.body.position.y}
- // : {x:0, y:this.body.position.y};
- // let x_force = Math.pow(dist/800,10) * dir;
- console.log(`applyShuffleForces dir:${dir}, maxp:${maxp}, dist:${dist}, x_velocity:${x_velocity}, y_velocity:${y_velocity}`);
- Matter.Body.setVelocity(this.body, {x: x_velocity, y: y_velocity});
- } else { // if in center zone real shuffle velocity
- // x_velocity = -50 + Math.random()*100;
- // y_velocity = -50 + Math.random()*100;
- // this.setInitBodyVelocity();
- }
-
- this.body.frictionAir = 0.01;
- },
- applyNormalForces () {
- // bring gently to the centre
- // apply a force in direction of one side or an other depending of the start position
- // the force is exponentialy inversed proportional to the distance from the side
- // INFO logarithmic force : https://stackoverflow.com/questions/846221/logarithmic-slider/846249#846249
- // TODO cartouch width should change regarding actual cartouch is opened or not (and how many cartouch are opened)
- // X
- let pseudo_center_x = this.opened_concernement
- ? (this.canvas.width - this.cartouch_width) / 2
- : this.canvas.width / 2;
- let xdir = this.pos.x > pseudo_center_x
- ? -1 // to left
- : 1; // to right
- // get the inversed distance from the side
- let xdist = xdir < 0
- ? this.pos.x - pseudo_center_x
- : pseudo_center_x - this.pos.x;
- // Y
- let pseudo_center_y = this.canvas.height / 2;
- let ydir = this.pos.y > pseudo_center_y
- ? -1 // to top
- : 1; // to bottom
- // get the inversed distance from the side
- let ydist = ydir < 0
- ? this.pos.y - pseudo_center_y
- : pseudo_center_y - this.pos.y;
- let k = 4;
- if (xdist > this.canvas.width/k || ydist > this.canvas.height/k) { // apply decreasing forces and increasing friction air only out of center to let the items float in the center zone
- // max and min force
- let minf = 0;
- let maxf = 0.1;
- // X
- // max & min item position
- let xminp = 0;
- let xmaxp = xdir < 0
- ? this.canvas.width - pseudo_center_x
- : pseudo_center_x;
- // X force decrsinsing near the center
- // scale factor
- let xscale = (maxf-minf) / (xmaxp-xminp);
- let x_force = Math.exp(minf + xscale*(xdist-xminp)) * xdir;
- let xori_pos = xdir < 0
- ? {x:this.canvas.width, y:this.body.position.y}
- : {x:0, y:this.body.position.y};
- Matter.Body.applyForce(
- this.body,
- xori_pos,
- {
- x: x_force,
- y: 0
- }
- );
- // Y
- // max & min item position
- let yminp = 0;
- let ymaxp = ydir < 0
- ? this.canvas.height - pseudo_center_y
- : pseudo_center_y;
- // X force decrsinsing near the center
- // scale factor
- let yscale = (maxf-minf) / (ymaxp-yminp);
- let y_force = Math.exp(minf + yscale*(ydist-xminp)) * ydir;
- let yori_pos = ydir < 0
- ? {x:this.body.position.x, y:this.canvas.height}
- : {x:this.body.position.x, y:0};
- Matter.Body.applyForce(
- this.body,
- yori_pos,
- {
- x: 0,
- y: y_force
- }
- );
-
- // // Friction air fa (increasing near the center)
- // let fa_minf = 0;
- // let fa_maxf = 6;
- // // scale factor
- // let fa_scale = (fa_maxf-fa_minf) / (maxp-minp);
- // let fa = Math.exp(fa_minf + fa_scale*(dist-minp)*-1);
- // this.body.frictionAir = fa;
-
- // console.log(`bringToCenter dist:${xdist}, x_force:${x_force}`);
- } else { // in the ceneter zone let items floats freely
- // let velocity = Matter.Body.getVelocity(this.body);
- // let velocityx = Math.abs(velocity.x);
- // // map a range of numbers to another range of numbers
- // // INFO https://stackoverflow.com/a/46462321
- // let velocity_range = [50, 1000];
- // let fa_range = [0,3];
- // let fa = fa_range[0] + (velocityx - velocity_range[0]) * (fa_range[1] - fa_range[0]) / (velocity_range[1] - velocity_range[0]);
- // console.log(`bringToCenter velocity.x:${velocity.x}, fa:${fa}`);
- // this.body.frictionAir = fa;
- this.body.frictionAir = 0.1;
- }
- },
- respawn() {
- // respawn element if outside screen
- if(this.pos.x <= 0
- || this.pos.x >= this.canvas.width
- || this.pos.y <= 0
- || this.pos.y >= this.canvas.height){
- this.pos = this.getRandomPos()
- Matter.Body.setPosition(this.body, {x:this.pos.x, y:this.pos.y});
- // this.setInitBodyVelocity();
- Matter.Body.setVelocity(this.body, {x:0,y:0});
- }
-
- },
- onAfterEngineUpdate (event) {
- this.respawn();
- this.paper_main_object.position = this.pos = this.body.position;
- this.handlePaperVisibilityOnAfterEnginUpdate()
- },
- },
- render() {
- // console.log('render()', this.ctx);
- },
- }
- </script>
|