zouyaoji / vue-cesium

🎉 Vue 3.x components for CesiumJS.
https://zouyaoji.top/vue-cesium
MIT License
1.47k stars 317 forks source link

PolylineArrowMaterialProperty cause 'Converting circular structure to JSON' error in customdatasource object watching, while splice element from datasource array #275

Closed liuganting closed 1 year ago

liuganting commented 1 year ago

my code:

__DataSourceEntityPushPolyline(id, type, posArray, start, end, data) {
  let lineColor = new this.Cesium.Color.fromCssColorString(ConstDefine.LineColor[type]);
  let linePosition = this.Cesium.Cartesian3.fromDegreesArray(posArray);
  let lineMaterial = lineColor; 
  let lineWidth = 2;
  if (type != ConstDefine.LineType.XXXX) {
    lineMaterial = new this.Cesium.PolylineArrowMaterialProperty(lineColor);
    lineWidth = 8;
  }

  this.DataSourceEntities.push({
    id: id,
    polyline: {
      positions: linePosition,
      width: lineWidth,
      // material: new self.Cesium.PolylineDashMaterialProperty({
      //   color: lineColor,
      // }),
      material: lineMaterial,
    },
    msg: {
      type: type,
      start: start,
      end: end,
      positions: posArray,
      data: data,
    },
  });

errorHandler.js?d656:24

   TypeError: Converting circular structure to JSON
--> starting at object with constructor 'PolylineArrowMaterialProperty'
|     property '_color' -> object with constructor 'ConstantProperty'
|     property '_definitionChanged' -> object with constructor 'Event'
|     property '_scopes' -> object with constructor 'Array'
--- index 0 closes the circle
at JSON.stringify (<anonymous>)
at unwatchFns.push.deep (index.mjs?9f50:44:1)
at callWithErrorHandling (runtime-core.esm-bundler.js?d2dd:155:1)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js?d2dd:164:1)
at Array.job (runtime-core.esm-bundler.js?d2dd:1782:1)
at flushPreFlushCbs (runtime-core.esm-bundler.js?d2dd:328:1)
at flushJobs (runtime-core.esm-bundler.js?d2dd:371:1)

index.mjs:

function useDatasources(props, ctx, vcInstance) { vcInstance.cesiumEvents = ["changedEvent", "errorEvent", "loadingEvent"]; if (vcInstance.cesiumClass === "KmlDataSource") { vcInstance.cesiumEvents.push("refreshEvent"); vcInstance.cesiumEvents.push("unsupportedNodeEvent"); } vcInstance.cesiumMembersEvents = [ { name: "clock", events: ["definitionChanged"] }, { name: "clustering", events: ["clusterEvent"] }, { name: "entities", events: ["collectionChanged"] } ]; const commonState = useCommon(props, ctx, vcInstance); if (commonState === void 0) { return; } vcInstance.alreadyListening.push("entities"); let unwatchFns = []; unwatchFns.push(watch(() => cloneDeep(props.entities), (newVal, oldVal) => { if (!vcInstance.mounted) { return; } const datasource = vcInstance.cesiumObject; if (newVal.length === oldVal.length) { const modifies = []; for (let i = 0; i < newVal.length; i++) { const options = newVal[i]; const oldOptions = oldVal[i]; if (JSON.stringify(options) !== JSON.stringify(oldOptions)) { modifies.push({ newOptions: options, oldOptions }); } } modifies.forEach((v) => { const modifyEntity = datasource.entities.getById(v.oldOptions.id); if (v.oldOptions.id === v.newOptions.id) { modifyEntity && Object.keys(v.newOptions).forEach((prop) => { if (v.oldOptions[prop] !== v.newOptions[prop]) { modifyEntity[prop] = commonState.transformProp(prop, v.newOptions[prop]); } }); } else { datasource.entities.remove(modifyEntity); const entityOptions = v.newOptions; addEntities(datasource, [entityOptions]); } }); } else { const addeds = differenceBy(newVal, oldVal, "id"); const deletes = differenceBy(oldVal, newVal, "id"); const deletedEntities = []; for (let i = 0; i < deletes.length; i++) { const deleteEntity = datasource.entities.getById(deletes[i].id); deletedEntities.push(deleteEntity); } deletedEntities.forEach((v) => { datasource.entities.remove(v); }); addEntities(datasource, addeds); } }, { deep: true }));

zouyaoji commented 1 year ago

Please change lineMaterial to plain object.

  let lineColor = ConstDefine.LineColor[type];
  let lineMaterial = lineColor; 
  let lineWidth = 2;
  if (type != ConstDefine.LineType.XXXX) {
    lineMaterial = {
       fabric: {
          type: 'PolylineArrow',
          uniforms: {
            color: lineColor;
          }
        }
      }
    };
    lineWidth = 8;
  }

In this way, the logic of actually instantiating the lineMaterial is placed in vue-cesium to avoid the object of the component watch being too complex (such as recursive properties) and throwing exceptions.

https://github.com/zouyaoji/vue-cesium/blob/dev/packages/utils/cesium-helpers.ts#L522

liuganting commented 1 year ago

fantastic,solved my problem perfectly !
thanks !