svg 项目实践——添加可编辑的 svg 图片

最近的项目中遇到一个需求,在页面上添加一个能够自由拖拽、缩放、编辑颜色的 svg 图片,项目中引用了两个现有的插件,对插件进行解读以后略有心得,与你们分享一下。react

自由拖拽缩放的节点 —— react-rnd

说到拖拽,咱们的第一反应固然是监听鼠标事件来修改 dom 元素的位置,而缩放的话,则是在对元素边界进行操做时从新修正元素的 positionwidthheight 属性。这部分就不予过多的赘述,有兴趣的朋友能够参考下 react-rnd 这个插件,它引用了 react-draggable 和 react-resizeable 两个插件来实现元素的拖拽和缩放。微信

此时咱们理论上已经实现了 dom 元素的拖拽和缩放,可是在添加了 svg 图片以后咱们很快发现,因为外层的拖拽是由 document.addEventListener 来实现的,可是咱们在 mouseDown 的时候,鼠标点击的位置其实是 svg 内的 documentdom

avatar

那么这个时候应该怎么处理呢?最简单的思路:把 svgdocument 取出来,放到父级的 document 里面。svg

自由的 svg —— react-svg

有了把 svgdocument 取出来的思路,咱们很容易能找到一个插件:react-svg,它的实现思路与咱们上面提到的彻底一致,此处贴上它的核心代码供各位查看:spa

avatar

此时咱们发现,咱们添加的 svg 图片已经能够自由的拖拽和缩放了。另外因为 react-svg 还开放了一个属性 beforeInjection,咱们能够经过这个属性来在 svg 挂载以前修改它的属性,如 strokestroke-widthfill 等,所以咱们能够更加灵活得处理咱们的 svg 图片。插件

svg 的缩放 —— preserveAspectRatio、vector-effect

咱们很快又发现一个问题,svg 的缩放默认是等比的,也就是说当咱们横向拉长图片的时候,它并不会变大,只会横向偏移居中。code

avatar

这个时候咱们就要用到 svg 自带的一个属性:preserveAspectRatio,用来表示是否强制进行统一缩放,当设置为 none 的时候,svg 图片不会进行强制统一缩放,若是须要,会缩放指定元素的图形内容,使元素的边界彻底匹配视图矩形。以下图。其余类型强制缩放可参考 MDN。orm

avatar

如今咱们的 svg 终于能够自由缩放了,可是很快咱们又发现,把一个 svg 放大以后,它的线条宽度也跟着变宽了,那么有没有什么属性来保持线条宽度不变呢?答案是有的,vector-effect,可是这个属性只对部分 svg 元素( <circle>, <ellipse>, <foreignObject>, <image>, <line>, <path>, <polygon>, <polyline>, <rect>, <text>, <textPath> <tspan>, <use>)生效,而它的属性有如下几个:事件

none 该值指定不该用矢量效果,即,使用默认的渲染行为,即首先用指定的绘画填充形状的几何形状,而后使用指定的绘画描边轮廓。图片

non-scaling-stroke 该值修改了笔触的方式。一般,笔触涉及在当前用户坐标系中计算形状路径的笔触轮廓,并用笔触颜料(颜色或渐变)填充轮廓。该值的最终视觉效果是笔触宽度不依赖于元素的变换(包括非均匀缩放和剪切变换)和缩放级别。

non-scaling-size 该值指定元素及其后代使用的特殊用户坐标系。尽管从宿主坐标空间进行任何转换更改,该用户坐标系的比例也不会更改。可是,它没有指定抑制旋转和偏斜。一样,它也不指定用户坐标系的原点。因为此值抑制了用户坐标系的缩放,所以它还具备 non-scaling-stroke 的特性。

non-rotation 该值指定元素及其后代使用的特殊用户坐标系。尽管从宿主坐标空间发生任何变换更改,该用户坐标系的旋转和倾斜仍被抑制。可是,它没有指定抑制缩放。一样,它也没有指定用户坐标系的原点。

fixed-position 该值指定元素及其后代使用的特殊用户坐标系。尽管从宿主坐标空间进行任何转换更改,用户坐标系的位置都是固定的。可是,它没有指定抑制旋转,偏斜和缩放。当同时指定了该矢量效果和 transform 属性, transform 属性将因该矢量效果而被消耗。

当咱们设置vector-effect="non-scaling-stroke"后,咱们的svg终于看起来正常了~

avatar

尾声

以上就是咱们在作给页面上添加一个能够自由拖拽、缩放、编辑颜色的 svg 图片时总结的一些东西,但愿对各位有所帮助。另外咱们还有一个没有解决的问题,若是path的内容是经过相似同心圆的方式来绘制图形的时候,咱们并无什么好的方法来保证缩放时候线条宽度的变化,若是有人有什么好的意见或者方法,能够联系我交流指导,能够知音楼搜曹文亮或者添加本人微信caowl_1013,谢谢。

相关文章
相关标签/搜索