前端绘制地图中的地理坐标到屏幕坐标转换的简单思路--放大、缩小、移动

《地理坐标(经纬度坐标)和屏幕坐标(xy坐标)间的转换》的读后笔记 原文给出了一种基于向量法的对于坐标点的映射方式,该方式可用且原理简单。本文对原文的数学公式做了说明,并附加了Java代码的实现。 阅读详情

前端绘制地图中的地理坐标到屏幕坐标转换的简单思路–放大、缩小、移动

前言

为了让自己熟悉地图的绘制,我想手绘一个地图如何绘制的工具。使用了zrender库,这是一个canvas库,Echart基于此做。数据的来源则是一个geojson文件。下面就要解决一下如何进行绘制的问题包括:
1、地理坐标如何与屏幕坐标转换。
2、如何放大、缩小。
3、如何移动。

问题1 地理坐标系与屏幕坐标系如何进行转换

这里面我们是读取一个矢量数据在地图上绘制出来,思路如下:
0、明确浏览器坐标系是屏幕坐标系原点在左上角,地理坐标系原点是坐标系的原点。
1、找到屏幕坐标系的方框和地理坐标系的方框,找到屏幕坐标系的高度和地理坐标系的高度计算缩放比。

注:这里的缩放比,我是按照简单的思路来的,其实应该是选择最小的那个,然后将坐标挪到中间。

2、有了缩放比之后就明确了,地理坐标系和屏幕坐标系之间的缩放关系,之后开始计算地理坐标系在屏幕上的坐标。如图根据此点到左边的距离和到顶部的距离之后乘以缩放参数就会得到此点的屏幕坐标。
如何从地理坐标计算到屏幕坐标
3、转换完屏幕坐标之后就可以绘制了。如果初始时有默认的缩放级别参照下面的缩放算一下就行。

问题2 如何放到缩小

1 如何确定放大缩小系数

这里使用了mousewheel事件直接绑定在了zrender对象上。这里要处理的是缩放系数缩放系数也就是放大和缩小的倍数。 使用evt.wheelDelta参数大于0代表放大小于0代表缩小。通过这样计算出缩放系数。

var x = evt.offsetX;
var y = evt.offsetY;//距离容器
var scalefactor = 1.2;
evt.wheelDelta = evt.wheelDelta ? evt.wheelDelta : (evt.deltalY * (-40));  //获取当前鼠标的滚动情况
if (evt.wheelDelta > 0) {
            scalefactor *= 2;
} else {
            scalefactor /= 2;
}

参考 http://www.zhangxinxu.com/wordpress/2013/04/js-mousewheel-dommousescroll-event/

2 如何放大缩小

这里面的思路是:
1、直接将地理信息数据每个坐标乘以放大系数得到新的坐标但是这个坐标是向外扩展的,所以还要纠正回去、
2、计算鼠标缩放的原点的坐标与缩放之后的原点坐标的差值,作为纠正值,向原点纠正纠正之后放大缩小完成。

问题3 如何移动

主要思路 :
1、 使用事件mouseup和mousedown。
2、 计算两个事件的坐标差然后将数据坐标计算即可。

效果

如何从地理坐标计算到屏幕坐标

总结

效果简单但是还有很大的提升空间,解决了主要的问题剩下的还可以精进。

'手动实现的一个小地图'
function CanvasMap(render,mapdata){
    this.render = render;
    this.mapdata=mapdata;
    this.bound = this.returnMinXY(mapdata);
    console.log(mapdata,this.bound)
    var _my = this;
    var x1,y1,x2,y2;
    this.render.on("mousedown",function(evt){
        x1 = evt.offsetX;
        y1 = evt.offsetY;
    });
    this.render.on("mouseup",function(evt){
        x2 = evt.offsetX;
        y2 = evt.offsetY;
        var xfactor = x2-x1;
        var yfactor = y2-y1;
        _my.render.clear();
        _my.move(_my.mapdata,xfactor,yfactor);
        for (var i=0;i<_my.mapdata.features.length;i++){
            _my.addgeometry(_my.mapdata.features[i],false);
        }
    });
    this.render.on("mousewheel",function(evt){
        //  console.log(evt);
        var x = evt.offsetX;
        var y = evt.offsetY;//距离容器
        var scalefactor = 1.2;
        evt.wheelDelta = evt.wheelDelta ? evt.wheelDelta : (evt.deltalY * (-40));  //获取当前鼠标的滚动情况
        if (evt.wheelDelta > 0) {
            scalefactor *= 2;
        } else {
            scalefactor /= 2;
        }
        console.log(evt.wheelDelta)
        var sx = scalefactor*x;
        var sy = scalefactor*y;
        var sdisx =sx-x;
        var sdisy = sy-y;
        _my.sacle(_my.mapdata,scalefactor,sdisx,sdisy);
        _my.render.clear();
        for (var i=0;i<_my.mapdata.features.length;i++){
            _my.addgeometry(_my.mapdata.features[i],false);
        }

    });
}
/**
 * 
 * @param {一个geojson文件的对象} obj 
 */
CanvasMap.prototype.returnMinXY=function(obj){
    var factor = 20;
    var features = obj.features,feature = null,coor = null;
    var t = features[0].geometry.coordinates;
    var minx=t[0][0][0],miny=t[0][0][1],maxx=t[0][0][0],maxy=t[0][0][1];
    for (var z=0;z<features.length;z++){
        feature=features[z];
        coor = feature.geometry.coordinates;
        for (var i=0;i<coor.length;i++){
            for (var j=0;j<coor[i].length;j++){
                var coo = coor[i][j];
                if (minx >coo[0]  ){
                    minx = coo[0];
                }
                if (maxx <coo[0]){
                    maxx = coo[0];
                }
                if (miny >coo[1]){
                    miny = coo[1];
                }
                if (maxy <coo[1]){
                    maxy = coo[1];
                }
            }
        }
    }

    return {
        minx:minx,
        miny:miny,
        maxx:maxx,
        maxy:maxy
    }
}
/**
 * 坐标转换
 * 函数思路是这个样子的
 * 首先找出这里面的最左上角的坐标
 * 之后minx maxy
 * 之后算出点坐标与 左上角点的距离也就是曼哈顿距离 dx dy 
 * 之后把距离扩大扩大的factor为宽度的比
 * @param {*} geometry 
 * @param {*} bound 
 */
CanvasMap.prototype.changecoordinate = function(geometry,bound){
  // 获取外界矩形
  var factor = 400/(bound.maxy-bound.miny);//获取外边界
  var minx=bound.minx,miny=bound.miny,maxx=bound.maxx,maxy=bound.maxy;
  // //获得了外接矩形

  var coor = geometry.coordinates;
  var disx = 0,disy = 0;
  for (var i=0;i<coor.length;i++){
      for (var j=0;j<coor[i].length;j++){
          var coo =  coor[i][j];
         disx = coo[0]-minx;
         disy = maxy - coo[1];
         coor[i][j][0]=disx*factor;
         coor[i][j][1]=disy*factor;
      }
  }
}

CanvasMap.prototype.addgeometry = function(data,change){
    var bound = this.bound;
    var geometry = [];
    if (change!=false){
        this.changecoordinate(data.geometry,bound);
    }

    var polygon = new zrender.Polygon({
        shape: {
            points:data.geometry.coordinates[0]
        },
        style: {
            fill: 'none',
            stroke: '#c93756'
        }
    });
    this.render.add(polygon);
};

/**
 * 
 * @param {*} data 
 * @param {*} xfactor 
 * @param {*} yfactor 
 */
CanvasMap.prototype.move=function(data,xfactor,yfactor){
    console.log("move !!!!!!")
    for (var i=0;i<data.features.length;i++){
        var feature = data.features[i];
        movesingle(feature.geometry,xfactor,yfactor);
    }
    function movesingle (geometry,xfactor,yfactor){
        var coor = geometry.coordinates;
        var disx = 0,disy = 0;
        for (var i=0;i<coor.length;i++){
            for (var j=0;j<coor[i].length;j++){
                coor[i][j][0]=coor[i][j][0]+xfactor;
                coor[i][j][1]=coor[i][j][1]+yfactor;
            }
        }
    }
};

/**
 * 放大
 */
CanvasMap.prototype.sacle = function(data,scalefactor,sdisx,sdisy){
    for (var i=0;i<data.features.length;i++){
        var feature = data.features[i];
        scalesingle(feature.geometry,scalefactor,sdisx,sdisy);
    }
    function scalesingle (geometry,scalefactor){
        var coor = geometry.coordinates;
        var disx = 0,disy = 0;
        for (var i=0;i<coor.length;i++){
            for (var j=0;j<coor[i].length;j++){
                coor[i][j][0]=coor[i][j][0]*scalefactor-sdisx;
                coor[i][j][1]=coor[i][j][1]*scalefactor-sdisy;
            }
        }
    }
}
【Unity】坐标转换经纬度方法(原理篇) Unity坐标转换(线性变换) Demo下载 解决问题 针对缩放,旋转,翻转的两套坐标系转换。 线性变换原理 所有的线性坐标转换都是其基坐标的缩放和旋转。 变换公式 ∣abcd∣∣OiOj∣=∣TiTj∣ \begin{vmatrix} a & b \\ c & d\end{vmatrix}\begin{vmatrix} Oi \\ Oj\end{vmatrix}=\begin{vmatrix} Ti\\Tj\end{vmatrix} ∣∣∣∣​ac​bd​∣∣∣∣​∣∣∣∣​OiOj 阅读详情

相关推荐

地理坐标和屏幕坐标转换

地理坐标和屏幕坐标相互转换,代码详细,使用

关于屏幕坐标系和地理坐标系之间得转换

例如控件得大小是15*8,现在将一个5*4得矩形平铺到上面,所得到宽度比是0.3,意思也就是控件1像素对应矩形0.3像素,高度比是0.5,取最大得比例,因为如果取最小的,矩形的高度就会溢出控件的高度。屏幕坐标系转地理坐标系,首先在控件上选中一点,获取该点所距离最左侧的长度,将该长度转换为地理坐标系矩形的长度,然后再用地理包络矩形的最小X值加上当前长度,就是该点在地理坐标系上的位置(之所以加上地理包络矩形的最小X值,是因为地理坐标系并不是和屏幕坐标系一样从左上角0.0开始的),Y同上。

qq_40098572的博客 785

world-security.js 地图东西半球位置调换一下位置坐标

配合前面上传的世界地图位置使用的。,如果换了地图的位置,坐标可能不太精准,这个坐标我处理过,大家可以试试。

自定义控件(11)---Canvas的平移、旋转、缩放、错切、Matrix直接变换Canvas

Canvas中的变换操作,说起变换,无非就几种:平移、旋转、缩放和错切,而我们的Canvas也继承了变换的精髓,同样提供了这几种相应的方法,前面的很多章节我们也都用到了,像translate(float dx, float dy)方法平移画布用了无数次,这里再次强调,translate方法会改变画布的原点坐标,原点坐标对变换的影响弥足轻重,前面也多次强调了!scale(float sx, floa

全干工程师 7244

FEniCS学习笔记01:centos7下通过conda安装FEniCSx0.7

2023年版本的Fenicsx0.7,官网推荐使用conda命令安装集成好的Python包,因此我们的安装思路是先安装Anaconda,再按照官网步骤安装Fenics。

huahua_xiao的博客 5056

攻克+86手机号Discord验证墙:从“无效”到“成功”的实战指南

本文提供了一份针对+86手机号在Discord注册时频繁遭遇“手机号无效”问题的实战解决指南。文章系统分析了问题根源,并分步详解了从打造纯净网络环境、尝试多种手机号格式(如+86前加0),到更换iOS等客户端设备的有效方法,旨在帮助用户成功完成Discord手机号验证。

mac99的博客 1108

地理坐标(经纬度坐标)和屏幕坐标(xy坐标)间的转换

在我们的屏幕上,有一张地图,这张地图经过缩放、平移、旋转,最终地理坐标和屏幕坐标的关系大致如下图所示: 这种关系要怎么描述呢?我们可以假设地图是一张纸,而屏幕是一堵墙。只要我们有两个图钉,我们就能把纸定在墙上。我们把这两个点称为锚点。锚点在屏幕坐标系上的坐标是(x1,y1)和(x2,y2),对应在地理坐标系上的坐标是(lon1,lat1)和(lon2,lat2)。 那现在的问题就变成了,已...

lweiyue的专栏 4万+

统信UOS系统盘扩容保姆级教程:用GParten-分区编辑器5分钟搞定

本文提供统信UOS系统盘扩容的详细图形化教程。针对系统盘空间不足问题,重点介绍如何使用系统自带的GParten-分区编辑器,在5-10分钟内安全、直观地完成扩容操作,无需记忆复杂命令,适合所有用户快速解决存储空间告急的困扰。

e3f4g5的博客 640

前端地图分类(包括坐标系,GIS基础知识,2D与3D地图结构划分)

前端地图分类(包括坐标系,GIS基础知识,2D与3D地图结构划分)

m0_52009348的博客 3621

AM驱动架构—优质Mini-LED显示技术解决方案

(VR)和增强现实(AR)设备:MiniLED背光驱动方案适用于虚拟现实和增强现实设备中的显示技术,通过高亮度和高对比度的显示效果,创造更逼真的虚拟体验此外,MiniLED背光还能够实现更快的响应速度,减少图像残影,使得用户的动作在虚拟环境中更加流畅自然。以其出色的性能和广泛的应用前景备受关注是实现MiniLED显示效果的重要环节。1)更高的亮度和对比度:尺寸更小,可以在同样面积的显示屏上配置更多的LED,并且通过独立控制每一个MiniLED,可以实现更高的亮度和更细致的对比度,使得显示画面更加鲜明清晰。

isweekDN的博客 2762

HTML5网页基础设计——课程介绍专栏

案例: 参考代码: <!doctype html> <html> <head> <meta charset="utf-8"> <title>动手实践</title> <style> *{ margin: 0; padding: 0; font-size:14px; } dd{ width: 461px; height: 145px; margin: -4px; pad.

shengming_tutou的博客 4594

地理坐标与屏幕坐标转换(VC++)

在底层GIS开发中,我们经常会碰到空间数据可视化问题,当我们拿到地理数据之后,我们该怎么把它展现在我们的计算机屏幕中呢,这或许是一个比较简单的问题。 我们知道,地理坐标系是我们用户自定义的坐标系,而现实在计算机屏幕上的坐标是基于屏幕坐标来绘制的,那么改如何转化呢? 首先,我们来熟悉几个概念: 地理坐标系,通常原点在左下角,X轴的方向是向右递增,Y轴的方向是向上递增。 屏幕坐标系,通常它的原

心如止水-GISer的成长之路 1万+

32、社交媒体大数据中的情感分析与网络欺凌检测

本文探讨了社交媒体大数据在情感分析和网络欺凌检测中的应用。情感分析有助于应对自动化带来的社会变化、促进社会包容和推动环境保护。网络欺凌作为一种严重的在线危害,其检测依赖于数据预处理、特征提取与深度学习模型(如CNN、LSTM)进行分类。文章还总结了大数据在欺诈检测、医疗、制造、交通等领域的广泛应用,并分析了数据存储、处理速度、质量和技术工具等方面的挑战,提出了相应的应对策略。未来,随着技术进步,社交媒体大数据将在更多领域发挥关键作用。

cc789的博客 91

GIS 中地理坐标和屏幕坐标的标准转换方法

在GIS中,当你拿到一个图层的地理坐标后,如果需要绘制到屏幕上,那么不可避免的需要在地理坐标和屏幕坐标之间进行转换,转换的方法相信每一个做GIS的都会有自己的实现方法,本文描述的是和ArcGIS、WMS、OpenLayers完全一致的坐标转换方法,当然这三个工具、标准、脚本也是采用的相同的方法; 因为采用完全一致的坐标转换方法,因此在我自己实现的WMS服务程序中提供的含透明通道的图,可以完全和A...

weixin_30446197的博客 477

KEPServerEX 6 之 EX 6.11.718.0 发布说明

KEPServerEX 6.11.718.0 发布说明

-雲飛兄-博客 2881

【推荐100个unity插件】Animator 的替代品?—— Animancer Pro插件的使用介绍

Animancer与Unity Animator对比及使用指南 摘要: 本文对比了Animancer与Unity官方Animator的核心差异,分析了Animancer的优势特点。Animancer采用代码驱动模式,相比Animator的状态机系统更灵活高效,支持实时调试、动态混合和深度逻辑集成。文章详细介绍了Animancer的快速使用方法,包括动画播放、切换和触发机制,并区分了免费版与专业版的功能差异。适合需要高效动画开发、复杂交互逻辑的中小项目,为开发者提供了一种现代化的动画解决方案。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 2434

在MFC中绘制地图以及地理坐标与屏幕坐标转换详解(附工程源码)

在MFC中绘图时,因为都是以像素为单位的,所以我们只能以整数作为参数。如果我们想要把一幅地图数据绘制在MFC窗口中,地图的坐标数据肯定的含有小数位的,这样我们就不能直接在MFC中绘制地图了,这就涉及到地理坐标向屏幕坐标的转换。 1、地理坐标转屏幕坐标 首先我们看一张图(图片来源于网络,若涉及版权,请联系我删除),这张图片直接的描述了屏幕坐标和地理坐标之间的关系,采用的相似比法,其实就是对一个图...

XTAOTWO的博客 8051

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

arcgis 将地图点转换为屏幕坐标_ArcGIS。adf javascript 已知地理坐标X,Y如何转换成屏幕坐标?(小问题值100分!)...

//在地图上单击画点varmap=$find('Map1');map.getGeometry(ESRI.ADF.Graphics.ShapeType.Point,usePoint,null,'red','#0000FF','pointer',true);//获取鼠标点击的位置的地图坐标funct...//在地图上单击画点var map = $find('Map1');map.getGeometry...

weixin_39667797的博客 338

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

c语言经纬度转换成屏幕坐标,百度地图使用踩坑之屏幕坐标和地图坐标的转换...

首先:关于屏幕坐标和地图经纬度转换是最好是在baidumap.setonmapstatuschanglistener里面的onMapstatuschangefinish回调函数里面调用最好!(总结如果使用百度地图提供方法时遇到空指针,首先考虑此时地图是否是已经绘制完成,所以处理这类操作最好是在baidumap.setonmapstatuschanglistener里面的onMapstatuscha...

weixin_34145418的博客 552

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

在前端的角度总结各大地图底图

1、首先先明确地理坐标系以及投影坐标系两个概念 在我看到,根据单位比较容易区分两者。 地理坐标系 单位是经纬度。投影坐标系 单位是米、千米。 2、前端常用的几种坐标系。 地理坐标系:BD09、WGS84、GCJ02、GOOGLE、EPSG:4326 投影坐标系:EPSG:3857 3、各大地图底图 百度地图:BD09 (GCJ02加密后的坐标系) 天地图:WGS84 高德:GCJ02 谷歌:GOOGLE 4、EPSG:4326和EPSG:3857关系 4326...

qq_36802917的博客 1853

JS实现经纬度坐标转成XY坐标

经纬度坐标转换 话不多说,先上代码 function delta(lat, lon) { let PI =3.14159265358979324 let x_pi = 3.14159265358979324 * 3000.0 / 180.0 var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。 var ee = 0.00669342162296594323; // ee: 椭球的偏心率。 var x=lon - 105.0

qq_44890887的博客 4429

html5 canvas获取坐标系,HTML5 Canvas坐标变换

我们在使用 Canvas 绘制图形时,可能会想对绘制的图形进行变换,例如让图形旋转90度,或者让图像缩小放大等,这些效果都可以通过 Canvas API 的坐标轴变换处理功能来实现。图形旋转如果我们要想将图形进行旋转,例如下面这张图片:可以通过 rotate() 方法来实现这个效果,rotate() 方法用于旋转当前的绘图,带有一个参数 angle,表示旋转角度。旋转的中心点是坐标的原点,是以顺时...

weixin_39793564的博客 441

前端---几种地图坐标系之间的转换

原因是,不同的产品他们对经纬度的表达方式不同(用的不同坐标系表达坐标)1、GCJ-02(又叫火星坐标系),国测局02年发布的坐标,国内多家地图厂商通常都用这个。2、GPS坐标系。这里分WGS-84和CGCS2000坐标系(中国国家大地坐标系) 1)WGS-84坐标系:是GPS原始坐标体系,在中国,不允许任何一个地图产品直接使用WGS-84坐标下的地理数据,为了保密,不暴露真实坐标。 2)CGCS2000坐标系:国家大地坐标系 该坐标系是通过中国GPS 连续运行基准站、 空间大地控制网以及天文大地网与空间地网

前端小师姐迪迪_的博客 2473

前端在控制台获取元素坐标

前端在控制台获取元素坐标

林中有神君 579
上一篇: JS 的apply call bind的实现
下一篇: 循环队列计算
yatsov
博客等级 码龄16年 52粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值