前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >跟牛老师一起学WEBGIS——WEBGIS实现(绘制点)

跟牛老师一起学WEBGIS——WEBGIS实现(绘制点)

作者头像
牛老师讲GIS
发布2020-12-07 10:35:49
7000
发布2020-12-07 10:35:49
举报
文章被收录于专栏:跟牛老师一起学WEBGIS

三、WEBGIS实现

后面的课程会以mapboxGLcanvas-source为入口开展,通过一个canvas画布,实现webgis的基础功能,包括:1、展示矢量数据(点、线、面,格式为geojson);2、展示x-y-z切片;3、展示wms服务。webgis基础功能部分,有一个比较核心的是前面的文章里面提到的屏幕坐标和地图坐标的相互转换,在mapboxGL中,可以通过map.project()实现地图坐标转换为屏幕坐标,通过map.unproject()实现屏幕坐标转换为地图坐标。

为方便后面使用,先将公用的部分拿出来,代码如下:

代码语言:javascript
复制
var CanvasLayer = function(map, data, style = {}) {
    this._data = data;
    this._map = map;
    this._canvas = null;
    this._ctx = null
    this._init(data);
    return this;
}
/**
 * 初始化
 * @param data
 * @private
 */
CanvasLayer.prototype._init = function (data) {
    const that = this;
    // 初始化canvas图层
    that._canvas = document.createElement('canvas');
    that._canvas.setAttribute('id', 'mapcanvas');
    var w = that._map.getCanvas().width,
        h = that._map.getCanvas().height;
    that._canvas.setAttribute('width', w);
    that._canvas.setAttribute('height', h);
    that._map.getCanvasContainer().appendChild(that._canvas);
    that._canvas.style.display = 'none';
    that._ctx = that._canvas.getContext('2d');

    that._map.addSource('canvas-source', {
        type: 'canvas',
        canvas: 'mapcanvas',
        coordinates: that._getMapExtent(),
        animate: true
    });
    that._map.addLayer({
        id: 'canvas-layer',
        type: 'raster',
        source: 'canvas-source'
    });
    that._map.on('movestart', function () {
        that._ctx.clearRect(0, 0, that._canvas.width, that._canvas.height);
    });
    that._map.on('zoomstart', function () {
        that._ctx.clearRect(0, 0, that._canvas.width, that._canvas.height);
    });
    that._map.on('moveend', function () {
        that._map.getSource('canvas-source').setCoordinates(that._getMapExtent());
        that._showData2Map();
    });

    // 如果为url,获取数据
    if(typeof data === 'string') {
        $.ajax({
            type:"get",
            url : data,
            async: false,
            success: function (res) {
                that._data = res;
                that._showData2Map();
            }
        })
    }
}
/**
 * 16位转换为rgba
 * @param color
 * @param opacity
 * @returns {string}
 * @private
 */
CanvasLayer.prototype._convertHexToRGB = function (color, opacity = 1) {
    if (color.length === 4) {
        let extendedColor = "#"
        for (let i = 1; i < color.length; i++) {
            extendedColor += color.charAt(i) + color.charAt(i)
        }
        color = extendedColor
    }
    const values = {
        r: parseInt(color.substr(1, 2), 16),
        g: parseInt(color.substr(3, 2), 16),
        b: parseInt(color.substr(5, 2), 16),
    }
    return `rgba(${values.r}, ${values.g}, ${values.b}, ${opacity})`;
}
/**
 * 获取地图的四至
 * @returns {[[*, *], [*, *], [*, *], [*, *]]}
 * @private
 */
CanvasLayer.prototype._getMapExtent = function () {
    var xmin = this._map.getBounds().getWest(),
        xmax = this._map.getBounds().getEast(),
        ymin = this._map.getBounds().getSouth(),
        ymax = this._map.getBounds().getNorth();
    return [
        [xmin, ymax],
        [xmax, ymax],
        [xmax, ymin],
        [xmin, ymin]
    ];
}
/**
 * 将地理坐标转换为屏幕坐标
 * @param coords
 * @returns {*}
 * @private
 */
CanvasLayer.prototype._map2pixel = function (coords) {
    const that = this;
    return that._map.project(coords);
}
/**
 * 将屏幕坐标转换为地理坐标
 * @param pixel
 * @returns {*}
 * @private
 */
CanvasLayer.prototype._pixel2map = function (pixel) {
    const that = this;
    return that._map.unproject(pixel);
}
/**
 * 将数据展示到地图上
 * @private
 */
CanvasLayer.prototype._showData2Map = function () {
    const that = this;
    const features = that._data.features;
    const geomType = features[0].geometry.type;
    switch (geomType) {
        case "Point": {
            that._showPoint2Map();
            break;
        }
        case "MultiPoint": {
            that._showMultiPoint2Map();
            break;
        }
        case "LineString": {
            that._showLine2Map();
            break;
        }
        case "MultiLineString": {
            that._showMultiLine2Map();
            break;
        }
        case "Polygon": {
            that._showPolygon2Map();
            break;
        }
        case "MultiPolygon": {
            that._showMultiPolygon2Map();
            break;
        }
    }
}

1、点数据绘制

1.1 绘制简单点

简单点的绘制方式我们分两种:圆形和方形,包括填充和边框。实现代码如下:

代码语言:javascript
复制
/**
 * 在地图上打点
 * @private
 */
CanvasLayer.prototype._showPoint2Map = function () {
    const that = this;
    const features = that._data.features;
    for (let i = 0; i < features.length; i++) {
        const coords = features[i].geometry.coordinates;
        that._drawPoint(coords);
    }
}
/**
 * 在地图上打多点
 * @private
 */
CanvasLayer.prototype._showMultiPoint2Map = function () {
    const that = this;
    const features = that._data.features;
    for (let i = 0; i < features.length; i++) {
        const coordinates = features[i].geometry.coordinates;
        for (let j = 0; j < coordinates.length; j++) {
            const coords = coordinates[j];
            that._drawPoint(coords);
        }
    }
}
/**
 * 绘制点
 * @param coords
 * @private
 */
CanvasLayer.prototype._drawPoint = function (coords) {
    const that = this;
    const pixel = that._map2pixel(coords);
    const x = pixel.x, y = pixel.y;
    const pointStyle = {
        type: 'circle', // circle, rect
        size: 5,
        color: '#00f',
        opacity: 1,
        borderWidth: 2,
        borderColor: '#ff0000',
        borderOpacity: 0.5
    };
    const size = pointStyle.size;
    const type = pointStyle.type;
    that._ctx.beginPath();
    type === 'rect'
        ? that._ctx.rect(x - size, y - size, size * 2, size * 2)
        : that._ctx.arc(x, y, size, 0, Math.PI * 2, true);
    that._ctx.closePath();
    // 边框
    if(pointStyle.borderWidth) {
        that._ctx.strokeStyle = that._convertHexToRGB(pointStyle.borderColor, pointStyle.borderOpacity);
        that._ctx.lineWidth = pointStyle.borderWidth + size;
        that._ctx.stroke();
    }
    // 填充
    if(pointStyle.color) {
        that._ctx.fillStyle = that._convertHexToRGB(pointStyle.color, pointStyle.opacity);
        that._ctx.fill();
    }
}

实现后效果如下:

1.2 绘制图标

为了更加灵活,本文讲述sprite图标的绘制方式。sprite图标参考了mapboxGL的实现方式,分为两个文件:.png.json,示例图标如下:

代码语言:javascript
复制
/**
 * 在地图上展示图标
 * @private
 */
CanvasLayer.prototype._showIcon2Map = function () {
    const that = this;
    const img = new Image();
    img.src = "/mapbox-lecture/lecture/data/sprite.png";
    img.onload = function () {
        $.ajax({
            type: 'get',
            url: '/mapbox-lecture/lecture/data/sprite.json',
            success: function (res){
                that._iconStyle.img = img;
                that._iconStyle.data = res;
                const features = that._data.features;
                for (let i = 0; i < features.length; i++) {
                    const coords = features[i].geometry.coordinates;
                    that._drawIcon(coords);
                }
            }
        })
    }
}
CanvasLayer.prototype._drawIcon = function (coords) {
    const that = this;
    const pixel = that._map2pixel(coords);
    const x = pixel.x, y = pixel.y;
    const iconStyle = that._iconStyle;
    const iconData = iconStyle.data[iconStyle.icon];
    const size = [iconData.width * iconStyle.size, iconData.height * iconStyle.size]
    that._ctx.drawImage(iconStyle.img,
        iconData.x, iconData.y,
        iconData.width, iconData.height,
        x - size[0] / 2, y - size[1] / 2,
        size[0], size[1]
    );
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/12/02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 三、WEBGIS实现
    • 1、点数据绘制
      • 1.1 绘制简单点
      • 1.2 绘制图标
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档