简体   繁体   中英

Creating interactive svg maps using vue.js

I am new to vue and have some experience with svg interactive maps using javascript and d3.js to reach DOM elements and make changes I need. Now I'm trying to set this maps inside vue framework and I am stack.

I created SvgMap.vue component which contain inline svg map inside .

<template>
<svg id="karta"
     :class="name"
     xmlns="http://www.w3.org/2000/svg" 
     width="1400" 
     height="960" 
     viewBox="0 0 1400 960">
<g id="wrap">
 <g id="lake">
   <path  d="....">
 </g>
 <g id="area1" class="pol">
   <path  d="....">
 </g>
 <g id="area2" class="pol">
   <path  d="....">
 </g>
 ....
</g>
</svg>
</template>

I want this SvgMap.vue component to hold svg with all needed map data (regions, rivers, lakes, cities,...) And than I want to create other vue components that contain imported <svg-map> with possibility to modify it depending of what the map represent. For example RegionMap.vue doesn't need to display rivers, cities, lakes,...just regions. So I want to able to manipulate with svg attributes. I am aware that some changes I can do using scoped style and css.

RegionMap.vue

<template>
  <svg-map name="Region"></svg-map>
</template>

<style scoped>
#karta /deep/ #wrap .pol {
    fill:red
}

#karta /deep/ #wrap .pol:hover {
    fill:black     }
</style>

But sometimes I need to use javascript to chose what I want to show on the map. I will give simplified example for this purpose: select all classes .pol and change fill to pink. I tried to reach this element using created() in script part of the vue component

<script>
import SvgMap from "./SvgMap"

export default {
    name: "RegionMap",

    components: {
        SvgMap
    },

    created(){
    var pol = document.getElementsByClassName("pol")
    pol.setAttribute("style", "fill:pink")
    }
  }
 </script>

In console I can see the code reach pol elements as HTMLCollection but I also get an error pol.setAttribute is not a function.

I don't understand how to reach specific elements in my main svg SvgMap.vue component and change it dynamically if I don't use props and css style. Any suggestion how I can make this work is welcome. Or if I am on the wrong track, what strategy would you suggest for this task.

The idea behind having one main svg map component and reuse it in other components is for easier maintenance. If some data change I change it in main component and all component where I reused it are up to date.

Update: I found the problem why it didn't work. The js code should be in mounted property. Not understanding 100% why like this is working and in inside created property not. I red about the differences, but if vue runs the created() hook when the component object is created, and before the component is mounted to the DOM my logic says it should work. So if someone know to explain me this I would be glad to read it. Anyway, it's working.

If you read the description of the created hook , you can see that at the end it mentions :

However, the mounting phase has not been started, and the $el property will not be available yet.

In the created hook, the component is not yet mounted and thus not available in the DOM yet ! You can also have a look at the lifecycle diagram to understand it better :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM