【bug记录10】同一iOS webview页面中相同的两个svg图标出现部分显示或全部不显示的情况

一、问题背景

在vue项目中,同一页面中++直接复制粘贴了两个相同的svg代码嵌入到html中++,

在chrome浏览器中显示良好;

但是在Safari浏览器 或者 iOS WKwebview中,出现++只显示一个svg或者两个都不显示的情况,但是绑定在svg的点击事件仍然可以触发++。

svg的代码如下

html 复制代码
 <svg width="18" height="18" viewBox="0 0 24 24" fill="#212121" xmlns="http://www.w3.org/2000/svg">
          <g clip-path="url(#clip0_3468_29991)">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M6.5 8.69995H4.55C3.55589 8.69995 2.75 9.50584 2.75 10.5V19.4C2.75 20.3941 3.55589 21.2 4.55 21.2H19.45C20.4441 21.2 21.25 20.3941 21.25 19.4V10.5C21.25 9.50584 20.4441 8.69995 19.45 8.69995H17.5V10.5H19.45V19.4H4.55L4.55 10.5H6.5V8.69995Z" />
          <path fill-rule="evenodd" clip-rule="evenodd" d="M11.3634 2.11358C11.7149 1.76211 12.2848 1.76211 12.6362 2.11358L16.9191 6.39642C17.1143 6.59168 17.1143 6.90827 16.9191 7.10353L16.3534 7.66921C16.1581 7.86448 15.8416 7.86448 15.6463 7.66921L11.9998 4.02277L8.3534 7.66921C8.15813 7.86448 7.84155 7.86448 7.64629 7.66921L7.0806 7.10353C6.88534 6.90827 6.88534 6.59168 7.0806 6.39642L11.3634 2.11358Z" />
          <path fill-rule="evenodd" clip-rule="evenodd" d="M12.4001 2.69995C12.6762 2.69995 12.9001 2.92381 12.9001 3.19995V16C12.9001 16.2761 12.6762 16.5 12.4001 16.5H11.6001C11.324 16.5 11.1001 16.2761 11.1001 16V3.19995C11.1001 2.92381 11.324 2.69995 11.6001 2.69995H12.4001Z" />
        </g>
        <defs>
          <clipPath id="clip0_3468_29991">
            <rect width="24" height="24" />
          </clipPath>
        </defs>
 </svg>

二、问题分析

当时由于不清楚原因,svg元素不显示但是可以点击,证明是svg绘制渲染这一步出了问题,即矢量图形没有被正确解析

🌟于是做了两组对照实验:

  • 将两个相同的svg代码,删除其中一份,看是否可以显示【++结果:单一svg在页面中可以显示】++
  • 将两个的svg代码均替换成页面中另一个可以显示的svg,看是否可以显示【++结果:全部替换成如下svg的时候,是可以两个同时正常显示的++】
html 复制代码
 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M14.9999 4L6.99994 12L14.9999 20" stroke="#212121" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>

👍根据上述实验分析:

对比新替换的svg代码和原svg代码,可以看出新svg代码最大的不同是没有应用clip-path进行区域裁剪而仅仅是用了path元素绘制。

而原svg单个可以显示、两个则不能显示,猜测可能是++clip-path的id在iOS系统中解析需要局部唯一,否则会造成冲突++。经验证和查询资料,确实如此。

拓展总结

诸如<clipPath>**此类的++图形效果++标签++在用url进行引用时,都需要设置唯一id++**,否则会因为冲突而无法解析效果、从而无法正确渲染矢量图形。

例如:

  • <filter>:滤镜效果
  • <mask>:遮罩效果
  • <linearGradient>和<radialGradient>:渐变和镭射效果
  • <pattern>:使用预定义的图形对一个对象进行填充或描边( 通过fill / stroke属性url引用pattern中预定义的图案)
  • <marker>:定义在<path><line><polyline><polygon> 这些线性/多边形元素上绘制箭头或者多边标记 所使用的图形。(通过 marker-startmarker-midmarker-end 属性将marker中定义的标记附着上来)

三、解决方法

🌰主要有两种思路:

1、避免id冲突

2、避免svg重复嵌入

👍 那么基于上述两种思路,主要有两个解决方法:

1、手动解决id冲突,在页面内保证id唯一【就是自己手动改下id值啦】

2、通过**<use>标签链接svg图形实例,配合<symbol>**定义图形模版对象,避免代码重复。

注意,一个symbol元素本身是不呈现的,通过use引用才显示。

🌰举例

html 复制代码
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
    <symbol id="icon-with-clip" viewBox="0 0 100 100">
        <defs>
            <clipPath id="uniqueClipPath">
                <circle cx="50" cy="50" r="50" />
            </clipPath>
        </defs>
        <rect width="100" height="100" clip-path="url(#uniqueClipPath)" />
    </symbol>
</svg>

<!-- 引入位置1:注意use是放在svg标签中的哦 -->
<svg>
    <use href="#icon-with-clip" />
</svg>


<!-- 引入位置2 -->
<svg>
    <use href="#icon-with-clip" />
</svg>

3、svg不直接嵌入代码,通过**<img>引入**,但是无法直接修改 SVG 图像中的颜色

相关推荐
用户54277848515404 分钟前
Vue 3 中开发高阶组件(HOC)与 Renderless 组件
前端
HIT_Weston17 分钟前
67、【Ubuntu】【Hugo】搭建私人博客(一)
前端·ubuntu·hugo
阿里巴啦30 分钟前
用React+Three.js 做 3D Web版搭建三维交互场景:模型的可视化摆放与轻量交互
前端·react·three.js·模型可视化·web三维·web三维交互场景
Liu.77440 分钟前
vue3组件之间传输数据
前端·javascript·vue.js
|晴 天|40 分钟前
前端闭包:从概念到实战,解锁JavaScript高级技能
开发语言·前端·javascript
开发者小天42 分钟前
react的拖拽组件库dnd-kit
前端·react.js·前端框架
用户4445543654261 小时前
在Android开发中阅读源码的指导思路
前端
用户54277848515401 小时前
ESM 模块(ECMAScript Module)详解
前端
全栈前端老曹1 小时前
【ReactNative】核心组件与 JSX 语法
前端·javascript·react native·react.js·跨平台·jsx·移动端开发
用户54277848515401 小时前
JavaScript 闭包详解:由浅入深掌握作用域与内存管理的艺术
前端