尽管伪造了getBoundingClientRect(),你如何将事件坐标转换为SVG坐标?

 DomincLiu 发布于 2023-02-06 11:05

我正在尝试根据鼠标的位置动态绘制SVG元素上的东西.不幸的是,我很难将鼠标坐标从mousemove事件转换为SVG元素的坐标空间.

这是我一直在测试的错误功能:

CylinderDemo.prototype.handleMouseMove = function(evt)
{
    debugEvent = evt;

    var bcr = evt.target.getBoundingClientRect();
    var x2 = evt.clientX - bcr.left;
    var y2 = evt.clientY - bcr.top;

    console.log(evt.target);
    //console.log(evt.clientY+" - "+evt.target.getBBox());

    var d = this.pathForCylinder(this.x0, this.y0, x2, y2, 30);
    this.cap.setAttributeNS(null, "d", d);
}

canvas.onmousemove = function(evt) {
self.handleMouseMove(evt);
}

问题是(至少在Firefox中)getBoundingClientRect()没有给我SVG对象的界限.它为我提供了SVG对象内可绘制对象的边界.当你将鼠标悬停在萤火虫的日志线上并突出显示可绘制元素的微小的子矩形时,它变得非常明显.这意味着我对坐标的转换会产生有缺陷的结果.

我应该使用什么技术将事件坐标系转换为SVG容器的坐标系?

我只是拼凑了http://jsfiddle.net/7kvkq/来说明问题.

1 个回答
  • 不要用getBoundingClientRect().相反,使用以下方法将点从屏幕空间转换为全局SVG空间getScreenCTM():

    var pt = demo.createSVGPoint(); // demo is an SVGElement
    demo.addEventListener('mousemove',function(evt) {
      pt.x = evt.clientX;
      pt.y = evt.clientY;
      var svgGlobal = pt.matrixTransform(demo.getScreenCTM().inverse());
      // svgGlobal.x and svgGlobal.y are now in SVG coordinates
    },false);
    

    修正了演示:http://jsfiddle.net/7kvkq/3/

    如果需要从屏幕空间转换为元素的局部变换,请使用getTransformToElement()以进一步转换点:

    var elTransform = demo.getTransformToElement(someElement);
    var elLocal     = svgGlobal.matrixTransform(elTransform );
    

    演示getTransformToElement():http://jsfiddle.net/7kvkq/4/

    为了获得更好的性能,不是将点转换两次并创建中间点,而是将矩阵组合成一个并使用它来转换坐标:

    var demo = document.querySelector('svg'),
        pt   = demo.createSVGPoint(),
        g    = demo.querySelector('#myGroup');
    
    // Assumes that the group does not move with respect to the SVG;
    // if so, re-calculate this as appropriate.
    var groupXForm = demo.getTransformToElement(g);
    demo.addEventListener('mousemove',function(evt) {
        pt.x = evt.clientX;
        pt.y = evt.clientY;
        var xform = groupXForm.multiply(demo.getScreenCTM().inverse());
        var localPoint = pt.matrixTransform(xform);
        // localPoint.x/localPoint.y are the equivalent of your mouse position
    },false);
    

    您可以在我的网站上看到使用这些技术的演示:http:
    //phrogz.net/svg/drag_under_transformation.xhtml

    2023-02-06 11:08 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有