view client/src/components/layers/styles.js @ 5627:7768f14f6535 729-node-js-newer-version

Transformed scss variables into css custom properties
author Luisa Beerboom <lbeerboom@intevation.de>
date Tue, 09 May 2023 13:17:58 +0200
parents 96a544504818
children
line wrap: on
line source

import { Icon, Stroke, Style, Fill, Text, Circle } from "ol/style";
import Point from "ol/geom/Point";
import { getCenter } from "ol/extent";
import store from "@/store/index";
import classifications from "../../lib/classifications";

const styles = {
  blue1: new Style({
    stroke: new Stroke({
      color: [0, 0, 255, 0.8],
      lineDash: [2, 4],
      lineCap: "round",
      width: 2
    }),
    fill: new Fill({
      color: [240, 230, 0, 0.2]
    })
  }),
  blue2: new Style({
    stroke: new Stroke({
      color: [0, 0, 255, 0.9],
      lineDash: [3, 6],
      lineCap: "round",
      width: 2
    }),
    fill: new Fill({
      color: [240, 230, 0, 0.1]
    })
  }),
  blue3: new Style({
    stroke: new Stroke({
      color: [0, 0, 255, 1.0],
      width: 2
    }),
    fill: new Fill({
      color: [255, 255, 255, 0.4]
    })
  }),
  yellow1: new Style({
    stroke: new Stroke({
      color: "rgba(230, 230, 10, .8)",
      width: 4
    }),
    fill: new Fill({
      color: "rgba(230, 230, 10, .3)"
    })
  }),
  yellow2: new Style({
    stroke: new Stroke({
      color: "rgba(250, 200, 0, .8)",
      width: 2
    }),
    fill: new Fill({
      color: "rgba(250, 200, 10, .3)"
    })
  }),
  yellow3: new Style({
    stroke: new Stroke({
      color: "rgba(250, 240, 10, .9)",
      width: 5
    }),
    fill: new Fill({
      color: "rgba(250, 240, 0, .7)"
    })
  }),
  orange1: new Style({
    stroke: new Stroke({
      color: "rgba(255, 150, 10, .8)",
      width: 2
    }),
    fill: new Fill({
      color: "rgba(255, 150, 0, .3)"
    })
  }),
  orange2: new Style({
    stroke: new Stroke({
      color: "rgba(255, 166, 10, .9)",
      width: 5
    }),
    fill: new Fill({
      color: "rgba(255, 166, 0, .7)"
    })
  }),
  red1: new Style({
    stroke: new Stroke({
      color: "rgba(255, 0, 0, 1)",
      width: 4
    })
  }),
  circleBlue: new Style({
    image: new Circle({
      radius: 5,
      fill: new Fill({ color: "rgba(255, 0, 0, 0.1)" }),
      stroke: new Stroke({ color: "blue", width: 1 })
    })
  }),
  textFW1: new Style({
    text: new Text({
      font: 'bold 12px "Open Sans", "sans-serif"',
      placement: "line",
      fill: new Fill({
        color: "black"
      }),
      text: "LOS: 1"
      //, zIndex: 10
    })
  }),
  textFW2: new Style({
    text: new Text({
      font: 'bold 12px "Open Sans", "sans-serif"',
      placement: "line",
      fill: new Fill({
        color: "black"
      }),
      text: "LOS: 2"
      //, zIndex: 10
    })
  }),
  textFW3: new Style({
    text: new Text({
      font: 'bold 12px "Open Sans", "sans-serif"',
      placement: "line",
      fill: new Fill({
        color: "black"
      }),
      text: "LOS: 3"
      //, zIndex: 10
    })
  })
};

const styleFactory = function(mapId) {
  const recencyColorCodes = {
    OK: "lime",
    WARNING: "yellow",
    DANGER: "red",
    NEUTRAL: "white"
  };
  const gmAvailabilityColorCodes = {
    OK: "lime",
    WARNING: "yellow",
    DANGER: "red",
    NEUTRAL: "white"
  };
  const forecastAccuracyColorCodes = {
    OK: "lime",
    WARNING: "yellow",
    DANGER: "red",
    NEUTRAL: "white"
  };

  const forecastVsRealityColorCodes = {
    OK: "lime",
    WARNING: "yellow",
    DANGER: "red",
    NEUTRAL: "white"
  };
  return {
    recencyColorCodes: recencyColorCodes,
    gmAvailabilityColorCodes: gmAvailabilityColorCodes,
    forecastAccuracyColorCodes: forecastAccuracyColorCodes,
    forecastVsRealityColorCodes: forecastVsRealityColorCodes,
    stretches(feature) {
      let style = styles.yellow2;
      if (feature.get("highlighted")) {
        style = styles.yellow3;
      }
      return style;
    },
    sections(feature) {
      let style = styles.orange1;
      if (feature.get("highlighted")) {
        style = styles.orange2;
      }
      return style;
    },
    fwd1() {
      return [styles.blue1, styles.textFW1];
    },
    fwd2() {
      return [styles.blue2, styles.textFW2];
    },
    fwd3() {
      return [styles.blue3, styles.textFW3];
    },
    bottleneck() {
      return styles.yellow1;
    },
    bottleneckStatus(feature, resolution, isLegend) {
      let s = [];
      if ((feature.get("fa_critical") && resolution > 15) || isLegend) {
        let bnCenter = getCenter(feature.getGeometry().getExtent());
        s.push(
          new Style({
            geometry: new Point(bnCenter),
            image: new Icon({
              src: require("@/assets/marker-bottleneck-critical.png"),
              anchor: [0.5, 0.5],
              scale: isLegend ? 0.5 : 1
            })
          })
        );
      }
      if (feature.get("fa_critical") && !isLegend) {
        s.push(styles.red1);
      }
      return s;
    },
    bottleneckFairwayAvailability(feature, resolution, isLegend) {
      let s = [];
      if (isLegend) {
        s.push(
          new Style({
            image: new Icon({
              src: require("@/assets/fa-diagram.png"),
              anchor: [0.5, 0.5],
              scale: 1
            })
          })
        );
      }
      if (feature.get("fa_critical") && feature.get("fa_data")) {
        let data = feature.get("fa_data");
        const heightInPixel = 80;
        const relativeHeightInPercent = heightInPixel / 100;
        let lnwlHeight = relativeHeightInPercent * data.ldc;
        let belowThresholdHeight = relativeHeightInPercent * data.below;
        let betweenThresholdHeight = relativeHeightInPercent * data.between;
        let aboveThresholdHeight = relativeHeightInPercent * data.above;
        let lnwl = `<rect x='2' y='${2 +
          heightInPixel -
          lnwlHeight}' width='10' height='${lnwlHeight}' stroke-width='0' fill='aqua'/>`;
        let above = `<rect x='12' y='${2 +
          heightInPixel -
          aboveThresholdHeight}' width='18' height='${aboveThresholdHeight}' stroke-width='0' fill='blue'/>`;
        let between = `<rect x='12' y='${2 +
          heightInPixel -
          aboveThresholdHeight -
          betweenThresholdHeight}' width='18' height='${betweenThresholdHeight}' stroke-width='0' fill='darksalmon'/>`;
        let below = `<rect x='12' y='${2 +
          heightInPixel -
          aboveThresholdHeight -
          betweenThresholdHeight -
          belowThresholdHeight}' width='18' height='${belowThresholdHeight}' stroke-width='0' fill='hotpink'/>`;
        let frame = `<rect x='0' y='0' width='32' height='84' stroke-width='0' fill='white'/>`;
        let svg = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='84'><g>${frame}${lnwl}${above}${between}${below}</g></svg>`;
        let bnCenter = getCenter(feature.getGeometry().getExtent());
        s.push(
          new Style({
            geometry: new Point(bnCenter),
            image: new Icon({
              src: svg,
              anchor: [1.2, 1.2]
            })
          })
        );
      }
      return s;
    },
    dataAvailability(feature, resolution, isLegend) {
      let s = [];
      if (isLegend) {
        s.push(
          new Style({
            image: new Icon({
              src: require("@/assets/da-diagram.png"),
              anchor: [0.5, 0.5],
              scale: 1
            })
          })
        );
      } else {
        // TODO: Get information from feature and check the ranges according to #423, #424, #425
        let colorWaterlevel =
          gmAvailabilityColorCodes[classifications.gmAvailability(feature)];
        let colorComparison =
          forecastVsRealityColorCodes[
            classifications.forecastVsReality(feature)
          ];
        let colorAccuracy =
          forecastAccuracyColorCodes[classifications.forecastAccuracy(feature)];
        let map = store.getters["map/openLayersMap"](mapId);
        let geom = feature.getGeometry();
        if (!(geom instanceof Point)) {
          geom = new Point(getCenter(feature.getGeometry().getExtent()));
        }
        if (
          (map.getLayer("BOTTLENECKS").getVisible() &&
            feature.getId().indexOf("bottlenecks") > -1) ||
          (map.getLayer("SECTIONS").getVisible() &&
            feature.getId().indexOf("sections") > -1) ||
          (map.getLayer("STRETCHES").getVisible() &&
            feature.getId().indexOf("stretches") > -1) ||
          (map.getLayer("GAUGES").getVisible() &&
            feature.getId().indexOf("gauges") > -1)
        ) {
          let frame = `<polyline points='16,0 32,28 0,28 16,0' stroke='grey' stroke-width='1' fill='white'/>`;
          let waterlevel = `<polyline points="16,0 24,14 16,28 8,14 16,0" stroke='grey' stroke-width='1' fill='${colorWaterlevel}'/>`;
          let accuracy = `<polyline points="24,14 32,28 16,28 24,14" stroke='grey' stroke-width='1' fill='${colorAccuracy}'/>`;
          let comparison = `<polyline points="8,14 16,28 0,28 8,14" stroke='grey' stroke-width='1' fill='${colorComparison}'/>`;
          let svg = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='28'><g>${frame}${waterlevel}${comparison}${accuracy}</g></svg>`;
          s.push(
            new Style({
              geometry: geom,
              image: new Icon({
                src: svg,
                anchor: [-0.5, 1]
              })
            })
          );
        }

        if (
          map.getLayer("BOTTLENECKS").getVisible() &&
          feature.getId().indexOf("bottlenecks") > -1
        ) {
          let colorUniformTriangle =
            recencyColorCodes[classifications.surveyRecency(feature)];
          let frame = `<polyline points='16,0 32,28 0,28 16,0' stroke='grey' stroke-width='1' fill='${colorUniformTriangle}'/>`;
          let svg = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='28'><g>${frame}</g></svg>`;
          s.push(
            new Style({
              geometry: geom,
              image: new Icon({
                src: svg,
                anchor: [0.5, 1]
              })
            })
          );
        }
      }
      return s;
    },
    dma(feature, resolution) {
      if (resolution < 10) {
        var s = styles.circleBlue;
        if (resolution < 6) {
          s.setText(
            new Text({
              offsetY: 12,
              font: '10px "Open Sans", "sans-serif"',
              fill: new Fill({
                color: "black"
              }),
              text: (feature.get("hectometre") / 10).toString()
            })
          );
        }
        return s;
      }
      return [];
    },
    gauge(feature, resolution, isLegend) {
      let waterlevel = feature.get("gm_waterlevel");
      let text = feature.get("objname");
      let iconColor = "white";
      if (waterlevel) {
        text += "\n(" + waterlevel + " cm)";
        let refWaterlevels = JSON.parse(feature.get("reference_water_levels"));
        if (refWaterlevels) {
          const HDC =
            refWaterlevels[
              Object.keys(refWaterlevels).find(e => /HDC/.test(e))
            ];
          const LDC =
            refWaterlevels[
              Object.keys(refWaterlevels).find(e => /LDC/.test(e))
            ];
          if (waterlevel < LDC) iconColor = "brown";
          if (waterlevel > LDC && waterlevel < HDC) iconColor = "blue";
          if (waterlevel > HDC) iconColor = "red";
        }
      }

      return [
        new Style({
          image: new Icon({
            src: require("@/assets/marker-gauge-" + iconColor + ".png"),
            anchor: [0.5, isLegend ? 0.5 : 1],
            scale: isLegend ? 0.5 : 1
          }),
          text: new Text({
            font: '10px "Open Sans", "sans-serif"',
            offsetY: 15,
            fill: new Fill({
              color: "black"
            }),
            backgroundFill: new Fill({
              color: "rgba(255, 255, 255, 0.7)"
            }),
            padding: [2, 2, 2, 2],
            text
          })
        })
      ];
    }
  };
};

export { styles, styleFactory };