Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Unable to Display Features Using Vector3DLayer in Vue App #404

Open
mrAbra opened this issue Feb 5, 2025 · 0 comments
Open

Unable to Display Features Using Vector3DLayer in Vue App #404

mrAbra opened this issue Feb 5, 2025 · 0 comments

Comments

@mrAbra
Copy link

mrAbra commented Feb 5, 2025

Hello,

I’m currently working with the ol-ext library in a Vue app and trying to display 3D features using the custom component from https://vue3openlayers.netlify.app/pluginsguide/ , but I’m unable to render any features on the map. I have followed the documentation and used Vector3DLayer, but the features do not appear in the 3D layer at all.
ol-ext example: https://github.com/Viglino/ol-ext/blob/master/examples/map/map.layer.3D.2.html

<template>
    <form>
      <label for="zoom">Zoom:</label>
      <input type="number" id="zoom" v-model="zoom" />
    </form>
  
    <ol-map style="height: 400px" ref="mapRef">
      <ol-view
        ref="view"
        :center="center"
        :rotation="rotation"
        :zoom="zoom"
        :projection="projection"
        @change:center="centerChanged"
        @change:resolution="resolutionChanged"
        @change:rotation="rotationChanged"
      />
  
      <ol-tile-layer>
        <ol-source-osm />
      </ol-tile-layer>
  
      <!-- 3D слой -->
      <Vector3DLayer
        :source="vectorSource"
        :style="styleFunction"
        :height="heightFunction"
        ref="ref3Dlayer"
      />
  
      <ol-rotate-control />
      <ol-interaction-link />
    </ol-map>
  
    <div class="info">
      <button @click="animateLayer">Animate!</button>
    </div>
  
    <div v-if="loading" class="loading">Loading data...</div>
  
    <ul>
      <li>center: {{ currentCenter }}</li>
      <li>resolution: {{ currentResolution }}</li>
      <li>zoom: {{ currentZoom }}</li>
      <li>rotation: {{ currentRotation }}</li>
    </ul>
  </template>
  
  <script setup>
  import { ref, onMounted } from "vue";
  import Vector3DLayer from "./Vector3DLayer.vue"; // Компонент для 3D слоя
  import GeoJSON from "ol/format/GeoJSON";
  import VectorSource from "ol/source/Vector";
  import { Stroke } from "ol/style";
  

  const center = ref([256267.70558611996, 6250141]);
  const projection = ref("EPSG:3857");
  const zoom = ref(15);
  const rotation = ref(0);
  
 
  const currentCenter = ref(center.value);
  const currentZoom = ref(zoom.value);
  const currentRotation = ref(rotation.value);
  const currentResolution = ref(0);
  

  function resolutionChanged(event) {
    currentResolution.value = event.target.getResolution();
    currentZoom.value = event.target.getZoom();
  }
  function centerChanged(event) {
    currentCenter.value = event.target.getCenter();
  }
  function rotationChanged(event) {
    currentRotation.value = event.target.getRotation();
  }
  

  const mapRef = ref(null);
  const ref3Dlayer = ref(null);
  const vectorSource = ref(new VectorSource());
  const loading = ref(true);
  let isAnimating = false; 
  
  const geojsonData = {
    type: "FeatureCollection",
    features: [
      {
        type: "Feature",
        geometry: {
          type: "Polygon",
          coordinates: [
            [
              [256267.70558611996, 6250141],
              [256400.70558611996, 6250200],
              [256350.70558611996, 6250300],
              [256220.70558611996, 6250300],
              [256267.70558611996, 6250141],
            ],
          ],
        },
        properties: { nb: 10 },
      },
      {
        type: "Feature",
        geometry: {
          type: "Polygon",
          coordinates: [
            [
              [256500.70558611996, 6250200],
              [256600.70558611996, 6250300],
              [256550.70558611996, 6250400],
              [256450.70558611996, 6250400],
              [256500.70558611996, 6250200],
            ],
          ],
        },
        properties: { nb: 5 },
      },
    ],
  };
  
  const loadGeoJSON = () => {
    const features = new GeoJSON().readFeatures(geojsonData);
    console.log("Загружены фичи:", features);
    vectorSource.value.addFeatures(features);
    loading.value = false;
  };
  
  // Анимация 3D слоя
  const animateLayer = () => {
    if (isAnimating) return;
  
    const render3DLayer = ref3Dlayer.value?.vectorLayer;
  
    if (!render3DLayer) {
      console.error("3D слой ещё не инициализирован");
      return;
    }
  
    isAnimating = true;
    console.log("Анимация слоя...", render3DLayer);
    render3DLayer.animate(
      { height: (f) => f.get("nb") * 20 },
      {
        duration: 2000,
        complete: () => {
          isAnimating = false;
        },
      }
    );
  };
  
  onMounted(() => {
    loadGeoJSON();
  });
  
  
  const styleFunction = (feature) => {
    return {
      stroke: new Stroke({
        width: 5,
        color: [255, 0, 0, 0.5],
      }),
      geometry: feature.getGeometry().getInteriorPoint(),
    };
  };
  

  const heightFunction = (feature) => feature.get("nb") * 20 || 0;
  </script>

Vector3DLayer

<template>
  <slot></slot>
</template>

<script setup>
import { ref, onMounted, provide, defineExpose } from "vue";
import Vector3D from "ol-ext/layer/Render3D";

// Define props
const props = defineProps({
  source: Object, // Data source (VectorSource)
  style: Function, // Style function for the features
  height: Function, // Function to determine the height of features
});

const layer = ref(null);

onMounted(() => {
  // Create the Vector3D layer
  layer.value = new Vector3D({
    source: props.source,
    styler: function (feature) {
      // Pass the style function from props
      return props.style ? props.style(feature) : null;
    },
    height: function (feature) {
      // Pass the height function from props
      return props.height ? props.height(feature) : 0;
    },
  });

  // Define layer_ if necessary
  layer.value.layer_ = layer.value;

  // Provide the layer via provide for usage in other components
  provide("vectorLayer", layer.value);
});

// Expose the layer for external use
defineExpose({
  vectorLayer: layer,
});
</script>
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant