Home > Enterprise >  SVG shadows do not repeat the element contour
SVG shadows do not repeat the element contour

Time:11-19

I am trying to render an SVG world map where I can select countries. I want to add a shadow effect for a particular country for the onmouseenter event. Everything works fine except that for some countries shadows do not follow the country border completely. Here is how it should work, the whole country is surrounded by a shadow:Good example

Here is what happens for some countries, you can see that shadow is absent for the southern border: Bad example

What do you think is the reason for this? I tried several SVGs and always the same problem.

I am using Rust Yew framework to build this, however, I think the problem is more related to SVG or CSS stuff which I don't really know well. Here is my CSS:

.shadow {
    filter: drop-shadow( 0px 0px 3px rgba(0, 0, 0, .7));
    z-index: 999;
}

This is how I render the map:

impl Country {
  fn toggle_highlight(e: MouseEvent, enable: bool) {
    let style = if enable {
      "#fcecec"
    } else {
      "#ececec"
    };
    let class = if enable {
      "country shadow"
    } else {
      "country"
    };
    e.target()
      .and_then(|t| t.dyn_into::<SvgElement>().ok())
      .map(|el| {
        el.set_attribute("fill", style)
          .expect("Unable to set style attribute for the country path");
        el.set_attribute("class", class)
          .expect("Unable to set class attribute for the country path");
      });
  }

  fn render(&self) -> Html {
    let onm ouseenter = Callback::from(|e: MouseEvent| Country::toggle_highlight(e, true));
    let onm ouseleave = Callback::from(|e: MouseEvent| Country::toggle_highlight(e, false));
    html! {
      <path class="country" id={self.id.clone()} name={self.name.clone()} d={self.path.clone()} onmouseenter={onmouseenter} onmouseleave={onmouseleave}></path>
    }
  }
}

...

html! {
  <svg baseprofile="tiny" fill="#ececec" stroke="black" viewBox="0 0 1500 1500"
       width="100%" height="100%" stroke-linecap="round" stroke-linejoin="round"
       stroke-width=".2" version="1.2" xmlns="http://www.w3.org/2000/svg"
       style="border: 1px solid red">
    { for build_countries_list().iter().map(|c| c.render()) }
  </svg>
}

I am not sure it makes sense to post also SVG data here, please let me know if it is necessary.

CodePudding user response:

Other countries outlines are on top and obscure the shadow.

To reveal the shadow move the element so it's last in DOM order.

  • Related