pieChart.js 11 KB

12345
  1. /*
  2. All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. See https://js.arcgis.com/4.25/esri/copyright.txt for details.
  4. */
  5. import e from"../../Color.js";import"../../renderers/ClassBreaksRenderer.js";import"../../renderers/DictionaryRenderer.js";import"../../renderers/DotDensityRenderer.js";import"../../renderers/HeatmapRenderer.js";import r from"../../renderers/PieChartRenderer.js";import"../../renderers/Renderer.js";import"../../renderers/SimpleRenderer.js";import"../../renderers/UniqueValueRenderer.js";import"../../renderers/support/jsonUtils.js";import"../../symbols.js";import a from"../../core/Error.js";import{isSome as t}from"../../core/maybe.js";import{toPt as n}from"../../core/screenUtils.js";import{fetchMessageBundle as i}from"../../intl/messages.js";import s from"../../layers/support/AggregateField.js";import o from"../../layers/support/ExpressionInfo.js";import l from"../../renderers/support/AttributeColorInfo.js";import p from"../heuristics/outline.js";import u from"../heuristics/sizeRange.js";import{createVisualVariables as m}from"./size.js";import{createColors as c,createSymbol as d,getSymbolOutlineFromScheme as f,verifyBasicFieldValidity as b,getBasemapInfo as h}from"./support/utils.js";import y from"../statistics/predominantCategories.js";import{getSumOfAttributesExpr as w}from"../statistics/support/utils.js";import{verifyBinningParams as g}from"../support/binningUtils.js";import{getFieldsList as v}from"../support/utils.js";import{LayerType as z,binningCapableLayerTypes as E,createLayerAdapter as S,getLayerTypeLabels as j,getLayerTypes as C}from"../support/adapters/support/layerUtils.js";import{cloneScheme as x,getSchemes as V}from"../symbology/pieChart.js";import{getCIMSymbolColor as $}from"../../symbols/support/cimSymbolUtils.js";import T from"../../symbols/SimpleLineSymbol.js";const I=[z.CSVLayer,z.FeatureLayer,z.OGCFeatureLayer,z.GeoJSONLayer,z.WFSLayer];async function k(e){if(!(e&&e.layer&&e.view&&e.attributes?.length))throw new a("pie-chart-renderer:missing-parameters","'layer', 'view' and 'attributes' parameters are required");if(e.attributes.length>10)throw new a("pie-chart-renderer:invalid-parameters","PieChart renderer does not support more than 10 attributes");e.forBinning&&g(e,"pie-chart-renderer");const r={...e};r.shape=r.shape||"pie",r.othersCategoryEnabled=null==r.othersCategoryEnabled||r.othersCategoryEnabled,r.includeSizeVariable=e.includeSizeVariable||!1;const n=e.forBinning?E:I,i=S(r.layer,n,e.forBinning);if(r.layer=i,!i)throw new a("pie-chart-renderer:invalid-parameters","'layer' must be one of these types: "+j(n).join(", "));const s=t(r.signal)?{signal:r.signal}:null;await Promise.all([r.view.when(),i.load(s)]);const o=i.geometryType,l="polygon"===o,p="point"===o||"multipoint"===o||l;if(r.outlineOptimizationEnabled=!!l&&r.outlineOptimizationEnabled,r.sizeOptimizationEnabled=!!p&&r.sizeOptimizationEnabled,!p)throw new a("pie-chart-renderer:not-supported","PieChart renderer is only supported for point and polygon layers");const u=[],m=r.attributes;for(const a of m){const e=await v({field:a.field,valueExpression:a.valueExpression});u.push(...e)}const c=b(i,u.filter(Boolean),"pie-chart-renderer:invalid-parameters");if(c)throw c;return r}async function q(e){let r=e.pieChartScheme,a=null,n=null;const i=await h(e.basemap,e.view);if(a=t(i.basemapId)?i.basemapId:null,n=t(i.basemapTheme)?i.basemapTheme:null,r)return{scheme:x(r),basemapId:a,basemapTheme:n};const s=V({basemap:a,numColors:e.attributes.length,geometryType:e.layer.geometryType,basemapTheme:n});return s&&(r=s.primaryScheme,a=s.basemapId,n=s.basemapTheme),{scheme:r,basemapId:a,basemapTheme:n}}async function O(e,r){const{valueExpression:a,sqlExpression:t,sqlWhere:n}=w(e.attributes),s=await i("esri/smartMapping/t9n/smartMapping");return m({layer:e.layer,basemap:e.basemap,valueExpression:a,sqlExpression:t,sqlWhere:n,sizeScheme:r,sizeOptimizationEnabled:e.sizeOptimizationEnabled,legendOptions:{title:s.sumOfCategories},view:e.view,signal:e.signal})}async function B(e){const t=await k(e),i=await q(t),s=i?.scheme;if(!s)throw new a("pie-chart-renderer:insufficient-info","Unable to find pie-chart scheme");const o=t.layer,{includeSizeVariable:l,sizeOptimizationEnabled:m,outlineOptimizationEnabled:b,view:h,signal:w}=t,g=s.sizeScheme,v=t.attributes,z=v.map((e=>e.field)),[E,S,j,C]=await Promise.all([z.length>1?y({layer:o,fields:z,view:h,signal:w}):null,l?O(t,g):null,!l&&m?u({layer:o,view:h,signal:w}):null,b?p({layer:o,view:h,signal:w}):null]),V=E&&E.predominantCategoryInfos?{uniqueValueInfos:E.predominantCategoryInfos}:{uniqueValueInfos:z.map((e=>({value:e,count:0})))},$=c(s.colors,v.length),I=v.map(((e,r)=>({field:e.field,valueExpression:e.valueExpression,label:e.label,valueExpressionTitle:e.valueExpressionTitle,color:$[r]}))),B=o.geometryType,R="background"in g&&g.background,L=new r({attributes:I,othersCategory:{color:t.othersCategoryEnabled?s.colorForOthersCategory:null,threshold:.04},holePercentage:"donut"===t.shape?.45:0,backgroundFillSymbol:R?d(B,{type:"2d",color:R.color,outline:f(R,B,C?.opacity)}):null,size:n(s.size),outline:new T(f(s,"point",C?.opacity)),legendOptions:t.legendOptions});if(S&&(m||S.visualVariables.forEach((e=>{"number"==typeof e.minSize&&"number"==typeof e.maxSize&&(e.minSize*=2.5,e.maxSize*=1.8)})),m&&"point"===B&&S.visualVariables.forEach((e=>{e?.minSize&&"object"==typeof e.minSize&&e.minSize?.stops.forEach((e=>{e.size*=1.8}))})),L.authoringInfo=S.authoringInfo.clone(),L.visualVariables=S.visualVariables?.map((e=>e.clone()))),C?.visualVariables?.length){const e=C.visualVariables.map((e=>e.clone()));L.visualVariables?L.visualVariables.push(...e):L.visualVariables=e}return j?.minSize&&("point"===B&&j.minSize.stops.forEach((e=>{e.size*=2.5})),"polygon"===B&&j.minSize.stops.forEach((e=>{e.size*=1.8})),L.visualVariables?L.visualVariables.push(j.minSize):L.visualVariables=[j.minSize]),{renderer:L,pieChartScheme:x(s),size:S,basemapId:i.basemapId,basemapTheme:i.basemapTheme,statistics:V}}const R=["unique-value","class-breaks"],L=new e("#aaaaaa"),F=new e("#5c5c5c"),P=[new e("#e60049"),new e("#0bb4ff"),new e("#50e991"),new e("#e6d800"),new e("#9b19f5"),new e("#ffa300"),new e("#dc0ab4"),new e("#b3d4ff"),new e("#00bfa0"),new e("#f0cccc")];async function U(e){if(!e||!e.layer)throw new a("pie-chart-cluster-renderer:missing-parameters","'layer' parameter is required");const r={...e};r.shape=r.shape||"pie",r.defaultSymbolEnabled??(r.defaultSymbolEnabled=!0);const n=e.layer;if(!C(I).includes(n.type))throw new a("pie-chart-cluster-renderer:invalid-parameters","'layer' must be one of these types: "+j(I).join(", "));const i=t(r.signal)?{signal:r.signal}:null;await n.load(i);if(!("point"===n.geometryType))throw new a("pie-chart-cluster-renderer:invalid-parameters","Cluster renderers are only supported for point layers");const{renderer:s}=n;if(!s)throw new a("pie-chart-cluster-renderer:invalid-parameters","input layer does not have a renderer.");if(!R.includes(s.type))throw new a("pie-chart-cluster-renderer:invalid-parameters",`Cannot create a pie chart renderer for clusters based on a ${s.type} renderer.`);if("valueExpression"in s&&s.valueExpression)throw new a("pie-chart-cluster-renderer:invalid-parameters","Cannot create a pie chart renderer for clusters from a layer whose renderer contains a valueExpression.");if("unique-value"===s.type){if(s.field2)throw new a("pie-chart-cluster-renderer:invalid-parameters","Cannot create a pie chart renderer for clusters from a UniqueValueRenderer using more than one field.");if(s.uniqueValueInfos.length>10)throw new a("pie-chart-cluster-renderer:invalid-parameters","PieChart cluster renderer cannot be created from a UniqueValueRenderer with more than 10 unique value infos.")}if("class-breaks"===s.type){if(s.classBreakInfos.length<2)throw new a("pie-chart-cluster-renderer:invalid-parameters","Cannot create a pie chart renderer for clusters from a layer renderer with a continuous color or size gradient.");if(s.classBreakInfos.length>10)throw new a("pie-chart-cluster-renderer:invalid-parameters","PieChart cluster renderer can not be created from a ClassBreaksRenderer with more than 10 class break infos.");if("class-breaks-size"===s?.authoringInfo?.type)throw new a("pie-chart-cluster-renderer:invalid-parameters","PieChart cluster renderer can not be created from a ClassBreaksRenderer with breaks varied by size instead of color.")}return r}async function M(e){const a=await U(e),{layer:t,shape:n,defaultSymbolEnabled:s,legendOptions:o}=a,{renderer:p}=t,u=(await i("esri/smartMapping/t9n/smartMapping")).other;let m=[];"unique-value"===p.type&&(m=N({renderer:p,defaultSymbolEnabled:s,defaultLabelBackup:u})),"class-breaks"===p.type&&(m=_({renderer:p,defaultSymbolEnabled:s,defaultLabelBackup:u}));const c=[],d=[];for(const r of m){const{field:e,color:a}=r;c.push(e),d.push(new l({color:a,field:e.name,label:e.alias}))}return{fields:c,renderer:new r({attributes:d,legendOptions:o,holePercentage:"donut"===n?.45:0,outline:null,size:18,othersCategory:null})}}function N(e){const{renderer:r,defaultSymbolEnabled:a,defaultLabelBackup:t}=e,{field:n,uniqueValueInfos:i,defaultSymbol:l,defaultLabel:p}=r,u=l&&a,m=u?9:10,d=c(P,m),f=i.slice(0,m).map(((e,r)=>{const a=e.label,t=d[r];return{field:new s({name:A(e.value?.toString()),alias:a,onStatisticExpression:new o({title:`Field definition - ${a}`,expression:W(n,e),returnType:"number"}),statisticType:"sum"}),color:D(e.symbol,t)}}));if(u){const e="cluster_default",r=p||t;f.push({field:new s({name:A(e),alias:r,onStatisticExpression:new o({title:`Field definition - ${r}`,expression:G(n,i),returnType:"number"}),statisticType:"sum"}),color:D(l,F)})}return f}function _(e){const{renderer:r,defaultSymbolEnabled:a,defaultLabelBackup:t}=e,{field:n,classBreakInfos:i,defaultSymbol:l,defaultLabel:p}=r,u=l&&a,m=u?9:10,d=c(P,m),f=i.slice(0,m).map(((e,r)=>{const a=e.label||`${e.minValue} - ${e.maxValue}`,t=d[r];return{field:new s({name:A(a),alias:a,onStatisticExpression:new o({title:`Field definition - ${a}`,expression:H(n,e),returnType:"number"}),statisticType:"sum"}),color:D(e.symbol,t)}}));if(u){const e="cluster_default",r=p||t;f.push({field:new s({name:A(e),alias:r,onStatisticExpression:new o({title:`Field definition - ${r}`,expression:J(n,i),returnType:"number"}),statisticType:"sum"}),color:D(l,F)})}return f}function A(e){return"SUM_"+(e+"").replace(/[^a-zA-Z0-9_]/g,"_")}function D(e,r){if("simple-marker"===e.type&&e.color)return e.color.clone();if("cim"===e.type){const r=$(e);if(r)return r.clone()}return r?r.clone():L.clone()}function W(e,r){return`Number(Text($feature["${e}"]) == "${r.value+""}")`}function G(e,r){return`Number(!(${r.map((r=>`(Text($feature["${e}"]) == "${r.value+""}")`)).join(" || ")}))`}function H(e,r){return`Number($feature["${e}"] >= ${r.minValue} && $feature["${e}"] < ${r.maxValue})`}function J(e,r){return`Number(!(${r.map((r=>`($feature["${e}"] >= ${r.minValue} && $feature["${e}"] < ${r.maxValue})`)).join(" || ")}))`}export{B as createRenderer,M as createRendererForClustering};