如何在react-leaflet中制作一个椭圆形?

2024-02-02

我正在尝试在使用制作的地图上绘制一个椭圆react-leaflet,它内置了对圆形和矩形的支持。

为了实现这一点,我使用代码在(非反应)中生成一个椭圆leaflet from here https://github.com/jdfergason/Leaflet.Ellipse,我已对其进行了调整并粘贴如下:

import * as L from 'leaflet';


L.SVG.include ({
    _updateEllipse: function (layer) {
        var // c = layer._point,
            rx = layer._radiusX,
            ry = layer._radiusY,
            phi = layer._tiltDeg,
            endPoint = layer._endPointParams;

        var d = 'M' + endPoint.x0 + ',' + endPoint.y0 +
            'A' + rx + ',' + ry + ',' + phi + ',' +
            endPoint.largeArc + ',' + endPoint.sweep + ',' +
            endPoint.x1 + ',' + endPoint.y1 + ' z';
        this._setPath(layer, d);
    }
});

L.Canvas.include ({
    _updateEllipse: function (layer) {
        if (layer._empty()) { return; }

        var p = layer._point,
            ctx = this._ctx,
            r = layer._radiusX,
            s = (layer._radiusY || r) / r;

        this._drawnLayers[layer._leaflet_id] = layer;

        ctx.save();

        ctx.translate(p.x, p.y);
        if (layer._tilt !== 0) {
            ctx.rotate( layer._tilt );
        }
        if (s !== 1) {
            ctx.scale(1, s);
        }

        ctx.beginPath();
        ctx.arc(0, 0, r, 0, Math.PI * 2);
        ctx.restore();

        this._fillStroke(ctx, layer);
    },
});

L.Ellipse = L.Path.extend({

    options: {
        fill: true,
        startAngle: 0,
        endAngle: 359.9
    },

    initialize: function (latlng, radii, tilt, options) {

        L.setOptions(this, options);
        this._latlng = L.latLng(latlng);

        if (tilt) {
            this._tiltDeg = tilt;
        } else {
            this._tiltDeg = 0;
        }

        if (radii) {
            this._mRadiusX = radii[0];
            this._mRadiusY = radii[1];
        }
    },

    setRadius: function (radii) {
        this._mRadiusX = radii[0];
        this._mRadiusY = radii[1];
        return this.redraw();
    },

    getRadius: function () {
        return new L.point(this._mRadiusX, this._mRadiusY);
    },

    setTilt: function (tilt) {
        this._tiltDeg = tilt;
        return this.redraw();
    },

    getBounds: function () {
        // TODO respect tilt (bounds are too big)
        var lngRadius = this._getLngRadius(),
            latRadius = this._getLatRadius(),
            latlng = this._latlng;

        return new L.LatLngBounds(
            [latlng.lat - latRadius, latlng.lng - lngRadius],
            [latlng.lat + latRadius, latlng.lng + lngRadius]);
    },

    // @method setLatLng(latLng: LatLng): this
    // Sets the position of a circle marker to a new location.
    setLatLng: function (latlng) {
        this._latlng = L.latLng(latlng);
        this.redraw();
        return this.fire('move', {latlng: this._latlng});
    },

    // @method getLatLng(): LatLng
    // Returns the current geographical position of the circle marker
    getLatLng: function () {
        return this._latlng;
    },

    setStyle: L.Path.prototype.setStyle,

    _project: function () {
        var lngRadius = this._getLngRadius(),
            latRadius = this._getLatRadius(),
            latlng = this._latlng,
            pointLeft = this._map.latLngToLayerPoint([latlng.lat, latlng.lng - lngRadius]),
            pointBelow = this._map.latLngToLayerPoint([latlng.lat - latRadius, latlng.lng]);

        this._point = this._map.latLngToLayerPoint(latlng);
        this._radiusX = Math.max(this._point.x - pointLeft.x, 1);
        this._radiusY = Math.max(pointBelow.y - this._point.y, 1);
        this._tilt = Math.PI * this._tiltDeg / 180;
        this._endPointParams = this._centerPointToEndPoint();
        this._updateBounds();
    },

    _updateBounds: function () {
        // http://math.stackexchange.com/questions/91132/how-to-get-the-limits-of-rotated-ellipse
        var sin = Math.sin(this._tilt);
        var cos = Math.cos(this._tilt);
        var sinSquare = sin * sin;
        var cosSquare = cos * cos;
        var aSquare = this._radiusX * this._radiusX;
        var bSquare = this._radiusY * this._radiusY;
        var halfWidth = Math.sqrt(aSquare*cosSquare+bSquare*sinSquare);
        var halfHeight = Math.sqrt(aSquare*sinSquare+bSquare*cosSquare);
        var w = this._clickTolerance();
        var p = [halfWidth + w, halfHeight + w];
        this._pxBounds = new L.Bounds(this._point.subtract(p), this._point.add(p));
    },

    _update: function () {
        if (this._map) {
            this._updatePath();
        }
    },

    _updatePath: function () {
        this._renderer._updateEllipse(this);
    },

    _getLatRadius: function () {
        return (this._mRadiusY / 40075017) * 360;
    },

    _getLngRadius: function () {
        return ((this._mRadiusX / 40075017) * 360) / Math.cos((Math.PI / 180) * this._latlng.lat);
    },

    _centerPointToEndPoint: function () {
        // Convert between center point parameterization of an ellipse
        // too SVG's end-point and sweep parameters.  This is an
        // adaptation of the perl code found here:
        // http://commons.oreilly.com/wiki/index.php/SVG_Essentials/Paths
        var c = this._point,
            rx = this._radiusX,
            ry = this._radiusY,
            theta2 = (this.options.startAngle + this.options.endAngle) * (Math.PI / 180),
            theta1 = this.options.startAngle * (Math.PI / 180),
            delta = this.options.endAngle,
            phi = this._tiltDeg * (Math.PI / 180);

        // Determine start and end-point coordinates
        var x0 = c.x + Math.cos(phi) * rx * Math.cos(theta1) +
            Math.sin(-phi) * ry * Math.sin(theta1);
        var y0 = c.y + Math.sin(phi) * rx * Math.cos(theta1) +
            Math.cos(phi) * ry * Math.sin(theta1);

        var x1 = c.x + Math.cos(phi) * rx * Math.cos(theta2) +
            Math.sin(-phi) * ry * Math.sin(theta2);
        var y1 = c.y + Math.sin(phi) * rx * Math.cos(theta2) +
            Math.cos(phi) * ry * Math.sin(theta2);

        var largeArc = (delta > 180) ? 1 : 0;
        var sweep = (delta > 0) ? 1 : 0;

        return {'x0': x0, 'y0': y0, 'tilt': phi, 'largeArc': largeArc,
            'sweep': sweep, 'x1': x1, 'y1': y1};
    },

    _empty: function () {
        return this._radiusX && this._radiusY && !this._renderer._bounds.intersects(this._pxBounds);
    },

    _containsPoint : function (p) {
        // http://stackoverflow.com/questions/7946187/point-and-ellipse-rotated-position-test-algorithm
        var sin = Math.sin(this._tilt);
        var cos = Math.cos(this._tilt);
        var dx = p.x - this._point.x;
        var dy = p.y - this._point.y;
        var sumA = cos * dx + sin * dy;
        var sumB = sin * dx - cos * dy;
        return sumA * sumA / (this._radiusX * this._radiusX)  + sumB * sumB / (this._radiusY * this._radiusY) <= 1;
    }
});

export const lellipse = function (latlng, radii, tilt, options) {
    return new L.Ellipse(latlng, radii, tilt, options);
};

创建要使用的椭圆react-leaflet,我效仿了Circle in react-leaflet https://github.com/PaulLeCam/react-leaflet/blob/master/src/Circle.js产生以下Ellipse成分:

import PropTypes from 'prop-types'

import { lellipse as LeafletEllipse } from '../l.ellipse';
import Path from './Path'
import children from './propTypes/children'
import latlng from './propTypes/latlng'
import type { LatLng, MapLayerProps, PathOptions } from './types'

type LeafletElement = LeafletEllipse
type Props = {
  center: LatLng,
  mSemiMajorAxis: number,
  mSemiMinorAxis: number,
  degreeTiltFromWest: number,
} & MapLayerProps &
  PathOptions &
  Object

export default class Ellipse extends Path<LeafletElement, Props> {
  static propTypes = {
    center: latlng.isRequired,
    mSemiMajorAxis: PropTypes.number.isRequired,
    mSemiMinorAxis: PropTypes.number.isRequired,
    degreeTiltFromWest: PropTypes.number.isRequired,
    children: children,
  }

  createLeafletElement(props: Props): LeafletElement {
    const { center, mSemiMajorAxis, mSemiMinorAxis, degreeTiltFromWest, ...options } = props
    return new LeafletEllipse(center, [mSemiMajorAxis, mSemiMinorAxis], this.getOptions(options))
  }

  updateLeafletElement(fromProps: Props, toProps: Props) {
    if (toProps.center !== fromProps.center) {
      this.leafletElement.setLatLng(toProps.center);
    }
    if (toProps.degreeTiltFromWest !== fromProps.degreeTiltFromWest) {
      this.leafletElement.setTilt(toProps.degreeTiltFromWest);
    }
    if (toProps.mSemiMinorAxis !== fromProps.mSemiMinorAxis || toProps.mSemiMajorAxis !== fromProps.mSemiMajorAxis) {
      this.leafletElement.setRadius([toProps.mSemiMajorAxis, toProps.mSemiMinorAxis]);
    }

  }
}

该代码的问题在于它不会渲染椭圆并且不会引发任何错误。有人可以建议如何渲染椭圆吗react-leaflet?谢谢。


Your 创建传单元素函数缺少倾斜参数。它应该是:

   createLeafletElement(props) {
        const { center, mSemiMajorAxis, mSemiMinorAxis, degreeTiltFromWest, ...options } = props
        return new LeafletEllipse(center, [mSemiMajorAxis, mSemiMinorAxis], degreeTiltFromWest, this.getOptions(options))
    }

请参阅下面的完整文件(在 ES6 中而不是在 typescript 中,因为我发现它更清楚)。

import React, { PropTypes } from 'react';
import { lellipse as LeafletEllipse } from './l.ellipse';
import { Path, withLeaflet } from 'react-leaflet';

class Ellipse extends Path {

    static propTypes = {
        center: PropTypes.arrayOf(PropTypes.number).isRequired,
        mSemiMajorAxis: PropTypes.number.isRequired,
        mSemiMinorAxis: PropTypes.number.isRequired,
        degreeTiltFromWest: PropTypes.number.isRequired
    }

    createLeafletElement(props) {
        const { center, mSemiMajorAxis, mSemiMinorAxis, degreeTiltFromWest, ...options } = props
        return new LeafletEllipse(center, [mSemiMajorAxis, mSemiMinorAxis], degreeTiltFromWest, this.getOptions(options))
    }

    updateLeafletElement(fromProps, toProps) {
        if (toProps.center !== fromProps.center) {
            this.leafletElement.setLatLng(toProps.center);
        }
        if (toProps.degreeTiltFromWest !== fromProps.degreeTiltFromWest) {
            this.leafletElement.setTilt(toProps.degreeTiltFromWest);
        }
        if (toProps.mSemiMinorAxis !== fromProps.mSemiMinorAxis || toProps.mSemiMajorAxis !== fromProps.mSemiMajorAxis) {
            this.leafletElement.setRadius([toProps.mSemiMajorAxis, toProps.mSemiMinorAxis]);
        }
    }
} 
export default class withLeaflet(Ellipse);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在react-leaflet中制作一个椭圆形? 的相关文章

  • 在 React 中使用 leaflet.offline ?

    我正在开发一个 React 应用程序 并且正在尝试实现一个支持离线下载地图图块的 Leaflet 地图 为此我想到使用 leaflet offline https github com allartk leaflet offline 但我不
  • 刷新页面时未定义带有react-leaflet窗口的下一个js

    我在 Next js 中使用react leaflet 但是当重新加载页面时显示 窗口未定义 即使我使用 ssr false 的动态导入 我在这里看到了其他人提出的这个问题 并尝试了他们提供的答案 但没有成功 还尝试使地图安装在组件之后 但
  • React Leaflet V3 自定义控件

    有一个新的 React leaflet 版本即将推出 可以在这里找到 npm 安装react leaflet next 文档 https react leaflet v3 now sh docs start introduction 这是使
  • 使用react-leaflet时缺少Leaflet地图图块

    我正在使用简单的例子 from 传单反应准系统create react app app Problem 地图图块确实会渲染 但始终有 1 2 行地图图块未渲染 呈灰色 当地图移动时 不同的行将开始消失 但是 如果我要调整浏览器窗口的大小 地
  • 从反应传单中的地图中删除缩放控制

    我正在构建一个反应传单应用程序 并且尝试将缩放控件与地图本身分开 这里在普通传单上下文中提出了同样的问题 使用 Leaflet 将控件放置在地图容器之外 这就是我试图在反应传单框架内完成的任务 这是我的项目的总体轮廓 import UIWi
  • React-leaflet 创建自定义组件

    我想使用react leaflet 创建一个自定义组件 显示鼠标的实际位置 x y 但我不知道如何创建它 我发现react leaflet control但好像不是最新的 当然我看了api文档https react leaflet js o
  • React-Leaflet MapContainer 在状态更新时未使用新位置值进行渲染

    我是基于 Typescript 和 Hook 的 React 应用程序的新传单用户 在我的应用程序中 应用程序使用 chrome 浏览器的地理定位 API 获取了我当前的地理位置 纬度 经度 我已允许浏览器的权限 并且应使用标记在地图中显示
  • 使用react-leaflet在标记内实现动态JSX元素

    我有一个正在使用的 React 应用程序Leaflet http leafletjs com 通过反应传单 https github com PaulLeCam react leaflet 两个超级有用的库 在这个应用程序中 我有一组需要渲
  • 在反应传单地图上自动打开标记弹出

    我在反应传单地图上使用一些标记来显示各种文本 但我找不到自动打开工具提示的标志 我得到 位置 孩子 onOpen onClose 作为可用属性 render return div this shapes map shape gt retur
  • 如何使用react leaflet向地图添加图例,而不使用refs并手动修改DOM?

    我正在使用react leaflet 并想向地图添加图例 目前 我可以通过将地图的引用传递给自定义组件并呈现 null 同时让函数创建 HTML 并将其添加到地图来实现此目的 使用 Jest 和 Enzyme 进行测试对裁判来说是一场噩梦
  • CRA + React Leaflet:编译失败

    我刚刚开始一个全新的项目create react app并设置react leaflet正如他们的文档所建议的here https react leaflet js org docs start installation 我正在尝试使用这个
  • Leaflet React在功能组件中获取地图实例

    我想要在地图外有一个按钮 将视图更改为另一个坐标 有没有办法让mapContainer实例调用它们的函数 或者说如何实现这个功能呢 我尝试使用 ref 来获取它 但它不起作用 这是我当前的代码 const zoom 13 function
  • React-leaflet:添加 TopoJSON 层

    我刚刚开始使用 React leaflet 库并获得了一个要加载 geoJSON 层的地图 但是我想使用 TopoJSON 层 我知道这样的纯传单是可能的 https gist github com rclark 5779673 https
  • 如何在react-leaflet中制作一个椭圆形?

    我正在尝试在使用制作的地图上绘制一个椭圆react leaflet 它内置了对圆形和矩形的支持 为了实现这一点 我使用代码在 非反应 中生成一个椭圆leaflet from here https github com jdfergason
  • 如何飞往react-leaflet中的某个位置

    所以我对反应和传单真的很陌生 但我想做的基本上就是让用户输入一些输入 然后按回车键后 触发一个事件 然后该事件飞到从该输入生成的坐标 我正在使用地理编码 经纬度坐标已成功生成 但是我不知道如何使地图飞到那个位置 这是我到目前为止所拥有的 i
  • 有没有办法使用反应传单库使传单弹出响应?

    我一直在研究并且我知道传单 https leafletjs com 有插件https github com yafred leaflet responsive popup https github com yafred leaflet re
  • 如何在react 16.4.1中使用leaflet-polylinedecorator

    我正在尝试在react 16 4 1中使用传单插件polylinedecorator 所以没有钩子 然而 我能找到的关于如何在 React 中使用此插件的唯一示例是使用钩子 请参阅 如何将 Polylinedac orator 与 Reac
  • 未捕获的错误:地图容器已初始化

    我正在使用 React JS 制作网页 我的目标是在前端显示地图 我正在使用react leaflet npm 包来实现同样的目的 但是 我收到以下错误 Error Uncaught Error Map container is alrea
  • 使用文本字段同时过滤react-table和react-leaflet标记(在表中显示过滤数据并在地图中显示标记)

    我是反应传单的新手 需要一点帮助来解决我的问题 跟进上一篇文章 https stackoverflow com questions 52557802 how to get the number of map markers per coun
  • 用笑话测试实现react-leaflet映射的react组件的问题

    当我尝试测试实现react leaflet库的react组件时 遇到以下问题 C digital booking ui node modules react leaflet lib index js 1 Object

随机推荐

  • Java 异常 - 线程“main”中的异常 java.lang.NoClassDefFoundError: net/sourceforge/tess4 j/Tesseract

    我试图让事情与 tess4j OCR 算法 一起工作 并且我使用以下代码 import java awt image RenderedImage import java io File import java net URL import
  • 复制 .docx 并保留图像

    我正在尝试将文档的元素从一个文档文件复制到另一个文档文件 文本部分很简单 图像是棘手的地方 附加图像来解释文档的结构 只有一些文本和 1 张图像 from docx import Document import io doc Documen
  • Xcode:如何将 MP4 文件转换为音频文件

    我想将应用程序文档文件夹中的 MP4 文件转换为音频文件 mp3 或 m4a 我已经尝试过 但无法使用 AVPlayer 播放转换后的 MP3 文件 这是我的代码 void convertMP4toMP3withFile NSString
  • Android 中的 Google 地图上的标记闪烁

    我刚刚开始Android应用程序开发 按照本教程开发了Google地图应用程序并在Google地图上添加了标记 http mobiforge com developing story using google maps android ht
  • 获取用户头像大小的照片

    我正在使用 C 开发 Facebook 网站应用程序 我可以使用以下方式获取信息 FacebookClient FBApp new FacebookClient getAccessToken dynamic user FBApp Get m
  • g++编译错误

    我是 Ubuntu 的新手 我尝试编写一个简单的 Hello World Ubuntu 11 04 中的 c 代码 该代码 在终端中 gcc Wall W Werror tex cpp o tex 但编译器返回了很多错误 tmp ccL8c
  • 用于本地化的流畅 NHibernate 映射

    我正在尝试从 NHibernate 映射构建数据库 但遇到了问题 我有许多具有本地化字符串值的类 public class MyClass1 public virtual int Id get set public virtual Shor
  • 如何创建私有类方法?

    这种创建私有类方法的方法是如何工作的 class Person def self get name persons name end class lt lt self private def persons name Sam end end
  • Dart 异常:已经为元素 x 注册了(聚合物)原型

    我有两个共享相同飞镖文件的聚合物元件 在 dart 文件中 我声明了两个 PolymerElement 类 直到聚合物 0 15 0 1 都工作正常 我已将项目更新为聚合物 0 15 1 现在出现此异常 Exception Already
  • 函数参数过多

    我从我的头文件中收到此错误 too many arguments to function void printCandidateReport 我对 C 相当陌生 只需要一些正确方向的指导来解决此错误 我的头文件如下所示 ifndef CAN
  • 如何在`Axios.interceptors.request`的配置中获取Cookies的`csrftoken`?

    我怎样才能得到饼干csrftoken in Axios interceptors request的配置 Axios interceptors request use config gt if config method post confi
  • 使用 GWT 编译器将 Java 转换为 JavaScript

    我写了一些 Java 代码 想将其转换为 JavaScript 我想知道是否可以使用GWT编译器将提到的Java代码编译为JavaScript代码保留所有名字方法 变量和参数 我尝试使用 draftCompile 关闭代码优化来编译它 但方
  • 以明文显示的 IIS 应用程序池身份帐户密码

    当我使用appcmd list apppool
  • 删除时触发将行插入到另一个表中

    我正在尝试创建一个触发器 它将包含所有列的行插入到另一个表中 这是我到目前为止所得到的 但它不起作用 delimiter CREATE TRIGGER item deleted move AFTER DELETE ON item begin
  • 在php中将时间戳转换为之前的时间?

    我知道这个问题已经被问过好几次了 我发现了很多关于在 php 中将时间戳转换为之前时间的教程 博客文章 我尝试了无数的代码 但似乎没有什么对我有用 我要么得到一个没有错误的空白页面 我的 php 页面上重新发布时出错 要么在我的页面中得到一
  • 如何在 Flutter 上使用 SignalR?

    我正在尝试与使用 SignalR 建立聊天通信的 Asp Net core 2 1 应用程序进行通信 但我无法弄清楚使用 flutter 实现这一目标的最佳方法是什么 我已经搜索了一些库来做到这一点 但我发现的库与 Flutter 不兼容
  • 避免多个ajax请求

    我试图避免向工厂中的服务器发出多个 ajax 请求 我已经添加了一个小型缓存服务 但这还不足以实现我的目标 在服务器响应之前可以多次调用该工厂 从而导致向服务器生成多个请求 为了避免这种情况 我添加了第二个 Promise 对象 如果 AJ
  • 如何将两个 SSE 寄存器加在一起

    我有两个 SSE 寄存器 128 位是一个寄存器 我想将它们相加 我知道如何在其中添加相应的单词 例如我可以这样做 mm add epi16如果我在寄存器中使用 16 位字 但我想要的是类似的东西 mm add epi128 不存在 它将使
  • 重置索引后无法过滤索引列中包含特定值的行

    我正在组织多个计划的数据 其中包含计划阶段的信息 P 初步 或F 最终 我正在使用中显示的方法examples https pandas pydata org pandas docs stable generated pandas Data
  • 如何在react-leaflet中制作一个椭圆形?

    我正在尝试在使用制作的地图上绘制一个椭圆react leaflet 它内置了对圆形和矩形的支持 为了实现这一点 我使用代码在 非反应 中生成一个椭圆leaflet from here https github com jdfergason