好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Fabric.js 简介。第 4 部分

Fabric.js 简介。 第 4 部分。

在上一个系列中,我们已经讨论了很多主题; 从基本的对象操作到动画、事件、过滤器、组和子类。 但是仍然有一些非常有趣和有用的事情要讨论!

免费绘图

如果说有什么 <canvas> 真正的亮点,那就是它对免费绘图的出色支持! 由于画布只是一个 2D 位图——一张用于绘画的纸——执行自由绘图是非常自然的。 当然,Fabric 会为我们解决这个问题。

isDrawingMode 只需将Fabric 画布的属性 设置为 ,即可启用自由绘图模式 true 。 这立即使画布上的任何进一步点击和移动都被解释为铅笔/画笔。

您可以根据需要在画布上多次绘制,而 isDrawingMode is  true 。 但是,只要您执行任何移动,然后是“mouseup”事件,Fabric 就会触发“path:created”事件并将刚刚绘制的形状转换为真实 fabric.Path 实例!

如果在任何时候,您设置 isDrawingMode 回 false ,您最终会得到所有创建的路径对象仍然存在于画布上。 而且由于它们是很好的旧 fabric.Path 对象,您可以随意修改它们——移动、旋转、缩放等。

还有 2 个属性可用于自定义免费绘图 - freeDrawingBrush.color 和 freeDrawingBrush.width .  两者都可以通过 freeDrawingBrush 实例在 Fabric 画布实例上使用。 freeDrawingBrush.color 可以是任何常规颜色值,代表画笔的颜色。 freeDrawingBrush.width 是以像素为单位的数字,表示画笔厚度。

在不久的将来,我们计划为免费绘图添加更多选项 - 各种版本的画笔(例如喷雾状或粉笔状)。 还有自定义画笔图案,以及使用您自己的扩展选项,类似于 Fabric 图像过滤器。

擦除 是另一个很酷的可用功能,可以很好地与免费绘图配合使用。

定制

Fabric 令人惊奇的事情之一是它的可定制性。 您可以在画布或画布对象上调整数十种不同的参数,以使事物完全按照您想要的方式运行。 让我们来看看其中的一些。

锁定对象

画布上的每个对象都可以通过几种方式锁定。 “lockMovementX”、“lockMovementY”、“lockRotation”、“lockScalingX”、“lockScalingY”是锁定相应对象动作的属性。 因此设置 object.lockMovementX 以 true 防止对象水平移动。 你仍然可以在垂直平面上移动它。 同样, lockRotation 防止旋转和 lockScalingX /  lockScalingY - 缩放。 所有这些都是累积的。 您可以以任何方式将它们组合在一起。

改变边界,角落

您可以通过“hasControls”和“hasBorders”属性控制对象的边框和角的可见性。 只需将它们设置为 false ,对象就会立即呈现“裸体”。

object.hasBorders = false;

object.hasControls = false;

您还可以通过调整一些自定义属性“cornerDashArray”、“borderDashArray”、“borderColor”、“transparentCorners”、“cornerColor”、“cornerStrokeColor”、“cornerStyle”、“selectionBackgroundColor”、“padding”和“cornerSize”来更改它们的外观“ 特性。

object.set({ 
  borderColor:'red', 
  cornerColor:'green', 
  cornerSize:6 });

  object.set({ 
    transparentCorners: false, 
    cornerColor:'blue', 
    cornerStrokeColor:'red', 
    borderColor:'red', 
    cornerSize:12, 
    padding:10, 
    cornerStyle:'circle', 
    borderDashArray:[3, 3] 
  }) ;

禁用选择

您可以通过将画布的“ selection ”属性设置为 来禁用画布上的object选择 false 。 这可以防止对画布上显示的所有内容进行选择。 如果您只需要使某些object不可选择,您可以更改对象的“ selectable ”属性。 只需将其设置为 false ,对象就会失去交互性。

自定义选择

现在,如果您不想禁用选择,而是想更改其外观怎么办? 没问题。

画布上有 4 个属性可以控制其呈现方式——“selectionColor”、“selectionBorderColor”、“selectionLineWidth”和“selectionDashArray”。 这些应该是不言自明的,所以让我们看一个例子:

canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 }));

canvas.selectionColor = 'rgba(0,255,0,0.3)';
canvas.selectionBorderColor = 'red';
canvas.selectionLineWidth = 5;

最后一个属性——“selectionDashArray”——并不那么简单。 它允许我们做的是使选择线变成虚线。 定义破折号模式的方法是通过数组指定间隔。 因此,要创建一个长破折号后跟一个短破折号的模式,我们可以使用 [10, 5] “selectionDashArray”之类的东西。 这将绘制一条 10px 长的线,然后跳过 5px,再次绘制 10px 的线,依此类推。 如果我们使用 [2, 4, 6] 数组,图案将通过绘制 2px 线,然后跳过 4px,然后绘制 6px 线,然后跳过 2px,然后绘制 4px 线,然后跳过 6px,等等来创建。 你明白了。 例如,这是 [5, 10] 模式的外观:

虚线描边

与画布上的“selectionDashArray”类似,所有 Fabric 对象都具有“strokeDashArray”属性,负责在对象上执行的任何笔划的虚线图案。

var rect = new fabric.Rect({
  fill: '#06538e',
  width: 125,
  height: 125,
  stroke: 'red',
  strokeDashArray: [5, 5]
});
canvas.add(rect);

可点击区域

如您所知,所有 Fabric 对象都有边界框,用于在存在控件/角时拖动对象或旋转和缩放对象。 您可能已经注意到,即使单击对象边界框内没有绘制任何内容的空间,也可以拖动对象。

看看这张图片:

默认情况下,画布上的所有 Fabric 对象都可以被边界框拖动。 但是,如果您想要不同的行为——仅通过对象的实际内容单击/拖动对象,您可以在对象上使用“perPixelTargetFind”属性。 只需将其设置为 true 即可获得所需的行为。

旋转点

由于 1.0 版 Fabric 默认使用替代 UI — 对象不能再同时缩放和旋转。 相反,每个对象都有一个单独的旋转控件。 该控件的相应属性是“hasRotatingPoint”。 您可以通过“rotatingPointOffset”数字属性自定义其相对于对象的偏移量。

对象变换

自 1.0 版以来 ,Fabric 中还有许多其他与转换相关的属性 。 其中之一是画布实例上的“uniScaleTransform”。 false 默认情况下,可用于启用对象的非均匀缩放 ; 换句话说,它允许在拖动角落时改变对象的比例。

然后是“centeredScaling”和“centeredRotation”属性(在 v1.3.4 之前是一个属性 - “centerTransform”)。 它们指定是否应将对象的中心用作变换的原点。 当它们都设置为 true 时,当对象总是从中心缩放/旋转时,它会复制 1.0 之前的行为。 由于 1.0 的变换原点是动态的,因此可以在缩放对象时进行更精细的控制。

最后一对新属性是“originX”和“originY”。 默认情况下相应地设置为“left”和“top”,它们允许以编程方式更改对象的转换原点。 当您拖动对象的角时,正是这些属性在引擎盖下动态变化。

那么我们什么时候可以手动更改它们呢? 例如,在处理文本对象时。 当您动态更改文本并且文本框尺寸增加时,“originX”和“originY”指示框的增长位置。 因此,如果您需要将文本对象居中,您可以将 originX 设置为“center”。 要将其固定在右侧,您可以将 originX 设置为“正确”。 等等。 这种行为类似于 CSS 中的“位置:绝对”。

画布背景和覆盖

您可能还记得第一部分,您可以指定一种颜色来填充整个画布背景。 只需将任何常规颜色值设置为画布的“背景颜色”属性。

canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 }));
canvas.backgroundColor = 'rgba(0,0,255,0.3)';
canvas.renderAll();

您可以更进一步,将图像指定为背景。 您需要为此使用 setBackgroundImage 方法,传递 url 和一个可选的完成回调。

canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 }));
canvas.setBackgroundImage('assets/pug.jpg', canvas.renderAll.bind(canvas));

需要注意的是,虽然该属性称为“背景图像”,但它可以托管任何结构对象类型。 您可以设置一个 `fabric.Rect` 来表示一个画板,也可以设置一组对象。 下面的`overlayImage`或可以承载任何填充物的`backgroundColor`也是如此,例如渐变或图案。

最后,您还可以设置叠加图像,在这种情况下,它将始终出现在画布上渲染的任何对象的顶部。 只需使用 setOverlayImage ,传递 url 和可选的完成回调。

canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 }));
canvas.setOverlayImage('assets/jail_cell_bars.png', canvas.renderAll.bind(canvas));

Node.js 上的 Fabric

Fabric 的独特之处之一是它不仅可以在客户端、浏览器中工作,还可以在服务器上工作! 当您想从客户端发送数据并在服务器上创建该数据的图像时,这可能很有用。 或者,如果您只是想从控制台使用 Fabric API——出于速度、方便或其他原因。

下面我们来看看如何搭建Node环境并启动Fabric。

首先,您需要安装 Node.js (如果您还没有的话)。 根据平台的不同,安装 Node 的方法很少。 您可以按照 这些说明 或 这些 .

安装 Node 后,我们需要安装 node-canvas 库。 node-canvas 是 NodeJS 的 Canvas 实现。 它依赖于 Cairo  — 可以在 Mac、Linux 或 Windows 上运行的 2D 图形库。 node-canvas 有专门的 安装说明 ,具体取决于您选择的平台。

由于 Fabric 在 Node 之上运行,它以 NPM 包的形式出现。 所以下一步就是安装 NPM。 您可以在其github repo 中找到安装说明 。

最后一步是使用 NPM 安装 Fabric 包 。 这只需运行 npm install fabric (或 npm install -g fabric 全局安装包)即可完成。

如果我们现在运行节点控制台,我们应该可以同时使用节点画布和 Fabric:

> node
...
> typeof require('canvas'); // "function"
> typeof require('fabric'); // "object"

现在一切准备就绪,我们可以尝试一个简单的“hello world”测试。 让我们创建一个 helloworld.js 文件:

var fs = require('fs'),
    fabric = require('fabric').fabric,
    out = fs.createWriteStream(__dirname + '/helloworld.png');

var canvas = new fabric.StaticCanvas(null, { width: 200, height: 200 });
var text = new fabric.Text('Hello world', {
  left: 100,
  top: 100,
  fill: '#f55',
  angle: 15
});
canvas.add(text);
canvas.renderAll();

var stream = canvas.createPNGStream();
stream.on('data', function(chunk) {
  out.write(chunk);
});

然后将其作为 node helloworld.js .  打开 helloworld.png 显示:

那么这里发生了什么? 让我们回顾一下这段代码的重要部分。

首先,我们包括 Fabric 本身 (  fabric = require('fabric').fabric )。 然后,我们创建好的旧织物画布。

然后是看起来很熟悉的对象创建 (  new fabric.Text() ) 和画布添加 (  canvas.add(text) )。

所有这些都只是创建了 Fabric 画布并将文本对象渲染到上面。 现在,如何创建在画布上渲染的任何图像? 使用 createPNGStream 画布实例上可用的方法。 createPNGStream 返回 Node 的 流对象 ,然后可以使用 输出到图像文件中 on('data') ,并写入图像文件对应的流中( fs.createWriteStream() )。

fabric.Canvas#createPNGStream 是 Node 特有的方法之一。 其他一切都一样——您仍然可以像往常一样创建对象、将它们添加到画布上、修改、渲染等等。

节点服务器和 Fabric

作为示例,让我们创建一个简单的 Node 服务器,它将使用 JSON 格式的 Fabric 数据侦听传入请求,并输出该数据的图像。 整个脚本只有 25 行长!

var fabric = require('fabric').fabric, // or import { fabric } from 'fabric';
    http = require('http'),
    url = require('url'),
    PORT = 8124;

var server = http.createServer(function (request, response) {
  var params = url.parse(request.url, true);
  var canvas = new fabric.StaticCanvas(null, { width: 200, height: 200 });

  response.writeHead(200, { 'Content-Type': 'image/png' });

  canvas.loadFromJSON(params.query.data, function() {
    canvas.renderAll();

    var stream = canvas.createPNGStream();
    stream.on('data', function(chunk) {
      response.write(chunk);
    });
    stream.on('end', function() {
      response.end();
    });
  });
});

server.listen(PORT);

这个片段中的大部分代码应该已经很熟悉了。 它的要点在于服务器响应。 我们正在创建 Fabric 画布,将 JSON 数据加载到其上,进行渲染,并将最终结果作为服务器响应流式传输。

为了测试它,让我们取一个绿色的、稍微旋转的矩形的数据:

{"objects":[{"type":"rect","left":103.85,"top":98.85,"width":50,"height":50,"fill":"#9ae759","overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"scaleX":1.39,"scaleY":1.39,"angle":30,"flipX":false,"flipY":false,"opacity":0.8,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":false,"transparentCorners":true,"perPixelTargetFind":false,"rx":0,"ry":0}],"background":"rgba(0, 0, 0, 0)"}

对其进行 URI 编码:

%7B"objects"%3A%5B%7B"type"%3A"rect"%2C"left"%3A103.85%2C"top"%3A98.85%2C"width"%3A50%2C"height"%3A50%2C"fill"%3A"%239ae759"%2C"overlayFill"%3Anull%2C"stroke"%3Anull%2C"strokeWidth"%3A1%2C"strokeDashArray"%3Anull%2C"scaleX"%3A1.39%2C"scaleY"%3A1.39%2C"angle"%3A30%2C"flipX"%3Afalse%2C"flipY"%3Afalse%2C"opacity"%3A0.8%2C"selectable"%3Atrue%2C"hasControls"%3Atrue%2C"hasBorders"%3Atrue%2C"hasRotatingPoint"%3Afalse%2C"transparentCorners"%3Atrue%2C"perPixelTargetFind"%3Afalse%2C"rx"%3A0%2C"ry"%3A0%7D%5D%2C"background"%3A"rgba(0%2C%200%2C%200%2C%200)"%7D

并通过“数据”查询参数传递给服务器。 立即响应以“image/png”内容类型返回,如下所示:

如您所见,在服务器上使用 Fabric 非常简单直接。 随意尝试这个片段。 可能从 URL 参数中更改画布尺寸,或者在返回图像作为响应之前修改客户端数据。

节点上 Fabric 中的自定义字体

在我们可以在 Fabric 中使用自定义字体之前,我们需要先加载它们。 在浏览器(客户端)中,最常见的加载字体的方法是使用 CSS3 @font-face 规则 。 在 Fabric on Node(服务器端)中,我们可以使用 node-canvas  Font API ,这使得加载字体变得轻而易举。

下面的示例演示了如何加载和使用自定义字体。 将其保存到 customfont.js 并确保字体文件的路径正确。 在这个例子中,我们使用 Ubuntu 作为我们的自定义字体。

  var fs = require('fs'),
      fabric = require('fabric').fabric; // or import { fabric } from 'fabric';

  fabric.nodeCanvas.registerFont(__dirname + '/test/fixtures/Ubuntu-Regular.ttf', {
    family: 'Ubuntu', weight: 'regular', style: 'normal'
  });
  fabric.nodeCanvas.registerFont(__dirname + '/test/fixtures/Ubuntu-Bold.ttf', {
    family: 'Ubuntu', weight: 'bold', style: 'normal'
  });
  fabric.nodeCanvas.registerFont(__dirname + '/test/fixtures/Ubuntu-Italic.ttf', {
    family: 'Ubuntu', weight: 'regular', style: 'italic'
  });
  fabric.nodeCanvas.registerFont(__dirname + '/test/fixtures/Ubuntu-BoldItalic.ttf', {
    family: 'Ubuntu', weight: 'bold', style: 'italic'
  });

  var canvas = new fabric.StaticCanvas(null, { width: 300, height: 250 });

  var text = new fabric.Text('regular', {
      left: 0,
      top: 50,
      fontFamily: 'Ubuntu'
  });
  canvas.add(text);

  text = new fabric.Text('bold', {
      left: 0,
      top: 100,
      fontFamily: 'Ubuntu',
      fontWeight: 'bold'
  });
  canvas.add(text);

  text = new fabric.Text('italic', {
      left: 0,
      top: 150,
      fontFamily: 'Ubuntu',
      fontStyle: 'italic'
  });
  canvas.add(text);

  text = new fabric.Text('bold italic', {
      left: 0,
      top: 200,
      fontFamily: 'Ubuntu',
      fontWeight: 'bold',
      fontStyle: 'italic'
  });
  canvas.add(text);
  canvas.renderAll();
  var out = fs.createWriteStream(__dirname + '/customfont.png');
  var stream = canvas.createPNGStream();
  stream.on('data', function(chunk) {
      out.write(chunk);
  });

查看更多关于Fabric.js 简介。第 4 部分的详细内容...

  阅读:47次