An example from Sandcastle doesn't work

Hello Cesium team,

As far as Cesium is concerned, I am totally inexperienced and try to get used to it. So I would be very happy if you could help me.

My goal in a project is that I can mark / draw an area on the map and save the coordinates in a database (MySQL).

Later I would like to display several areas on the map with the saved coordinates.

I found an example of this at the Sandcastle that almost meets my goal. Here is the link to it:

My project is built with Webpack, like the proposed repository in another thread.

I added the code from the Sandcastle to my Typescript file and the VSCode shows me a lot of errors that I don’t quite understand. I would be very happy if you can help me get the example running.



Furthermore, a CSS file is imported here in the HTML area.
Is this also necessary for me, if so, where can I also import this file?
image

I ask for help.
I can’t do it alone and all searches on the Internet didn’t help me either.

Thank you in advance for all the trouble.

Many greetings

Hi,

you import cesium objects inside library:

import {
blabla
....
} from "cesium"

in your code there is lines for like this:

you need to delete Cesium and you need to import from cesium library.
like this:

import {
blabla
....
Color
} from "ceisum"


Cesium.Color // turn this to below
Color

I dont know others may be its about type script I cant understand German.

Hello HĂĽseyin,

thank you for the answer.
But unfortunately that didn’t work that way for me. I have already tested this like this.

I’ve done it this way in the meantime and that helped me a bit.

import * as Cesium from "cesium";

I only have an error in one place, but despite the errors it works wonderfully in the browser.

The error message (translated) is:

The "setValue" property does not exist for the "PositionProperty" type. Do you mean "getValue"? Ts (2551)
Cesium.d.ts (23197, 5): "getValue" is declared here.

I don’t quite get the sense of the line either. Since everything works wonderfully even without the line. I cannot explain why the positions have to be saved separately here. I tested it by commenting out the line.

Even the InfoPanel is below the map. Is there a way to do it like you can see on the demo?
Here is a screenshot of how I can currently see it:
image

I look forward to every little help and thank you in advance.

Many greetings

Hi Mr.Lion,

first the imports:
IN my opinion, just try import Cesium from "cesium";. That way you should be able to get all functions etc. like “Cesium.xyz…”

second the Property thingy:
There is no method “setValue” in Cesium for this Porperty (Documentation)

third the InfoPanel:
This error is looking like something is wrong with your CSS code.

INFO: I am not familiar with Webpack etc. so all this is solely based on my Javascript/Cesium knowledge

Best, Lennart

Hi Lennart,

Thanks for the answer.

Yes, that worked too. Great, I’m learning something about it :wink:

Yes, I read that in the documentation too. But why does it work anyway and what would be the right thing here or how could we improve the line?
I got this error from the demo. Look here:

I couldn’t take the CSS part from the demo area. What do I have to write as CSS?

I successfully solved the Webpack area and it works so far. It is important for me if I could get support in the area of Cesium and JS.

Many greetings

@Mr.Lion,
I noticed something:

What is the purpose of the “?” and “!” before the method call? Maybe thats the problem?

And on the CSS:
If you build your own page, u can’t use Sandcastle HTML-code 1:1, because it’s a little bit different, if I remember correctly (the imported “bucket.css” is Sandcastle specific).

I’m using TS (Typescript) and “?” and “!” is there to check whether the variable is undefined or null.
The line appears without the “?” marked completely in red. So it is right to at least one thing.

Okay, do I have to create my own here then?
How could I do that with the dropdown like you can see in the demo here with me?

Hi @Mr.Lion,

sadly I can’t help you with the the error in your TS code.
For all my CSS questions/problems I mostly use the site https://www.w3schools.com/css/default.asp, it’s really helping me.
Specific for dropdowns the following link: CSS Dropdowns (w3schools.com).

You can really do some nice things with CSS, if you go overboard with your Code.

Best, Lennart

Hello!

I have a little bit of experience with Cesium in Typescript. All I can say is that there is some discrepancies between Cesium type definitions and the actual interface. This is a bit lazy on my end to provide context, but you can read it more here. The team is working hard to fix it though.

To answer your question though, an entity’s position can also be defined using a different approach that is Typescript-friendly, for example:

floatingPoint.position = new ConstantPositionProperty(newPosition);

As for their dropdown, the Sandcastle.addToolbarMenu function from the sandcastle is their own code just for demonstration purpose, so it’s not built-in to the Cesium library. A lot of the things on the sandcastle including the bucket.css you mentioned is also for demo purpose, I think, so the only thing you have full control of is the Cesium library itself. You can perhaps create your own dropdown via HTML/CSS and JS then modify the state of your interaction with Cesium. For example:

<select id="toolbar">
  <option value="line">Draw lines</option>
  <option value="polygon>Draw polygons</option>
</select>
let drawingMode = "line";
function drawShape(positionData) {
  let shape;
  if (drawingMode === "line") {
    shape = viewer.entities.add({
      polyline: {
        positions: positionData,
        clampToGround: true,
        width: 3,
      },
    });
  } else if (drawingMode === "polygon") {
    shape = viewer.entities.add({
      polygon: {
        hierarchy: positionData,
        material: new Cesium.ColorMaterialProperty(
          Cesium.Color.WHITE.withAlpha(0.7)
        ),
      },
    });
  }
  return shape;
}

document.getElementById('toolbar').addEventListener('change', (e) => {
  drawingLine = e.currentTarget.value;
});

Obviously these are not the full code nor the exact code you should go for, but you get the idea. I hope it helps!

1 Like

I’ve been working with Cesium in Typescript for a pretty long time, and helped contribute to some of the typings now packed-in with the library. They’re not perfect but as the previous comment suggests, they’re working on it. The team doesn’t actually write Typescript, the typings are just generated from JSDoc comments (which were never completely accurate), so it hasn’t been a top priority.

I have a couple of thoughts in no particular order:

  • import { Viewer } from "cesium"; const v = new Viewer(...) should work with a properly configured project. This is better than import Cesium from "cesium" when using Webpack because the former syntax allows it to “tree shake” unused code and reduce the size of your bundle. You can verify this using the NPM package souce-map-explorer, which looks at your built code and tells you which parts of which libraries are included.
  • I think you could also use import * as Cesium from "cesium"; if you turn on the esModuleInterop flag in your TS compiler options (in the tsconfig.json file). You can read up on esModuleInterop if you want to understand more about the difference.
  • Your function parameters should have an explicitly declared type for each argument, and ideally a return type, like function createPoint(worldPosition: Cartesian3): Entity { ... }. Your variable declarations should likewise have explicit type information. (With recent Typescript versions, you can use the syntax import { type Cartesian3, Viewer } from "cesium"; to help the type-checker understand that you are only importing the type definition of Cartesian3 in this case, not the class implementation.)
  • Use of the non-null assertion operator (!) should be avoided whenever possible. It looks like activeShapePoints may not be reassigned, in which case a const would be preferable, and would allow you to avoid the non-null assertion, and would get rid of the error on the return line.
  • Unfortunately, the team hasn’t gotten around to merging my PR adding typed Events so you’ll have to specify the type of the parameter being passed to event listener callbacks.

You may also get some useful tips from this repo about using Cesium with Webpack – not Typescript specific, but addresses stuff like including CSS.

1 Like

Hi Lennart,

thank you for the answer and for the examples.
Sorry that I answer very late. I was sick in bed for a few days, almost a week, and unfortunately couldn’t answer any earlier.

Hi Iwakuya,

thank you for the answer and for the examples.
Sorry that I answer very late. I was sick in bed for a few days, almost a week, and unfortunately couldn’t answer any earlier.

However, the example here:

unfortunately did not work. Then I get the error:
The name "ConstantPositionProperty" was not found.ts (2304)

I used the one with the dropdown example and it worked for me. I thank you very much for that.

Hi James

thank you for the answer.

That was very helpful, thank you.

Yes, I try to do the typing as far as possible, as you suggest here, but sometimes you don’t know which type is the right one. It is very difficult as a beginner to see that from the JS documentaries. It’s a shame that the examples are not written directly in TS. Because you have given the right types directly and for the JS people you can derive that directly from TS to JS by removing all the types.

I didn’t quite understand the createPoint(...).

Unfortunately I cannot define a const for activeShapePoints here. Since I empty the list in the “terminateShape()” function.


Do you have any other suggested solution for me, how I could do it even better? So that I can leave out the “non-null assertion operator (!)”?

Yes, thank you, I’ve already used the repo and built on it.

As I’ve gotten comfortable using Typescript over the past few years, I’ve come to declare very nearly all my variables as const, which greatly improves the typechecker’s ability to make decisions based on control-flow logic, and I’ve discovered a lot of helpful practices that make that easier. In the case of your array, instead of allocating a new array as in your screenshot, you can simply write activeShapePoints.length = 0. Array does not have a clear method, but setting its length property to zero has the same effect.

1 Like

Hi James,

thanks for the hint. Yes can understand you well. I also mostly use “const” as a variable, but certain variables that change during the process cannot and must not be “const”. It has to be “let”.

I tried your suggestion anyway. This did not result in any errors in the code. But I could no longer draw polygons on the map in the browser. I could only place the points, but the connections between the points were not drawn.

What makes me rather puzzled is this mistake here:

The commented out line 173 (“floatingPoint.position? .SetValue (newPosition);”) is marked as an error. The “setValue ()” does not exist, which the documentation confirms so far.

See my post here:

If I could fix the problem here, I would be very happy.

Many greetings

It looks like floatingPoint is an Entity. In those docs, you can see that position is a PositionProperty, which is an abstract base class/interface for Properties whose value is a Cartesian3. If you read the PositionProperty docs, it links to various implementations, but I don’t think any of them allow you to change the wrapped position value – you just make a new Property instance representing the changed value. If you change your line to floatingPoint.position = new ConstantPositionProperty(newPosition); it should work correctly.

Hi james,

I wouldn’t disagree with you, but that’s exactly what I did and it definitely doesn’t work. I tried it again. This time I even copied your line to avoid typing errors. It just doesn’t want to work like that and is the same problem as I posted earlier with a screenshot and error message.

Please see my previous post / answer, especially with the first screenshot. The error message is that the ConstantPositionProperty() class does not exist or the name was not found.

You need to understand how the import syntax works in TS (and ES6 vanilla-JS modules). ConstantPositionProperty is a class (or more exactly, class-like constructor function, I think?) provided by Cesium. If you import Cesium from "cesium", then Cesium is a module object with all the exports explained in the Cesium documentation as properties, Cesium.Cartesian3, Cesium.Color, etc etc. In that case, you would construct a ConstantPositionProperty with new Cesium.ConstantPositionProperty(...).

I thought you had gotten the syntax import { Cartesian3, Color, ... } from "cesium" working. (It’s a better habit to get into than importing the whole Cesium namespace because it makes your bundler’s job easier.) In that case, you would need to add ConstantPositionProperty to that import list, which makes it a valid top-level identifier within the scope of your TS file. VSCode, which you appear to be using in your screenshots, will offer to do that for you with a quick-fix action, assuming your project is correctly configured.