当前位置: 首页 > 知识库问答 >
问题:

svg - 我好像发现了个chrome bug ?

长孙瑞
2025-10-26

我好像发现了个chrome bug

https://code.juejin.cn/pen/7564339560436465699

当svg缩放很大时,对于circle元素,浏览器的事件触发就会有问题,demo 中的hover是完全不生效的,即使用js添加事件侦听也是一样的。

但是缩小svg画布后,就正常了,例如在demo中将viewbox属性改为-90 -43 176 194后,hover能够正确触发。

所以是浏览器的问题,还是我的问题?

感觉是vector-effect导致的。

我试了下Safari,是完全正常的。

共有1个答案

隗轶
2025-10-26

根据你的描述和Demo分析,问题主要源于 SVG 的高缩放比例导致的事件命中测试(Hit Testing)精度问题,并非 Chrome 的 bug,而是 SVG 坐标转换机制的特性。以下是关键点:


�� 问题原因

  1. 超大 viewBox 导致元素尺寸极小
    你设置的 viewBox (-1700 -800 3400 1600) 范围非常大,但 SVG 容器尺寸较小(约 480x400px)。这导致:

    • 计算精度问题:Circle 的实际屏幕尺寸 ≈ (7.5 半径 × 2) × (480px / 3400 viewBox宽度) = 约 2.1px
    • 浏览器在计算鼠标坐标对应的 SVG 坐标时,因浮点精度限制无法精准命中微小元素。
  2. vector-effect 不是主因
    vector-effect: non-scaling-stroke 只影响描边渲染(阻止描边随缩放变粗),与事件触发无关。

✅ 解决方案

  1. 调整 viewBox 到合理范围(推荐)
    如 Demo 中缩小 viewBox 后正常(-90 -43 176 194),这本质是让 用户坐标屏幕像素 比例接近 1:1:

    <svg viewBox="-90 -43 176 194">...</svg>
  2. 通过 CSS 强制扩大命中区域
    给 Circle 添加透明描边扩大交互范围:

    circle {
      stroke: transparent;
      stroke-width: 10; /* 按需调整,增加命中面积 */
    }
  3. 业务层修复
    如果必须保持大 viewBox:

    // 在 SVG 上代理事件,手动计算命中
    svg.addEventListener('mousemove', e => {
      const pt = svg.createSVGPoint();
      pt.x = e.clientX, pt.y = e.clientY;
      const { x, y } = pt.matrixTransform(svg.getScreenCTM().inverse());
      
      // 手动检查坐标是否在 Circle 内
      const circle = document.querySelector('circle');
      const dx = x - circle.cx.baseVal.value;
      const dy = y - circle.cy.baseVal.value;
      const hit = (dx*dx + dy*dy <= circle.r.baseVal.value**2);
      
      if (hit) circle.classList.add('hover');
    });

�� 根本机制

  • 事件命中测试依赖 SVG 坐标 → 屏幕坐标的转换矩阵。
  • 当转换矩阵的缩放比例极大时(如 Demo 中约 0.0004倍),毫秒级的坐标误差也会导致事件丢失
  • 所有浏览器(Chrome/Firefox/Safari)都存在此限制,本质是计算机浮点数精度问题。

建议优先采用调整 viewBox 的方案,这是最符合 SVG 设计理念的做法。

 类似资料:
  • 我用的thinkcmf这个框架,突然所有的接口返回前面都自动加了一个“<!-23-230-jsc-->”,我也没找到这个东西是在哪里生成的,有遇到过的吗?

  • 概述 SVG 是一种基于 XML 语法的图像格式,全称是可缩放矢量图(Scalable Vector Graphics)。其他图像格式都是基于像素处理的,SVG 则是属于对图像的形状描述,所以它本质上是文本文件,体积较小,且不管放大多少倍都不会失真。 SVG 文件可以直接插入网页,成为 DOM 的一部分,然后用 JavaScript 和 CSS 进行操作。 <!DOCTYPE html> <htm

  • SVG是“可缩放矢量图”(Scalable Vector Graphics)的缩写,是一种描述向量图形的XML格式的标记化语言。也就是说,SVG本质上是文本文件,格式采用XML,可以在浏览器中显示出矢量图像。由于结构是XML格式,使得它可以插入HTML文档,成为DOM的一部分,然后用JavaScript和CSS进行操作。 相比传统的图像文件格式(比如JPG和PNG),SVG图像的优势就是文件体积小

  • SVG是“可缩放矢量图”(Scalable Vector Graphics)的缩写,是一种描述向量图形的XML格式的标记化语言。也就是说,SVG本质上是文本文件,格式采用XML,可以在浏览器中显示出矢量图像。由于结构是XML格式,使得它可以插入HTML文档,成为DOM的一部分,然后用JavaScript和CSS进行操作。 相比传统的图像文件格式(比如JPG和PNG),SVG图像的优势就是文件体积小

  • 面试时间很短,20分钟左右,没有问我项目相关,都是问八股和简历上的技术栈。 问题: 1,接口和抽象类有私有方法吗? 2,hashmap和hashtable的key和value可以为空吗? 3,nginx算前端中间件还是后端。(早知道简介上不写了)。 4,nginx能部署哪些前端资源。 5,反射机制,反射可以获取私有方法和私有属性吗? 6,线程创建方法,线程池创建方法。 7,mapper文件通过什么

  • 我刚刚浏览了一些关于如何在另一个像素阵列之上绘制像素阵列的代码,如下所示: } 如您所见,一个人能够在另一个位图之上的特定坐标上绘制一个位图对象。 我不明白的是两个for循环。我知道,外部for循环是绘制位图的y轴,并启动内部for循环来绘制位图的x轴。 现在我过来了: sp和dp到底代表什么?'c'在后面是什么意思 ? 提前感谢,致以最诚挚的问候

  • 问题内容: 我才刚开始使用本机。在安装此软件包时 https://github.com/NewOldMax/react-native-validator- form/issues/3 系统提示我,并向我显示了4个漏洞(上面列出) 运行2个帮助程序命令后,系统又提示我另外2个漏洞(请参阅链接) 我该如何解决其余问题? 更新相应的npm软件包无效。 不知道如何进行。希望可以有人帮帮我。谢谢。 问题答案

  • 问题内容: 我正在用Java进行游戏,只是将所有与窗口相关的代码从基于java.awt重写为javax.swing。不久之后,我意识到事情变得有些复杂了,因此我做了一些研究,发现了如何绘制事物,如何设置JFrame的大小等。但是由于某种原因,我的JFrame的大小总是比我指定的尺寸超出10像素。在这种情况下,我希望它是640 x 640像素。 这是我的代码: 当我运行它时,即使我调用setPref