view client/src/components/map/styles.js @ 3480:965b2fbb1890

Colorize gauge symbol based on availability of measurements
author Tom Gottfried <tom@intevation.de>
date Mon, 27 May 2019 15:45:55 +0200
parents 71022e6bd98e
children c5c7cc24fe72
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: "rgba(0, 0, 255, 0.8)",
      lineDash: [2, 4],
      lineCap: "round",
      width: 2
    }),
    fill: new Fill({
      color: "rgba(240, 230, 0, 0.2)"
    })
  }),
  blue2: new Style({
    stroke: new Stroke({
      color: "rgba(0, 0, 255, 0.9)",
      lineDash: [3, 6],
      lineCap: "round",
      width: 2
    }),
    fill: new Fill({
      color: "rgba(240, 230, 0, 0.1)"
    })
  }),
  blue3: new Style({
    stroke: new Stroke({
      color: "rgba(0, 0, 255, 1.0)",
      width: 2
    }),
    fill: new Fill({
      color: "rgba(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
    })
  })
};

export default {
  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") &&
      resolution > 15
    ) {
      let data = feature.get("fa_data");
      let lnwlHeight = (80 / 100) * data.ldc;
      let belowThresholdHeight = (80 / 100) * data.below;
      let betweenThresholdHeight = (80 / 100) * data.between;
      let aboveThresholdHeight = (80 / 100) * data.above;

      let frame = `<rect x='0' y='0' width='32' height='84' stroke-width='0' fill='white'/>`;
      let lnwl = `<rect x='2' y='${80 -
        lnwlHeight +
        2}' width='10' height='${lnwlHeight}' stroke-width='0' fill='aqua'/>`;
      let range1 = `<rect x='12' y='2' width='18' height='${belowThresholdHeight}' stroke-width='0' fill='hotpink'/>`;
      let range2 = `<rect x='12' y='${belowThresholdHeight +
        2}' width='18' height='${betweenThresholdHeight}' stroke-width='0' fill='darksalmon'/>`;
      let range3 = `<rect x='12' y='${80 -
        aboveThresholdHeight +
        2}' width='18' height='${aboveThresholdHeight}' stroke-width='0' fill='blue'/>`;
      let svg = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='84'><g>${frame}${lnwl}${range1}${range2}${range3}</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 = classifications.gmAvailability(feature);
      let colorUniformTriangle = "lime";
      let colorComparison = "white";
      let colorAccuracy = classifications.forecastAccuracy(feature);
      let maps = store.state.map.openLayersMaps;
      let geom = feature.getGeometry();
      if (!(geom instanceof Point)) {
        geom = new Point(getCenter(feature.getGeometry().getExtent()));
      }
      maps.forEach(m => {
        if (
          (m.getLayer("GAUGES").getVisible() &&
            feature.getId().indexOf("gauges") > -1) ||
          (m.getLayer("STRETCHES").getVisible() &&
            feature.getId().indexOf("stretches") > -1) ||
          (m.getLayer("SECTIONS").getVisible() &&
            feature.getId().indexOf("sections") > -1)
        ) {
          let frame = `<polyline points='16,0 32,32 0,32 16,0' stroke='grey' stroke-width='1' fill='white'/>`;
          let waterlevel = `<polyline points="16,0 24,16 16,32 8,16 16,0" stroke='grey' stroke-width='1' fill='${colorWaterlevel}'/>`;
          let accuracy = `<polyline points="24,16 32,32 16,32 24,16" stroke='grey' stroke-width='1' fill='${colorAccuracy}'/>`;
          let comparison = `<polyline points="8,16 16,32 0,32 8,16" stroke='grey' stroke-width='1' fill='${colorComparison}'/>`;
          let svg = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32'><g>${frame}${waterlevel}${comparison}${accuracy}</g></svg>`;
          s.push(
            new Style({
              geometry: geom,
              image: new Icon({
                src: svg,
                anchor: [-0.5, 1]
              })
            })
          );
        }
        if (
          m.getLayer("BOTTLENECKS").getVisible() &&
          feature.getId().indexOf("bottlenecks") > -1
        ) {
          colorUniformTriangle = classifications.surveyCurrency(feature);
          let frame = `<polyline points='16,0 32,32 0,32 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='32'><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 (waterlevel < refWaterlevels.LDC) iconColor = "brown";
      if (waterlevel > refWaterlevels.LDC && waterlevel < refWaterlevels.HDC)
        iconColor = "blue";
      if (waterlevel > refWaterlevels.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
        })
      })
    ];
  }
};