Select to view content in your preferred language

Rotation with an offset

770
4
04-26-2022 05:50 AM
Nicolai045
New Contributor

The following code shows 2 layers. Each of them containing features with the same coordinates.
The goal of these featues is #1 to display a coordinate (red point) and #2 display a fixed direction from this coordinate (yellow arrow).

What I noticed is, when you change the value of 'field' (field: WIND_DIRECT) in the visualVariable array, the arrow turns/points in the direction on its own axis, as expected. However, when you define an offset (y or x, in this case yoffset) in the symbol (in this case the arrow, to make it visible behind the red dot), the arrow then doesn't rotates on its own axis anymore but rotates around the red dot (or the defined coordinate).

So my question is, is it possible to give the arrow an offset of (e.g. yoffset: 10 ) but at a fixed position next to the red dot? -So that the arrow still recieves values through the WIND_DIRECT field, but then rotating itself around its own axis, at a fixed position next to the red dot

Note: I've already tried a few solutions to fix this, and adjusting the angle in the symbol is currently not an option

The Problem (arrow rotates around the red dot and not staying at a fixed position next to it, when changing the rotationExpression/field value):

DotsArrowProblem.png

<html>
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="initial-scale=1, maximum-scale=1,user-scalable=no"
    />
    <title>
      Visualize data with rotation | Sample | ArcGIS API for JavaScript 4.23
    </title>

    <style>
      html,
      body,
      #viewDiv {
        height: 100%;
        width: 100%;
        margin: 0;
        padding: 0;
      }
    </style>

    <link
      rel="stylesheet"
      href="https://js.arcgis.com/4.23/esri/themes/light/main.css"
    />
    <script src="https://js.arcgis.com/4.23/"></script>

    <script>
      require(["esri/Map", "esri/views/MapView", "esri/layers/FeatureLayer"], (
        Map,
        MapView,
        FeatureLayer
      ) => {
        const symbolArrow = {
          type: "simple-marker", 
          path: "M14.5,29 23.5,0 14.5,9 5.5,0z",
          color: "#ffff00",
          outline: {
            color: [0, 0, 0, 0.7],
            width: 0.5
          },
          angle: 180,
          size: 15,
          yoffset: 15
        };
        let symbolRedDot = {
          type: "simple-marker",  
          color: "red",
          outline: {  
          color: [ 128, 128, 128, 1 ],
            outline: {
            color: [0, 0, 0, 0.7],
            width: 0.5
          },
          width: "0.1px"
          }
        };
        const rotationRendererYellow = {
          type: "simple", 
          symbol: symbolArrow,
          visualVariables: [
            {
              type: "rotation",
              field: "WIND_DIRECT",
              rotationType: "geographic"
            },
            {
              type: "size",
              field: "WIND_SPEED",
              minDataValue: 0,
              maxDataValue: 60,
              minSize: 10,
              maxSize: 10,
            }
          ]
        };
        const rotationRendererRed = {
          type: "simple", 
          symbol: symbolRedDot,
        };
        
        const layerRed = new FeatureLayer({
          url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/weather_stations_010417/FeatureServer/0",
          renderer: rotationRendererRed
        });
        const layerYellow = new FeatureLayer({
          url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/weather_stations_010417/FeatureServer/0",
          renderer: rotationRendererYellow
        });

        const map = new Map({
          basemap: "satellite",
          layers: [layerYellow, layerRed]
        });

        const view = new MapView({
          container: "viewDiv",
          map: map,
          extent: {
            spatialReference: { wkid: 3857 },
            xmin: -41525513,
            ymin: 4969181,
            xmax: -36687355,
            ymax: 9024624
          }
        });
      });
    </script>
  </head>
  <body>
    <div id="viewDiv"></div>
  </body>
</html>

 

0 Kudos
4 Replies
MartinPorteš
Occasional Contributor

Hi,

I'm quite new to this, but I have an idea.

Would it be possible to calculate the yoffset and xoffset based on the angle? Since you always want to have the arrow on position X=0 and Y=15, when the arrow would point to the for example right you need to cancel the offset by X-15 and Y+15 to get back to the top of the circle.

Seems like a simple Pythagorean theorem. But I'm not sure whether you can feed data to calculate the renderer. You might need to query the angle first for each feature.

I hope this helps a bit. Good luck!

Martin

 

MartinPorteš
Occasional Contributor

I did a really quick check if the idea can work. 

If you change symbolArrow to yoffset: 0xoffset: -15 and use definition on the layerYellow: definitionExpression: "WIND_DIRECT = 90" shown arrows render as you described. 

Basically you need to calculete where on the circle the arrow would end up and then move it accordingly to fit the visualisation. As I said not sure if you can calculate that for each point, but maybe you can return that from query using the fromJson method for VisualVariable?
https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-visualVariables-VisualV...

 

Martin

Nicolai045
New Contributor

Hi Martin,

Thank you for your thoughtful reply. While it seems like a considerable solution for the shown example above, my actual code varies a bit from the displayed one. I also apologize for not making it clear in that case. Similar to the angle I currently can't dynamically change any value inside the Symbol. I've actually tried it with Arcade Expressions from Esri, but it doesn't work in my case. Therefore, I'm searching for a solution that happens outside of the Symbol.  I know it is very specific, but it is what is is. Nevertheless, thank you for the effort!

Nicolai

0 Kudos
KristianEkenes
Esri Regular Contributor

Hi Nicolai,

I believe you can achieve the desired result using a CIMSymbol. Is this the behavior you're seeking to achieve? https://codepen.io/kekenes/pen/GRybwZV Rather than use a rotation visual variable, I set a primitive override for rotation on just the arrow symbol layer. That will rotate the arrow symbol layer in place and not the entire symbol. 

CIM is a bit complicated, so let me now if you find the code in the pen confusing, or if you would like further explanation.

 

Kristian