1. 程式人生 > >vue 中 canvas 和svg合用製作地圖

vue 中 canvas 和svg合用製作地圖

<template>
  <div class="contents">
    <div class="lefttop1-title">區域</div>
    <img id="police" src="../assets/police.svg" style="display:none;"  width="395px" height="343px">
    <div id="contentMap" style="width: 100%;height: 95%;">
      <canvas id="areaCanvas" width="395px" height="343px" style="width:90%;height:90%;margin-left:20px;"></canvas>
    </div>
  </div>
</template>

<script>
  //vue中點在不規則圖形中的判斷
    var inside = require( 'point-in-polygon' );
    import {generatePolygon} from '../api/index.js'
    export default {
        data () {
            return {
                collectionArr: [],
            }
        },
        mounted () {
            // 地圖座標
          generatePolygon().then(response => {
            this.collectionArr = response.data;
            this.drawPolygons();
          });

        },
        methods: {
//			地圖
            drawPolygons: function () {
              var canvas = document.getElementById( 'areaCanvas' );
              if ( null == canvas || !canvas.getContext ) return;
              var ctx = canvas.getContext( "2d" );

              var  img=document.getElementById("police");
              if(img.complete){
                ctx.drawImage(img, 0, 0);
              }else{
                img.onload = function() {
                  ctx.drawImage(img, 0, 0);
                }
              }

              //滑鼠移動事件
              this.canvasMousemoveEvent( canvas, ctx );

              //click事件
              this.canvasClickEvent( canvas );
            },
            canvasMousemoveEvent: function ( canvas, ctx ) {
                var _this = this;
                canvas.onmousemove = function ( e ) {
                  //清除繪製圖形
                  _this.clearPolygon(ctx,canvas);
                  //  ctx.clearRect( 0, 0, canvas.width, canvas.height );
                    var location = _this.getLocation( canvas, e.clientX, e.clientY );
                    _this.drawPolygonByPoint( ctx, location, e ,canvas);
                };
            },
            canvasClickEvent: function ( canvas ) {
                var _this = this;
                canvas.onclick = function ( e ) {
                    var location = _this.getLocation( canvas, e.clientX, e.clientY );
                    var count = 0;
                    _this.collectionArr.map( obj => {
                      var pointsArr = obj.polygon;
                        count++;
                        if ( location != null && inside( location, pointsArr ) == true ) {
                            alert(obj.name);
                        }
                    } );
                };
            },
            drawPolygonByPoint: function ( ctx, location, e ,canvas) {
                //清除title
                this.clearTitle();
                this.collectionArr.map( obj => {
                  var pointsArr = obj.polygon;
                    if ( location != null && inside( location, pointsArr ) == true ) {
                        //繪製高亮圖形
                        this.drawHighLightPolygon( ctx, pointsArr,canvas );
                        this.displayTitle(e,obj.name);
                    }
                } );
            },
            clearTitle: function () {
                var div = document.getElementById( 'title' );
                if ( div != null ) {
                  document.body.removeChild(div);
                }
            },
            displayTitle: function ( e ,name) {
                var div = document.createElement( "div" );
                div.setAttribute( "id", "title" );
                div.style.position = "absolute";
                div.style.left = e.clientX + 10 + "px";
                div.style.top = e.clientY + "px"
                div.innerText = name;
                div.style.backgroundColor = "gray";
                div.style.zIndex = "9999";
                document.body.appendChild( div );
            },
            drawHighLightPolygon: function ( ctx, pointsArr ,canvas) {
                ctx.beginPath();
                for ( let i = 0; i < pointsArr.length; i++ ) {
                  var pointX = Math.round(canvas.width * pointsArr[ i ][ 0 ])+1;
                  var pointY = Math.round(canvas.height * pointsArr[ i ][ 1 ])+1;
                  ctx.lineWidth=2;
                    if ( i == 0 ) {
                        ctx.moveTo( pointX, pointY );
                    } else if ( i < pointsArr.length - 1 ) {
                        ctx.lineTo( pointX, pointY );
                    } else {
                        ctx.lineTo( pointX, pointY );
                        ctx.strokeStyle = "#FF7F00";

                        ctx.closePath();
                        ctx.stroke();
                    }
                }
            },
          clearPolygon: function(ctx,canvas){
            ctx.clearRect( 0, 0, canvas.width, canvas.height );
            var  img=document.getElementById("police");
            ctx.drawImage(img, 0, 0);
          },
            getLocation: function ( canvas, x, y ) {
                var bbox = canvas.getBoundingClientRect();
                return [ ( x - bbox.left ) * ( canvas.width / bbox.width )/canvas.width, ( y - bbox.top ) * ( canvas.height / bbox.height )/canvas.height ];
                /*
                 * 此處不用下面兩行是為了防止使用CSS和JS改變了canvas的高寬之後是表面積拉大而實際
                 * 顯示畫素不變而造成的座標獲取不準的情況
                x: (x - bbox.left),
                y: (y - bbox.top)
                */
            },

        }
    }
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
    .contents {
      float: left;
      height: 98.5%;
      width: 41.3%;
      border: 1px solid rgba(15, 208, 198, 0.50);
      box-shadow: inset 0 2px 19px 0 rgba(15, 208, 198, 0.80);
      margin-left: 1.4%;
      margin-right: 1.4%;
    }
    .lefttop1-title{
      text-align: center;
      color: #0FD0C6;
      font-size: 12px;
      background: url(../assets/Group.png) no-repeat;
      width: 170px;
      line-height: 25px;
      display: inline-block;
    }
</style>


其中police.svg做地圖,滑鼠移動到某一區域,高亮顯示該區域(在底圖上只畫出該區域)。
所有區域的座標點使用svg匯出的相對座標,在畫圖時要根據canvas畫布轉換成絕對座標。
collectionArr資料結構:
collectionArr: [{name:'區域一',polygon:[[0.0123,0.1723],...]},{name:'區域二',polygon:[[0.0123,0.1723],...]},...]

相關推薦

vue canvas svg合用製作地圖

<template> <div class="contents"> <div class="lefttop1-title">區域</div> <img id="police" src="../asset

HTML5CanvasSVG的畫圖原理比較

面積 com 像素 jpg 最終 不同 谷歌 最適 保存   canvas 與 SVG都能夠使你在瀏覽器中畫圖,但它們的基本原理不同。鞍山治療白癜風多少錢www.pfk0412.com   SVG   SVG是一種在XML中描述二維圖形的語言。   SVG是基於XML的,意

vuenextTick$nextTick

ack for back div cal 回調 class gpo lba * `Vue.nextTick(callback)`,當數據發生變化,更新後執行回調。* `Vue.$nextTick(callback)`,當dom發生變化,更新後執行的回調。 this.nex

vueassetsstatic的區別

需求 壓縮 樣式 就會 sset 簡單 sse index ont Vue中assets和static的區別 再一次框架定型中,與同事在靜態資源的存放上有了一些分歧,後來經過查閱總結如下: 相同點: assets和static兩個都是存放靜態資

Vuerefsref的用法

vue 中的ref 開發過程中遇到的問題 知識點的查漏補缺 vm.$refs ref 開發過程中遇到的問題 在實際的操作過程中發現在created生命週期中列印refs,結果為空物件 crea

vuecomputed watch的異同

computed 在資料未發生變化時,優先讀取快取。computed 計算屬性只有在相關的資料發生變化時才會改變要計算的屬性,當相關資料沒有變化是,它會讀取快取。而不必想 motheds方法 和 watch 方法是的每次都去執行函式。 computed:{ fullName:{

對比canvassvg

  討論關於canvas和svg的區別。首先canvas是html5提供的新元素<canvas>,而svg存在的歷史要比canvas久遠,已經有十幾年了。svg並不是html5專有的標籤,最初svg是用xml技術(超文字擴充套件語言,可以自定義標籤或屬性)描述二維圖形

canvassvg區別

1.canvas是html5提供的新元素<canvas>   svg並不是html5專有的標籤,最初svg是用xml技術(超文字擴充套件語言,可以自定義標籤或屬性)描述二維圖形的語言。 2.canvas可以看做是一個畫布,其繪製出來的圖形為標量圖   &n

vue過渡動畫結合

動畫、過渡、頁面載入時就有動畫 <style> .de{ width: 100px; height: 100px; background: green; } .fade-leave-active { tran

前端繪圖方式CanvasSVG的區別

Canvas和SVG是html5中支援2種視覺化技術,都是可以在畫布上繪製圖形和放入圖片。下面來介紹和分析一下他們。 一.Canvas 和 SVG 簡介 1.什麼是Canvas? Canvas 是H5新出來的標籤<canvas></canvas> Canvas畫布,利用Java

canvassvg小記

遵從 縮放 www. 不同 graph 保存 等比例縮放 拖動 比例 一、關於canvas   <canvas> 是 HTML5 新增的元素,可用於通過使用JavaScript中的腳本來繪制圖形 例如,它可以用於繪制圖形,創建動畫。   <canvas&g

vue$setdelete

vue給物件新增屬性 對於一般的物件新增屬性,只需要物件新增屬性賦值操作就可以啦,但是不會觸發檢視更新. vue中使用$set()方法,既可以新增屬性,又可以觸發檢視更新。 this.$set(th

vue$route $router的區別

在vue中會出現一種情況 const url=this.$route.query.returnURL; this.$router.push(url);    $router和$route的區別傻傻的分不清 1.先說$

android CanvasPaint

相關連結: ---------------正文---------------- Canvas類主要實現了螢幕的繪製過程,其中包含了很多實用的方法,比如繪製一條路徑、區域、貼圖、畫點、畫線、渲染文字,下面是Canvas類常用的方法:  void drawRect(RectF rect, Pai

VUEcomputedwatch的使用

VUE中computed和watch的使用 VUE中computed和watch的使用 1.computed computed用來監控自己定義的變數,該變數不在data裡面宣告,直接在computed裡面定義,然後就可以在頁面上進行雙向資料繫結展示出結果或者用作其他處理; com

Vue watchcomputed的不同

今天我來總結一下vue中computed 和 watch的異同! 一、computed 和 watch 都可以觀察頁面的資料變化。當處理頁面的資料變化時,我們有時候很容易濫用watch。 而通常更好的辦法是使用computed屬性,而不是命令是的watch回撥。 這裡我直接

vuewatchcomputed的區別?

watch就是用於監聽資料變化,比如監控頁面一個變數值的改變需要進行的操作 computed時用於處理複雜的邏輯運算的,它不必每次都像methods一樣呼叫,它有一個快取機制,只有在做出改變的時候才會執行,並且還可以把方法封裝到裡面,只返回一個數據

Vuewatchcomputed的使用演示

watch的使用 :使用watch 監聽firstName的變化 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>D

vueComputed Watch的使用區別

Computed: 可以關聯多個實時計算的物件,當這些物件中的其中一個改變時都會出發這個屬性。具有快取能力,所以只有當資料再次改變時才會重新渲染,否則就會直接拿取快取中的資料。 舉個例子: 當我們想讓div元素的背景色和文字顏色一致時,我們就可以使用comp

vuepromiseaxios 同步爬坑小記

es6提供給了我們promise這個物件,我們再也不用像原來那樣多個ajax巢狀來實現同步了,在小編看來,promise本質是語法糖,讓你能更優雅的解決同步問題!本文來說說小編遇到的問題,和個人見解,具體promise語法請大家自行閱讀! 小編遇到的主要問題是有2個非同步的