当前位置: 首页 > article >正文

二维绘图,地图(Openlayers/Leafletjs)

 绘图工具

图表(数据可视化):Chart.js 、ECharts.js、Highcharts.js、D3.js

流程图:vueflow

Canvas 2D:Fabric.js、ZRender.js

矢量图(SVG,VML):SVG.js、ZRender.js

地图层叠(GIS):Echarts Map、Mapv、AntV L7、deck.gl、Leafletjs、Openlayers、Maptalks.js、Mapbox-gljs(不开源)

地图辅助工具:Turf.js(地图计算)、Gcoord.js(地图坐标)、chaikin-smooth(平滑曲线)

地图数据源:腾讯地图、百度地图、高德地图、天地图、BigMap

地图区域数据:GeoJSON、 DataV.GeoAtlas、Index of /examples/data/asset/geo

 Canvas 2D

案例:图片上画8点框

<template>
      <div class="image-json" :style="{ width: canvas2dWidth + 'px', height: canvas2dHeight + 'px', backgroundImage: `url(${imgUrl})` }">
        <canvas ref="canvas_2d" :width="canvas2dWidth" :height="canvas2dHeight"></canvas>
      </div>
</template>

<script setup>
import { ref } from 'vue';

let imgUrl = ref('');
let jsonUrl = ref('');  // 框数据
let canvas2dWidth = ref(800);
let canvas2dHeight = ref(450);
let canvas_2d = ref();

const renderImageJson = () => {
  let imgPro = new Promise((resolve, reject) => {
    let img = new Image();
    img.src = imgUrl.value;
    img.onload = () => {
      resolve(img);
    };
  });
  let jsonPro = new Promise((resolve, reject) => {
    fetch(jsonUrl.value).then((res) => {
      res.json().then((result) => {
        resolve(result);
      });
    });
  });
  Promise.all([imgPro, jsonPro]).then((result) => {
    let img = result[0];
    let json = result[1];
    let zoom = 1; // 缩放比
    let left = 0, top = 0; // 图片左上角在画布中的坐标

    if (img.naturalWidth / img.naturalHeight > canvas2dWidth.value / canvas2dHeight.value) {
      zoom = canvas2dWidth.value / img.naturalWidth;
      left = 0;
      top = (canvas2dHeight.value - img.naturalHeight * zoom) / 2;
    } else {
      zoom = canvas2dHeight.value / img.naturalHeight;
      top = 0;
      left = (canvas2dWidth.value - img.naturalWidth * zoom) / 2;
    }
    let context2d = canvas_2d.value.getContext('2d');
    context2d.clearRect(0, 0, canvas2dWidth.value, canvas2dHeight.value);
    // 图片也可以通过这种方式画上 context2d.drawImage(img, left, top, img.naturalWidth * zoom, img.naturalHeight * zoom);

      json.forEach((box) => {
        // 在一次 beginPath() 和 stroke() 之间,strokeStyle 只能生效一次
        context2d.beginPath();
        context2d.strokeStyle = '#ff0000';
        // 下底 4 条边
        context2d.moveTo(left + box[0].x * zoom, top + box[0].y * zoom);
        context2d.lineTo(left + box[1].x * zoom, top + box[1].y * zoom);
        context2d.lineTo(left + box[2].x * zoom, top + box[2].y * zoom);
        context2d.lineTo(left + box[3].x * zoom, top + box[3].y * zoom);
        context2d.lineTo(left + box[0].x * zoom, top + box[0].y * zoom);
        // 上底 4 条边
        context2d.moveTo(left + box[4].x * zoom, top + box[4].y * zoom);
        context2d.lineTo(left + box[5].x * zoom, top + box[5].y * zoom);
        context2d.lineTo(left + box[6].x * zoom, top + box[6].y * zoom);
        context2d.lineTo(left + box[7].x * zoom, top + box[7].y * zoom);
        context2d.lineTo(left + box[4].x * zoom, top + box[4].y * zoom);
        // 竖边
        context2d.moveTo(left + box[0].x * zoom, top + box[0].y * zoom);
        context2d.lineTo(left + box[4].x * zoom, top + box[4].y * zoom);
        context2d.moveTo(left + box[1].x * zoom, top + box[1].y * zoom);
        context2d.lineTo(left + box[5].x * zoom, top + box[5].y * zoom);
        context2d.moveTo(left + box[2].x * zoom, top + box[2].y * zoom);
        context2d.lineTo(left + box[6].x * zoom, top + box[6].y * zoom);
        context2d.moveTo(left + box[3].x * zoom, top + box[3].y * zoom);
        context2d.lineTo(left + box[7].x * zoom, top + box[7].y * zoom);
        // 每次 beginPath() 后得 stroke() 才能生效
        context2d.stroke();
      });
  });
};

</script>

<style lang="scss" scoped>
.image-json {
  position: relative;
  background-size: contain; // 图片比容器小时会放大图片到贴边
  background-position: center;
  background-repeat: no-repeat;
}
</style>

 Openlayers

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <link href="https://lib.baomitu.com/ol3/4.6.5/ol.css" rel="stylesheet" />
    <script src="https://lib.baomitu.com/ol3/4.6.5/ol.js"></script>
    <style>
      .ol-zoomslider {
        top: 7.5em;
      }
    </style>
  </head>
  <body>
    <div id="map_ele"></div>
    <script>
      /* 图层与地图 */
      // 瓦片图层
      const gaode = new ol.layer.Tile({
        title: "高德地图",
        source: new ol.source.XYZ({
          url: "http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7", // 高德地图瓦片地址
          wrapX: false,
          // 自定义瓦片服务
          tileUrlFunction: (zxy) => {
                    let [z, x, y] = zxy; // z 即 缩放级别,xy 为序号,参照Web墨卡托投影坐标系
                    return `/tile/${z}/${x}/${y}.png`; // 256px * 256px 的图片
                },
        }),
      });
      // 地图
      const map = new ol.Map({
        target: "map_ele",
        layers: [gaode], // 使用图层
        view: new ol.View({
          center: [114.3, 30.5], // 视图中心点
          zoom: 10, // 缩放级别
          projection: "EPSG:4326", // 坐标系
        }),
      });

      /* 控件 */
      // 跳到指定范围 按钮控件
      const zoomToExtent = new ol.control.ZoomToExtent({
        extent: [110, 30, 120, 40],
      });
      map.addControl(zoomToExtent);
      // 调整缩放级别 滑块控件
      map.addControl(new ol.control.ZoomSlider());
      // 全屏 控件
      map.addControl(new ol.control.FullScreen());

      /* 矢量元素 */
      // 元素样式
      let style = new ol.style.Style({
        image: new ol.style.Circle({
          radius: 10, // 单位是像素
          fill: new ol.style.Fill({
            color: "#ff2d51",
          }),
          stroke: new ol.style.Stroke({
            width: 2, // 单位是像素
            color: "#333",
          }),
        }),
      });
      // 点元素
      const point = new ol.Feature({
        geometry: new ol.geom.Point([114.3, 30.5]),
      });
      point.setStyle(style);
      // 矢量图层
      let layer = new ol.layer.Vector({
        source: new ol.source.Vector({
          features: [point],
        }),
      });
      map.addLayer(layer);

      /* geojson 矢量元素之点 */
      let geojson = {
        type: "FeatureCollection",
        features: [
          {
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [114.3, 30.6],
            },
          },
        ],
      };
      layer = new ol.layer.Vector({
        source: new ol.source.Vector({
          features: new ol.format.GeoJSON().readFeatures(geojson),
        }),
      });
      layer.setStyle(style);
      map.addLayer(layer);

      /* geojson 矢量元素之线条、区域 */
      geojson = {
        type: "FeatureCollection",
        features: [
          {
            type: "Feature",
            geometry: {
              type: "LineString",
              coordinates: [
                [114.3, 30.5],
                [114.3, 30.6],
              ],
            },
          },
          {
            type: "Feature",
            geometry: {
              type: "Polygon",
              coordinates: [
                [
                  [114.4, 30.5],
                  [114.4, 30.6],
                  [114.5, 30.5],
                ],
              ],
            },
          },
        ],
      };
      layer = new ol.layer.Vector({
        source: new ol.source.Vector({
          features: new ol.format.GeoJSON().readFeatures(geojson),
        }),
      });
      style = new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: "#ff2d51",
          width: 3,
        }),
        fill: new ol.style.Fill({
          color: "rgba(50, 50, 50, 0.3)",
        }),
      });
      layer.setStyle(style);
      map.addLayer(layer);

      /* 加载geojson */
      layer = new ol.layer.Vector({
        source: new ol.source.Vector({
          url: "./USA.json",
          format: new ol.format.GeoJSON(),
        }),
      });
      map.addLayer(layer);

      /* 点击事件 */
      map.on("click", (evt) => {
        let { coordinate } = evt;
        const view = map.getView();
        // 飞行
        view.animate({
          center: coordinate,
          zoom: 8,
          duration: 3000,
        });
      });
    </script>
  </body>
</html>

 Leafletjs

安装

npm install leaflet --save

导入

import 'leaflet/dist/leaflet.css'
import L from 'leaflet'

容器

  <div id="mapx"></div>

加载

let map = L.map('map').setView([90.56466, 39.7385], 8)  // 中心点[纬度,经度],层级
L.tileLayer('http://***/{z}/{x}/{y}.png', {  // 瓦片服务
    maxZoom: 17,             // 最大缩放级别
    minZoom: 0,              // 最小缩放级别
}).addTo(map)

let meta = await fetch(`http://***/meta.json`).then(response => response.text()).then(str => JSON.parse(str)) // TMS (Tile Map Service) 目录里会有一个元数据文件
let bounds = L.latLngBounds(L.latLng(meta.latLonBounds.north, meta.latLonBounds.west), L.latLng(meta.latLonBounds.south, meta.latLonBounds.east)) // 有瓦片区域的经纬度范围   L.tileLayer(`http://***/{z}/{x}/{y}.${meta.contentType.substring(meta.contentType.lastIndexOf('/') + 1)}`, {
          tileSize: meta.tilesize,
          minZoom: meta.minzoom,
          maxZoom: meta.maxzoom,
          tms: true   // 数据格式为 TMS (Tile Map Service) 
        }).addTo(map)  // 可以多个 layer 分别 addTo(map),即叠加
map.fitBounds(bounds)  // 中心点 和 缩放级别 调整到刚好能看全区域

// 自定义 marker 图标
let markerIcon = L.icon({
    iconUrl: './marker.png',
    iconSize: [16, 16],  // 图标尺寸
    iconAnchor: [8, 8], // 图标锚点,即图标的中心点
});
L.marker([latitude, longitude], {icon: markerIcon}).addTo(map).on('click', () => {
    // 点击图标
})


http://www.kler.cn/a/408021.html

相关文章:

  • JavaEE 实现 登录+注册(采用注解方式链接数据库)
  • go语言示例代码
  • 微信小程序包之加农炮游戏
  • Spring Aop+自定义注解实践(待完善日志)
  • windows10下3DGS环境配置
  • Rust 力扣 - 2466. 统计构造好字符串的方案数
  • Redis的理解
  • cangjie (仓颉) vscode环境搭建
  • 2024年亚太杯数学建模竞赛赛题选题人数发布
  • Qt之QWidget相关
  • 7、深入剖析PyTorch nn.Module源码
  • 【入门篇】欧几里德最差序列——多语言求解版
  • 后端:事务
  • RabbitMQ2:介绍、安装、快速入门、数据隔离
  • 八、无刷电机电压电流温度采集
  • CSS布局学习1
  • Oracle SQL优化②——访问路径
  • 使用 Elastic AI Assistant for Search 和 Azure OpenAI 实现从 0 到 60 的转变
  • 2-测试bigcache做进程内缓存 --开源项目obtain_data测试
  • Python爬虫:获取1688店铺详情的实战指南