Achieve a similar map effect where svg and images completely overlap


As shown in the figure, the building is a png picture, and the flickering mask is an svg element. svg uses absolute positioning to realize that the svg mask and png picture are not misplaced in any zoom state, so as to realize a simple interactive map like function

vue code is as follows:

<template>
  <div class="container">
    <img src="../../assets/map.png" alt="">
		
		
		<svg v-if="maskShow" class="svgMask" version="1.1" viewBox="0 0 826 386">
		 <g>
			 <!-- Outdoor living area -->
		  <polygon v-show="selectArea==1" class="fil0" points="56,211 131,195 130,189 242,164 222,120 21,161 "/>
			<!-- Indoor isolation area -->
		  <polygon v-show="selectArea==2" class="fil1" points="167,188 243,273 309,255 225,175 "/>
		  <polygon v-show="selectArea==2" class="fil1" points="240,149 282,187 328,176 284,139 "/>
		  <polygon v-show="selectArea==2" class="fil1" points="292,197 350,248 411,231 350,183 "/>
			<!-- Production area -->
		  <polygon v-show="selectArea==3" class="fil2" points="279,111 361,173 376,195 421,229 724,150 536,60 "/>
			<!-- Environmental protection zone -->
		  <path v-show="selectArea==4" class="fil3" d="M545 62c-1,2 44,-8 44,-8l111 51 -48 12 -107 -55z"/>
		 </g>
		</svg>
		
  </div>
</template>

<script>
export default {
  name: 'middleBottom',
  props: {

  },
	data() {
		return {
			maskShow: true
		}
	},
	computed: {
	  selectArea () {
	    return this.$store.state.selectArea
	  }
	},
	watch: {
		selectArea(newVal, oldVal) {
			// Re render with dom and let it play the animation
			this.maskShow = false
			this.$nextTick(()=> {
				this.maskShow = true
			})
		}
	},
  methods: {

  }
}
</script>

<style lang="scss" scoped>
.container {
	position: relative;
	height: 450px;
	display: flex;
	img {
		margin: auto;
		width: 100%;
	}
	.svgMask {
		width: 100%;
		height: 100%;
		position: absolute;
		.fil1 {fill:#008FD7;fill-opacity:0.5}
		.fil3 {fill:#009B4C;fill-opacity:0.5}
		.fil2 {fill:#B04B87;fill-opacity:0.5}
		.fil0 {fill:#E62129;fill-opacity:0.5}
		animation: blink .5s linear;
		animation-iteration-count:2;
	}
}
@keyframes blink {
	from {opacity: 1;}
	to {opacity: 0;}
}
</style>

svg code is exported after drawing with cdr. When drawing, create a new canvas with the same size as the picture, import the png picture, place it at the position that just covers the canvas, draw the vector diagram of the flashing area according to the position of the area in the picture, delete the png diagram after drawing, and export it to svg format
Open the exported file with an editor, delete some honor codes, and just keep the above svg codes
As shown in the code: the img element is kept vertically centered, and the width is 100% in any zoom state to enable it to be displayed completely. The width and height of the svg mask should be set to 100%, and absolute positioning should be used
In this way, it seems that the svg image will be stretched and deformed, but it will not, because there is an important attribute in the svg tag: viewBox. It must be set consistent with the image pixels. The specific concept of viewBox is similar to that of the browser. The browser window can only see part of the web page, and the function of viewBox is to set the position of this window
There must be other ways to achieve this function, but I tried for a while and found that this method is perfect
Mask flicker animation is realized by destroying and re creating elements. It may waste some performance, but the code is simple
svg elements are as easy to interact as ordinary dom elements. On this basis, a simple map application can be implemented

Tags: html5 html css

Posted on Thu, 09 Sep 2021 20:53:37 -0400 by mdub2112