Vue项目基于vue-baidu-map绘制渐变轨迹及箭头

效果图
在这里插入图片描述

前提:引入百度地图

index.html文件中 引入

<script src="https://api.map.baidu.com/api?v=3.0&ak=***"></script>

注意:ak 为百度地图的秘钥,必须是v=3.0

一、CanvasLayer.js

function CanvasLayer(options) {
    this.options = options || {};
    this.paneName = this.options.paneName || 'labelPane';
    this.zIndex = this.options.zIndex || 0;
    this._map = options.map;
    this._lastDrawTime = null;
    this.show();
}

CanvasLayer.prototype = new BMap.Overlay();

CanvasLayer.prototype.initialize = function (map) {
    this._map = map;
    let canvas = this.canvas = document.createElement("canvas");
    let ctx = this.ctx = this.canvas.getContext('2d');
    canvas.style.cssText = "position:absolute;" +
        "left:0;" +
        "top:0;" +
        "z-index:" + this.zIndex + ";";
    this.adjustSize();
    this.adjustRatio(ctx);
    map.getPanes()[this.paneName].appendChild(canvas);
    let that = this;
    map.addEventListener('resize', function () {
        that.adjustSize();
        that.adjustRatio(ctx);
        that._draw();
    });
    return this.canvas;
}

CanvasLayer.prototype.adjustSize = function () {
    let size = this._map.getSize();
    let canvas = this.canvas;
    canvas.width = size.width;
    canvas.height = size.height;
    canvas.style.width = canvas.width + "px";
    canvas.style.height = canvas.height + "px";
}

CanvasLayer.prototype.adjustRatio = function (ctx) {
    let backingStore = ctx.backingStorePixelRatio ||
        ctx.webkitBackingStorePixelRatio ||
        ctx.mozBackingStorePixelRatio ||
        ctx.msBackingStorePixelRatio ||
        ctx.oBackingStorePixelRatio ||
        ctx.backingStorePixelRatio || 1;
    let pixelRatio = (window.devicePixelRatio || 1) / backingStore;
    let canvasWidth = ctx.canvas.width;
    let canvasHeight = ctx.canvas.height;
    ctx.canvas.width = canvasWidth * pixelRatio;
    ctx.canvas.height = canvasHeight * pixelRatio;
    ctx.canvas.style.width = canvasWidth + 'px';
    ctx.canvas.style.height = canvasHeight + 'px';
    ctx.scale(pixelRatio, pixelRatio);
};

CanvasLayer.prototype.draw = function () {
    let self = this;
    let args = arguments;

    clearTimeout(self.timeoutID);
    self.timeoutID = setTimeout(function () {
        self._draw.apply(self, args);
    }, 15);
}

CanvasLayer.prototype._draw = function () {
    let map = this._map;
    this.canvas.style.left = -map.offsetX + 'px';
    this.canvas.style.top = -map.offsetY + 'px';
    this.dispatchEvent('draw');
    this.options.update && this.options.update.apply(this, arguments);
}

CanvasLayer.prototype.getContainer = function () {
    return this.canvas;
}

CanvasLayer.prototype.show = function () {
    if (!this.canvas) {
        this._map.addOverlay(this);
    }
    this.canvas.style.display = "block";
}

CanvasLayer.prototype.hide = function () {
    this.canvas.style.display = "none";
    this._map.removeOverlay(this);
}

CanvasLayer.prototype.setZIndex = function (zIndex) {
    this.canvas.style.zIndex = zIndex;
}

CanvasLayer.prototype.getZIndex = function () {
    return this.zIndex;
}

export {CanvasLayer};

二、引入CanvasLayer.js
1.将CanvasLayer.js放在src/assets/js目录下
在这里插入图片描述
2.在使用的页面引入

import {CanvasLayer} from '@/assets/js/CanvasLayer';

3.使用CanvasLayer.js绘制渐变色及箭头

<template>
  <div class="map-box">
    <baidu-map 
    id="baiduMap" 
    style="width: 100%;height: 100%;z-index:0;" 
    :center="center" 
    :zoom="zoom" 
    @ready="handler"
    :min-zoom="5" 
    :max-zoom="15" 
    :scroll-wheel-zoom="true" 
    :mapClick="false" >
    </baidu-map>
  </div>
</template>

<script>
import {CanvasLayer} from '@/assets/js/CanvasLayer';
export default {
  data(){
    return{
      map:'',
      center:{
        lng:114.52785300795644,
        lat:38.14758574827796,
      },
      zoom:13,
      canvasLayer:null,
      canvasLayerPointer:null,
      dataArr:[
        {
          center:{
            lng:114.52785300795644,
            lat:38.14758574827796,
          },
          num:1,
        },
        {
          center:{
            lng:114.54050114953694,
            lat:38.13759635572114
          },
          num:10,
        },
        {
          center:{
            lng:114.56579743269792,
            lat:38.12419932394176
          },
          num:25,
        },
        {
          center:{
            lng:114.5908781225365,
            lat:38.12056580319661
          },
          num:51,
        },
        {
          center:{
            lng:114.6115750814864,
            lat:38.11613720325717
          },
          num:12,
        },
      ]
    }
  },
  methods:{
    //加载地图以及初始化数据
    handler({BMap,map}) {
      this.zoom = 13
      this.map = map //百度地图实例化对象
      this.drawRiver()
    },
    drawRiver(){
      var that = this
      // CanvasLayer构造函数需要两个参数: map为实例化后的地图对象 update:绘制的方法
      if (this.canvasLayer == null) {
        this.canvasLayer = new CanvasLayer({
          map: that.map,
          update: mapLine,
        });
      }
      if(this.canvasLayerPointer==null){
        this.canvasLayerPointer = new CanvasLayer({
          map: that.map,
          update: updatePointer,
        });
      }

      this.canvasLayer.draw()
      this.canvasLayerPointer.draw()
      
      // 渐变河流的绘制
      function mapLine() {
        // getContext() 方法返回一个用于在画布上绘图的环境。(创建画布环境,用于图案绘制)
        const ctx = that.canvasLayer.canvas.getContext('2d');
        if (!ctx) {
          return;
        }
        // clearRect() 方法擦除了指定的矩形,并且用一个透明的颜色填充它。(清除画布)
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        // 绘制带速度颜色的轨迹 
        for (let i = 0, len = that.dataArr.length; i < len - 1; i += 1) {
          //pointToPixel({lng,lat})将经纬度转化为坐标
          const pixel = that.map.pointToPixel(that.dataArr[i].center);
          const nextPixel = that.map.pointToPixel(that.dataArr[i + 1].center);
          //beginPath() 方法开始一条路径,或重置当前的路径。
          ctx.beginPath();
          //moveTo开始一条路径,移动初始位置 aPixel.x, aPixel.y。
          //lineTo创建到达位置 midPixel.x, midPixel.y 的一条线:
          ctx.moveTo(pixel.x, pixel.y); 
          ctx.lineTo(nextPixel.x, nextPixel.y);
          ctx.lineCap = 'round'; 绘制圆形的结束线帽 (线类型)例:'square'、'round'
          ctx.lineWidth = 16; //绘制宽度(可自定义)
          //createLinearGradient() 方法创建线性的渐变对象。需要四个参数 起点坐标和终点坐标进行渐变绘制
          const grd = ctx.createLinearGradient(pixel.x, pixel.y, nextPixel.x,nextPixel.y);
          //水质类型     
          const nowValue = that.dataArr[i].num
          const nextValue = that.dataArr[i + 1].num
          //gradient.addColorStop(stop,color);
          //stop 介于 0.0 与 1.0 之间的值,表示渐变中开始与结束之间的位置。
          //color 在结束位置显示的 CSS 颜色值
          grd.addColorStop(0, getColorByValue(nowValue));
          grd.addColorStop(1, getColorByValue(nextValue));
          //strokeStyle 设置渐变颜色。
          ctx.strokeStyle = grd;
          ctx.stroke();stroke() 方法会实际地绘制出通过 moveTo() 和 lineTo() 方法定义的路径。
        }
      }
      // 箭头的绘制
      function updatePointer() {
        // getContext() 方法返回一个用于在画布上绘图的环境。
        //当前唯一的合法值是 "2d",它指定了二维绘图,并且导致这个方法返回一个环境对象,该对象导出一个二维绘图。
        const ctx = that.canvasLayerPointer.canvas.getContext("2d");
        if (!ctx) {
          return;
        }
        // clearRect() 方法擦除了指定的矩形,并且用一个透明的颜色填充它。
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        if (that.dataArr.length !== 0) {
          for (let i = 0, len = that.dataArr.length; i < len - 1; i += 1) {
            //百度地图 将经纬度转为坐标值
            const pixel = that.map.pointToPixel(that.dataArr[i].center);//前一个坐标
            const nextPixel = that.map.pointToPixel(that.dataArr[i + 1].center);//后一个坐标
            //beginPath() 方法开始一条路径,或重置当前的路径。
            ctx.beginPath();
            // 根据渲染像素距离渲染箭头
            // Math.abs() 获取绝对值的方格
            if (
              Math.abs(nextPixel.x - pixel.x) > 10 ||
              Math.abs(nextPixel.y - pixel.y) > 10
            ) {
              /**
               * @method 获取以下五个点坐标
               * @param {Object} 起点 pixel                           
               * @param {Object} 终点 nextPixel
               * @param {Object} 中心点 midPixel
               * @param {Object} 箭头端点1 startPoint
               * @param {Object} 箭头端点2 endPoint
               */

              // 计算中心点
              const midPixel = new BMap.Pixel(
                (pixel.x + nextPixel.x) / 2,
                (pixel.y + nextPixel.y) / 2
              );
              // 起点终点距离 运用了数学中的勾股定理
              const distance = ((nextPixel.x - pixel.x) ** 2 + (nextPixel.y - pixel.y) ** 2) ** 0.5;
              // 箭头长度
              const pointerLong = 6;
              
              // 箭头端点1 --- 起点坐标
              const startPoint = arrowPoint(pointerLong,midPixel,distance,nextPixel,pixel).aPixel
              // 箭头端点2 --- 终点坐标
              const endPoint = arrowPoint(pointerLong,midPixel,distance,nextPixel,pixel).bPixel

              //moveTo开始一条路径,移动初始位置 startPoint.x, startPoint.y。
              //lineTo创建到达位置 midPixel.x, midPixel.y 的一条线:
              ctx.moveTo(startPoint.x, startPoint.y); //从端点1开始移动
              ctx.lineTo(midPixel.x, midPixel.y);//端点1画到中心点
              ctx.lineTo(endPoint.x, endPoint.y);//中心点画到端点2
              ctx.lineWidth = 3;//设置线对的宽度
              ctx.strokeStyle = "#eee";//设置线的颜色
              ctx.lineCap = "round";//绘制圆形的结束线帽
              ctx.stroke();//stroke() 方法会实际地绘制出通过 moveTo() 和 lineTo() 方法定义的路径。
            }
          }
        }
      }

      /**
       * @method getColorByValue 获取颜色
       * @param value 判断标准
       */
      function getColorByValue(value) {
        if (value <= 10) {
          return '#409eff'
        } else if (value > 10 && value <= 50) {
          return '#fcff40'
        } else {
          return '#f56c6c'
        }
      }

      /**
       * @method arrowPoint 箭头起点和终点坐标计算规则
       * @param pointerLong 箭头长度
       * @param midPixel 中心点
       * @param distance 两点之间的距离
       * @param nextPixel 终端
       * @param pixel 起点
       */
      function arrowPoint(pointerLong,midPixel,distance,nextPixel,pixel){
        // 声明箭头端点1的坐标
        const aPixel = {};
        // 声明箭头端点2的坐标
        const bPixel = {};
        // 箭头端点1、箭头端点2坐标计算规则
        if (nextPixel.x - pixel.x === 0) {// 下一个X轴坐标等于上一个坐标
          if (nextPixel.y - pixel.y > 0) {//下一个Y轴坐标大于上一个坐标
            aPixel.x = midPixel.x - pointerLong * 0.5 ** 0.5;
            aPixel.y = midPixel.y - pointerLong * 0.5 ** 0.5;
            bPixel.x = midPixel.x + pointerLong * 0.5 ** 0.5;
            bPixel.y = midPixel.y - pointerLong * 0.5 ** 0.5;
          } else if (nextPixel.y - pixel.y < 0) {//下一个Y轴坐标小于上一个坐标
            aPixel.x = midPixel.x - pointerLong * 0.5 ** 0.5;
            aPixel.y = midPixel.y + pointerLong * 0.5 ** 0.5;
            bPixel.x = midPixel.x + pointerLong * 0.5 ** 0.5;
            bPixel.y = midPixel.y + pointerLong * 0.5 ** 0.5;
          }
        } else { // 下一个X轴坐标不等于上一个坐标
          const k0 =
            (-(2 ** 0.5) * distance * pointerLong +
            2 * (nextPixel.y - pixel.y) * midPixel.y) /
            (2 * (nextPixel.x - pixel.x)) + midPixel.x;
          const k1 = -((nextPixel.y - pixel.y) / (nextPixel.x - pixel.x));
          const a = k1 ** 2 + 1;
          const b = 2 * k1 * (k0 - midPixel.x) - 2 * midPixel.y;
          const c =
            (k0 - midPixel.x) ** 2 + midPixel.y ** 2 - pointerLong ** 2;

          aPixel.y = (-b + (b * b - 4 * a * c) ** 0.5) / (2 * a);
          bPixel.y = (-b - (b * b - 4 * a * c) ** 0.5) / (2 * a);
          aPixel.x = k1 * aPixel.y + k0;
          bPixel.x = k1 * bPixel.y + k0;
        }
        return {aPixel,bPixel}
      }
    }
  }
}
</script>

<style scoped>
.map-box{
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}
</style>

注:本文基于此链接文章基础上进行整理,可查看 https://blog.csdn.net/Tron_future/article/details/112832289.
如若引用本文内容,请注明出处

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
要在Vue项目中使用百度地图进行点的绘制,你可以按照以下步骤进行操作: 1. 首先,在你的Vue项目中安装 vue-baidu-map 插件。可以通过以下命令进行安装: ``` npm install vue-baidu-map --save ``` 2. 在你的Vue组件中引入 vue-baidu-map: ```vue <template> <div> <baidu-map :ak="yourBaiduMapAK" v-if="loaded"></baidu-map> </div> </template> <script> import { BaiduMap } from 'vue-baidu-map' export default { components: { BaiduMap }, data() { return { yourBaiduMapAK: 'yourBaiduMapAK', loaded: false } }, mounted() { // 在mounted钩子函数中设置地图加载完成后的回调函数 this.$nextTick(() => { this.loaded = true this.initMap() }) }, methods: { initMap() { // 初始化地图 // 创建地图实例 let map = new BMap.Map("map-container") // 设置地图中心点 let point = new BMap.Point(116.404, 39.915) map.centerAndZoom(point, 15) // 创建标注物 let marker = new BMap.Marker(point) // 将标注物添加到地图map.addOverlay(marker) } } } </script> ``` 3. 在 `yourBaiduMapAK` 的位置,替换为你自己的百度地图开发者AK(API Key),可以在百度地图开放平台申请获取。 4. 在 `initMap` 方法中,可以根据需要设置地图的中心点和缩放级别,然后创建标注物,并将其添加到地图中。 5. 在页面中添加一个容器,用于渲染地图: ```html <div id="map-container"></div> ``` 这样,你就可以在Vue项目中使用 vue-baidu-map 插件进行点的绘制了。记得替换 `yourBaiduMapAK` 为你自己的百度地图开发者AK。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值