UNPKG

@expofp/floorplan

Version:

Interactive floor plan library for expos and events

2 lines (1 loc) • 8.13 kB
import{Rect as B}from"@expofp/geometry";import{update as H}from"@expofp/renderer";import{reaction as M}from"mobx";import{FONT_WEIGHT_PRIMARY_BOOTH as U,FONT_WEIGHT_PRIMARY_EXHIBITOR as V,FONT_WEIGHT_SECONDARY_BOOTH as Z,FONT_WEIGHT_SECONDARY_EXHIBITOR as X}from"../../../../constants";import c from"../../../../data";import{createShapeDot as G,createTextDef as Y,createTextDefLines as Q}from"../../../../engine/defs";import{DEFAULT_FONT_LIGHT_URL as $,DEFAULT_FONT_URL as W,loadCustomFontsUrls as q}from"../../../../engine/fonts";import{getQuarterTurns as j,getRollValue as k,rotateRectByQuarters as J,rotateTextDefByQuarters as K,updateLinesScale as tt}from"../../../../engine/update-def";import{boothStore as et,layersStore as it,uiState as f}from"../../../../store";import{RegularBooth as st,SpecialBooth as ot}from"../../../../store/BoothStore";import D from"../../../../tools/settings";import{t as S}from"../../../../utils/i18n";import nt from"../../../../utils/is-mobile";import at from"../../../../utils/is-webview";import{isArabicText as rt}from"../../../../utils/rtl";import{BoothDrawerBaseWithoutPainter as ht}from"./BoothDrawerBase";import{getFont as _}from"./canvases";import{getLabelBorderInset as lt}from"./label-inset.js";let z=D.boothLabelColor;D.EXPO==="tqs2021"&&(z="#000");const x=nt||at,F=n=>n.replace(" ","").substring(0,4).replace(/[0-9]/g,"3").replace(/[A-Z]/gi,"A"),I=document.createElement("canvas").getContext("2d");export default function ct(n){if(!(!(n instanceof st)||n.noLabels))return new BoothLabelDrawer(n)}export function getMinZoomFactorForDot(n){return Array.isArray(n)&&n.length>0?Math.max(...n.map(t=>t)):typeof n=="number"?n:-0}export const isDirectionsMode=()=>!!(f.selectedRoute?.from&&f.selectedRoute?.to);export function getFontUrlByWeight(n,t=[],e="normal"){return[...t,{weight:500,url:W,style:"normal"},{weight:300,url:$,style:"normal"}].find(s=>+s.weight===n&&s.style===e)?.url||W}function b(n,t){return Number(getComputedStyle(document.body).getPropertyValue(n))||t}export function getBoothLabelWeights(){return{main:b(U,500),details:b(Z,300)}}export function getExhibitorLabelWeights(){return{main:b(V,500),details:b(X,300)}}export function getBadgeFontWeight(){return getExhibitorLabelWeights().details}const y="Details";export class BoothLabelDrawer extends ht{constructor(t){super(t),this.minZoomDotVisible=0,this.maxZoomDotVisible=0,this.exh=[],this.shapeLabel=void 0,this.shapeDot=void 0,this.fontSizes=[[],[]],this.lines=[[],[]],this.fontUrls=["",""],this.canvasRect=new B(t.rect.center,t.rect.size,t.rotate,t.elevation),this.paddingScaled=[4,4],this.padding=lt(t.borderWidth||et.borderWidth,t.rect.size),this.topLeftAlignment={horizontal:f.rtl?"right":"left",vertical:"top"},this.centerAlignment={horizontal:"center",vertical:"center"},this.prefixes=x?[{fontSize:7,name:"XS",short:!0},{fontSize:10,name:"S",short:!0},{fontSize:16,name:y,short:!1}]:[{fontSize:7,name:"XS",short:!0},{fontSize:10,name:"S",short:!0},{fontSize:12,name:"M",short:!0},{fontSize:14,name:"L",short:!0},{fontSize:18,name:y,short:!1}],!(t instanceof ot)&&(this.exh=c.hideExhibitors?[]:c.onlyFeaturedExhibitors?t.exhibitors.filter(e=>e.featured):t.exhibitors,x&&this.optimizationLevel()>=3&&(this.prefixes=this.prefixes.filter(e=>e.name!=="S")),this.createLines(),this.calculateFontSizeFactors(),this.shapeLabel=Y(Q(this.lines,this.booth.labelColor||z,0,this.fontUrls),new B(this.booth.rect.center,this.booth.rect.size,this.booth.rotate,this.booth.elevation),[...this.paddingScaled],{horizontal:"left",vertical:"top"}),this.shapeLabel.onScale=({pixelSize:e})=>this.layOutLabel(e),this.getShapeDot(),M(()=>it.layersLoaded&&this.booth.skipDim===!0,e=>{this.shapeLabel.dim=e?0:void 0,this.shapeDot.dim=e?0:void 0,H(this.shapeLabel,this.shapeDot)}),M(()=>f.mapSettings,({roll:e})=>{k(e??0)&&(this.shapeLabel.onRoll=({roll:i,pixelSize:a})=>{const s=j(i,this.shapeLabel.bounds.rotation);if(s===0)return;const{size:r}=this.canvasRect;return this.shapeLabel=K(this.shapeLabel,s),!this.shapeLabel.hidden&&!this.exh.length&&r.x!==r.y&&(this.canvasRect=J(this.canvasRect,s),this.calculateFontSizeFactors(),this.layOutLabel(a),this.layOutDot(a)),[this.shapeLabel,this.shapeDot]})},{fireImmediately:!0}))}getShape(){return[this.shapeLabel,this.shapeDot]}layOutLabel(t){const e=this.lines[1]??[],i=this.fontSizes[1]??[];if(D.EXPO!=="wineparis2026"){const s=this.exh.length?this.topLeftAlignment:e.length?t<i[i.length-1].scaleFactor?this.topLeftAlignment:this.centerAlignment:this.topLeftAlignment;this.shapeLabel.alignment=s}return tt(this.shapeLabel.lines,t,this.fontSizes)?(this.shapeLabel.padding[0]=this.paddingScaled[0]*t+this.padding,this.shapeLabel.padding[1]=this.paddingScaled[1]*t+this.padding,[this.shapeLabel]):[]}layOutDot(t){const e=t>=this.minZoomDotVisible&&t<=this.maxZoomDotVisible;if(!e&&this.shapeDot.hidden)return[];const i=this.shapeDot.bounds,a=this.shapeDot.source;return i.scale({x:a.width*t/i.size.x,y:a.height*t/i.size.y},i.center,i),this.shapeDot.hidden=!e,[this.shapeDot]}getShapeDot(){this.shapeDot=G(this.canvasRect,this.booth.labelColor||z),this.shapeDot.hidden=!0,this.shapeDot.onScale=({pixelSize:e})=>this.layOutDot(e);const t=this.shapeDot.source;this.maxZoomDotVisible=Math.min(this.canvasRect.size.x/t.width,this.canvasRect.size.y/t.height)}createLines(){const t=this.booth,e=[],i=[],a=x&&this.optimizationLevel()>=3?1:3;if(this.exh.length){const s=t.exhibitors.filter(o=>o.order===0),r=t.exhibitors.filter(o=>o.order);if(s.length>0)e.push(...s.map(o=>o.name));else if(c.onlyFeaturedExhibitors)e.push(...t.exhibitors.filter(o=>o.featured).map(o=>o.name));else if(r.length>0){e.push(...r.map(m=>m.name));const o=t.exhibitors.filter(m=>m.order===void 0);o.length>0&&e.push(S("and {{moreCount}} more",{moreCount:o.length}))}else t.exhibitors.length>a?e.push(`${t.exhibitors.length} ${c.exhibitorTermPlural}`):e.push(...t.exhibitors.map(o=>o.name));i.push(t.title||t.name)}else{const s=!!t.exhibitors.length;e.push(t.title||t.name),t.onHold?i.push(S("On Hold")):t.reserved?i.push(S("Reserved")):s||i.push(...t.exhibitors.map(r=>r.name).sort((r,o)=>r>o?1:-1)),t.size&&i.push(t.size.indexOf("/")>-1?t.size.substring(0,t.size.indexOf("/")).trim():t.size),t.price&&t.price!=="0"&&!f.previewMode&&i.push(t.price)}f.rtl&&e.forEach((s,r)=>{(s.endsWith(".")||s.endsWith("!")||s.endsWith("?"))&&(e[r]=e[r]+"\u200F"),rt(s)&&(e[r]=e[r]+" ")}),this.lines=[e,i]}calculateFontSizeFactors(){const t=this.lines[0];let e;const i=this.canvasRect,a=[],s=[],r=this.prefixes.slice(0,this.exh.length?this.prefixes.length:this.prefixes.length-1),{main:o,details:m}=this.exh.length?getExhibitorLabelWeights():getBoothLabelWeights();for(const{fontSize:l,short:u}of r){const p=l*devicePixelRatio,L=.9*l*devicePixelRatio,d=_(p,o),T=_(L,m),O=c.hideExhibitorBoothNumber||u;let w,A,v,g;if(this.exh.length)e=u?[]:this.lines[1],v=Math.max(...t.map(h=>this.measureText(h,d).width),...e.map(h=>this.measureText(h,T).width)),w=Math.max(...t.map(h=>this.exh.length?this.measureText(F(h),d).width:this.measureText(F(h),d).width+3+3),...e.map(h=>this.measureText(F(h),T).width)),g=p*t.length+L*e.length+devicePixelRatio*(t.length+e.length)+3,A=O?g/t.length:null;else{const h=t[0].replace(/[0-9]/g,"3").replace(/[A-Z]/g,"A"),N=4;v=this.measureText(h,d).width+3+3,g=p+N}const P=i.size.x/(w||v),C=i.size.y/(A||g),E=Math.min(P,C);a.push({scaleFactor:E,value:p,lines:[]}),O||s.push({scaleFactor:E,value:L,lines:[]})}if(!this.exh.length){const l=a[a.length-1],u=this.prefixes.find(p=>p.name===y);u&&(a.push({scaleFactor:l.scaleFactor/1.8,value:u.fontSize*devicePixelRatio,lines:[]}),s.push({scaleFactor:l.scaleFactor/1.8,value:u.fontSize*(x?1:.9)*devicePixelRatio,lines:[]}))}const R=q();this.fontUrls=[getFontUrlByWeight(o,R),getFontUrlByWeight(m,R)],this.minZoomDotVisible=getMinZoomFactorForDot(a.map(l=>l.scaleFactor)),this.fontSizes=[a,s]}calcArea(t,e){return Math.floor(Math.max(0,t)*Math.max(0,e)/1e3)}optimizationLevel(){return Math.min(c.viewOptimizationLevel?c.viewOptimizationLevel:Math.floor(this.calcArea(this.canvasRect.size.x,this.canvasRect.size.y)/5e3),3)}measureText(t,e){return I.font=e,I.measureText(t)}}