我用 fabritor 做了一个截图美化应用

偶尔间看到一款国外的应用:Screely,是一款截图美化工具。通常用截图工具截的图标注一下就发出去了,截图有大有小,发到文章或者社交网络并不整齐也不美观(可以参见我之前发我的文章😂,妥妥反面案例)。Screely 就是解决这个问题的,他可以给截图加上背景、圆角、Mac窗口,也可以加上标注和贴纸。这样分享截屏既美观也不会突兀。

如果你经常上推的话就会发现,大多数博主发的图片都带有背景、圆角。整体美观度会提升不少。

然后我就在想,我能不能也做一个类似的工具😎。这时候我想到了 fabritor,是时候让她继续发挥余热了。

fabritor 作为一个图片编辑器,已经比较完善了,做一个截图美化工具应该问题不大,随便折腾一下,有那味了。

是的,我做了 Photor

fork 一下 fabritor 的代码,停停写写,也差不多有一个月的时间,完成了名为 Photor 的截图美化工具,等不及的可以先去官网试用一下:www.photor.fun/

基本包含了截图美化工具的所有功能,包括上传、背景、边距、圆角、窗口、水印、定制截图尺寸、各类标注、裁剪等等。

简单推广过一波,目前 UV 稳定在 100 左右,说明还是有用户的。😂

简单技术分析

总体还是基于 fabritor 实现,像画布尺寸、背景渐变、圆角、裁剪、各类标注图形的基础方法,代码都是直接来自于 fabritor,下面会挑几个不一样的点说一下。

定制尺寸

很多网站上传图片会有建议尺寸甚至强制尺寸,这时候临时去截取和缩放都会比较麻烦,索性加一个定制尺寸的功能。定制尺寸其实直接修改的就是画布的尺寸,画布固定后,缩放图片即可。但图片上有时候还会附带 Mac 窗口,有时候缩放会比较奇怪,还需要优化。

标注绘制

fabritor 内,矩形等形状都是直接添加到画布然后编辑的,而对于截图标注的话,还是鼠标拖动绘制的好。之前掘金文章下面也有同学问过,fabricjs 提供了丰富的鼠标事件,事件内附带鼠标位置,要实现也不是很难。

这里以矩形为例:

typescript 复制代码
// mouse down 事件,在鼠标按下位置创建矩形。
drawShapeRef.current = {
  isDraw: true,
  lastPoint: opt.absolutePointer,
  tmp: createRect({
    left: opt.absolutePointer.x, 
    top: opt.absolutePointer.y, 
    width: 1, height: 1, rx: 10, ry: 10, 
    fill: 'rgba(0,0,0,0)', 
    stroke: '#D31638', 
    strokeWidth: 6 
  }),
  type: 'rect'
}

// mouse move 事件,修改矩形属性
tmp.set({
  left: Math.min(opt.absolutePointer.x, lastPoint.x),
  top: Math.min(opt.absolutePointer.y, lastPoint.y),
  width: Math.abs(opt.absolutePointer.x - lastPoint.x),
  height: Math.abs(opt.absolutePointer.y - lastPoint.y)
});

// mouse up 完成绘制
canvas.setActiveObject(tmp);

Mac 窗口

如果分享的是代码图片的话,带一个 Mac 窗口可以加分很多。我现在采用的方案是使用 圆形和矩形的组合(Group)。fabricjs 里使用组合的话可以比较方便的做一些复杂的图形。之前 issue 里有同学问过如何实现一个复杂的图形,我也是建议这样做。

typescript 复制代码
fabric.FMacWindow = fabric.util.createClass(fabric.Group, {
  type: 'f-mac-window',

  initialize (options) {
    this.callSuper('initialize', [
      this.background,
      this.closeCircle,
      this.minCircle,
      this.maxCircle
    ], rest, false);
  }
})

不过组合起来简单,但有个问题是 Mac 窗口覆盖到图片上,只能有两个圆角,而 fabricjs 默认是四个圆角的,也没有给出配置实现,只能自定义实现了。

所以需要自定义一下 rect 的 _render 。

同样覆盖在图片上时,图片上方的两个圆角也要去掉。

定制线条 control

fabricjs 内,默认的线条 control 也像矩形一样,并不像常见的线条 control,通常线条只需要两个端点修改长度和位置就好。

fabricjs 使用 new fabric.Control 定制。

typescript 复制代码
const linePositionHandler = (x, y) => {
  return (dim, finalMatrix, fabricObject) => {
    const points = fabricObject.calcLinePoints();
    const localPoint = new fabric.Point(points[x], points[y]);
    
    // move 不会改变 x1 y1 x2 y2
    // fabricObject.toLocalPoint(new fabric.Point(points[x], points[y]), 'center', 'center');
    const point = fabric.util.transformPoint(localPoint, fabric.util.multiplyTransformMatrices(
      fabricObject.canvas.viewportTransform,
      fabricObject.calcTransformMatrix()
    ));
    return point;
  }
}

const changeLineEnd = (eventData, transform, x, y) => {
  const { target } = transform;
  target.set({ x2: x, y2: y  });
  return true;
}

const changeLineStart = (eventData, transform, x, y) => {
  const { target } = transform;
  target.set({ x1: x, y1: y  });
  return true;
}

const objectControls = fabric.Object.prototype.controls;

if (fabric.Line) {
  const lineControls: any = fabric.Line.prototype.controls = {};
  lineControls.copy = objectControls.copy;
  lineControls.del = objectControls.del;

  lineControls.l1 = new fabric.Control({
    positionHandler: linePositionHandler('x1', 'y1'),
    actionHandler: changeLineStart,
    cursorStyleHandler: () => 'crosshair',
    actionName: 'line-change',
    render: objectControls.br.render
  });

  lineControls.l2 = new fabric.Control({
    positionHandler: linePositionHandler('x2', 'y2'),
    actionHandler: changeLineEnd,
    cursorStyleHandler: () => 'crosshair',
    actionName: 'line-change',
    render: objectControls.br.render
  });
}

图片文字模糊

使用 fabritor 的同学不知道有没有发现,如果图片上有文字,就能感觉出添加到画布的图片是糊的。

我这里找到一个 issue:github.com/fabricjs/fa... 里面讨论了图片和 clipPath 一起使用时,为了性能和缓存,是要牺牲图片清晰度的。

禁用缓存是可以解决这个问题,但会牺牲一定性能。

typescript 复制代码
fabric.Object.prototype.needsItsOwnCache = () => false

浏览器插件

此外,为了更方便的使用截图,我还开了浏览器插件,已经上架到 Chrome 和 Edge 插件商店。即可以截取这个页面,也可以选定部分区域,截图后直接进入 Photor 内编辑。

可以通过官方底部的链接下载使用。

写在后面

开发 Photor 这个应用,一方面是为了拿 fabritor 做点事情,另一方面也是尝试一下独立开发一个完整的产品。如果你也喜欢这种截图方式,不妨日常使用一下。(本文截图都是使用 Photor 制作

相关推荐
一丝晨光26 分钟前
数值溢出保护?数值溢出应该是多少?Swift如何让整数计算溢出不抛出异常?类型最大值和最小值?
java·javascript·c++·rust·go·c·swift
小堃学编程37 分钟前
前端学习(3)—— CSS实现热搜榜
前端·学习
Wannaer1 小时前
从 Vue3 回望 Vue2:响应式的内核革命
前端·javascript·vue.js
不灭锦鲤1 小时前
xss-labs靶场基础8-10关(记录学习)
前端·学习·xss
Bl_a_ck1 小时前
--openssl-legacy-provider is not allowed in NODE_OPTIONS 报错的处理方式
开发语言·前端·web安全·网络安全·前端框架·ssl
懒羊羊我小弟1 小时前
手写符合Promise/A+规范的Promise类
前端·javascript
互联网搬砖老肖1 小时前
Web 架构之负载均衡会话保持
前端·架构·负载均衡
赵大仁1 小时前
React vs Vue:点击外部事件处理的对比与实现
javascript·vue.js·react.js
肥肥呀呀呀2 小时前
在Flutter上如何实现按钮的拖拽效果
前端·javascript·flutter
Zero1017133 小时前
【React的useMemo钩子详解】
前端·react.js·前端框架