如何清除画布属性和事件并将其添加回fabricjs?

     2023-03-25     302

关键词:

【中文标题】如何清除画布属性和事件并将其添加回fabricjs?【英文标题】:How to clear canvas properties and events and add it back in fabricjs? 【发布时间】:2021-03-26 23:19:08 【问题描述】:

上下文:

我有一个用例,我需要从堆栈中获取旧画布并将其分配给 dom 中当前活动的画布。我目前面临的问题是画布属性(例如背景颜色、高度等)被替换并正确显示,但如果画布内的对象,属性和事件看起来像是被替换但没有显示在活动中画布(DOM)。

注意:我这里没有使用fabric的撤消/重做的选项。

我试图在我尝试执行以下操作的 sn-p 中重新创建问题。

第 1 步:我正在使用 addTextBox 方法创建具有默认属性的画布和对象,一旦应用了默认属性,我会将画布和文本框对象存储在一个称为状态的变量中以进行备份。

第 2 步:

在 AddHelloText Click(Button) 上,我正在推送已记录的状态 在上一步中撤消堆栈。

之后,我将“hello”分配给文本框并“更改背景颜色” 变红”。

第 3 步: 在 Undo Click(Button) 上,我从 undoStack 获取 canvasOb 并将 i 分配给 canvas(活动画布)。

在这一步中,当我撤消时,画布上的值/事件应该是存储在 undoStack 中的备份画布,但它的值不正确。 简单来说,画布背景应该是“蓝色”,文本框对象应该有“默认文本”,即使我点击 在文本框上它应该有背景“蓝色”和文本 “默认文本”

这是我目前面临的两个问题。

只有背景更新,文本对象保持不变。

单击边界框(文本框)时,会显示画布的另一个实例(具有 step2 值的实例)

不确定我应该如何进一步进行。

任何建议都会很有帮助。

var canvas = new fabric.Canvas("c");
var t1 = null;
var state = ;
const addTextBox=(canvasParam)=>
     t1 = new fabric.Textbox('Default text', 
              width: 100,
              top: 5,
              left: 5,
              fontSize: 16,
              textAlign: 'center',
               fill: '#ffffff',
     );
     canvas.on('selected', () => 
            canvas.clearContext(canvas.contextTop);
        );
     canvas.setBackgroundColor('blue');
     canvas.add(t1);
  state=id:1,canvasOb:canvas,t1Backup:t1;


addTextBox(canvas);

var undoStack =[];

//Update the text to hello and change canvas background to red
  $('#addHello').on('click', function() 
    undoStack.push(state:_.cloneDeep(state))
    canvas.setBackgroundColor('red');
    t1.text="hello red"
    canvas.renderAll();
  )

 //apply previous canvas stored in the stack
  $('#undo').on('click', function() 
    console.log("TextBox value stored in undo stack: ",undoStack[0].state.canvasOb.getObjects()[0].text);
    console.log("TextBox value stored in undo stack: ",undoStack[0].state.t1Backup.text);
    canvas = undoStack[0].state.canvasOb;
    console.log("Textbox value that should be displayed currently instead of 'hello red':",canvas.getObjects()[0].text);
    canvas.renderAll();
  )
body 
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  width: 100vw;


#c 
  box-shadow: 0 0 20px 0px #9090908a;
  border-radius: 1rem;
  //padding:.5rem;


#app-container
  height: 30vh;
  width: 30vw;
<script src="https://unpkg.com/lodash@4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.1.0/fabric.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
<html><body><div id="app-container">
<canvas id="c"  ></canvas>
  <button id="addHello" class="button">Add hello</button>
  <button id="undo" class="button">Undo</button>
 </div></body></html>

【问题讨论】:

您好,我相信您想在不使用原生 fabric.js 撤消/重做 API 的情况下实现撤消/重做选项,对吧? 是的,我已经部分实现了,有些部分工作但不完全,以上是我目前面临的问题。 【参考方案1】:

即使您将其引用保存在您的状态对象中,您仍在动态更改画布对象。因此,当您更新文本或更改画布的背景颜色等时,实际上您正在更改保存的状态,因为到目前为止您所做的只是保存对 fabric.js 画布object 的引用。 这篇文章可能很有趣: Reference vs Primitive values in Javascript 完成您想要实现的目标的最佳方法(在我看来)是使用fabric.js toJSON 方法并将状态保存为JSON,然后在需要时使用loadFromJSON 再次检索它。 这是一个例子:

var canvas = new fabric.Canvas('c');
var t1 = null;
var undoStack = [];


// Whenever you make a change and then you want to save it as a state
const addNewState = () => 
    var canvasObject = canvas.toJSON();
    undoStack.push(JSON.stringify(canvasObject));
;

const initCanvas = () => 
    t1 = new fabric.Textbox('Default text', 
        width: 100,
        top: 5,
        left: 5,
        fontSize: 16,
        textAlign: 'center',
        fill: '#ffffff',
    );
    canvas.on('selected', () => 
        canvas.clearContext(canvas.contextTop);
    );
    canvas.setBackgroundColor('blue');
    canvas.add(t1);
    addNewState(); // Our first state
;

// Init canvas with default parameters
initCanvas(canvas);

const retrieveLastState = () => 
    var latestState = undoStack[undoStack.length - 1]; // Get last state
    var parsedJSON = JSON.parse(latestState);
    canvas.loadFromJSON(parsedJSON);
;

// Update the text to hello and change canvas background to red
$('#addHello').on('click', function () 
    canvas.setBackgroundColor('red');
    t1.text = 'hello red';
    canvas.renderAll();
);

// apply previous canvas stored in the stack
// Retrieve the very last state
$('#undo').on('click', function () 
    retrieveLastState();
    canvas.renderAll();
);
body 
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    width: 100vw;


#c 
    box-shadow: 0 0 20px 0px #9090908a;
    border-radius: 1rem;


#app-container 
    height: 30vh;
    width: 30vw;
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app-container">
        <canvas id="c"  ></canvas>
        <button id="addHello" class="button">Add hello</button>
        <button id="undo" class="button">Undo</button>
    </div>
    <script src="https://unpkg.com/lodash@4/lodash.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.1.0/fabric.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</body>

</html>

但是,下次您单击#addHello 按钮并尝试再次撤消它时,它不会起作用。原因是我们试图访问t1 变量,它是第一个画布上的一个fabric.js 对象。解决方案是为添加到画布的每个对象分配一个 id,以便您可以再次检索它们(用于修改、删除等)。这会让事情变得更复杂,所以我没有把它放在这里。

【讨论】:

感谢 shahbazi 这行得通,似乎是一种更好的方法。但是撤消后的“选定”事件不会调用jsfiddle.net/fierce_trailblazer/ao7xc412/5 我认为事件需要以不同的方式重新初始化 Nevermind loadFromJson 第三个参数可以用来重新初始化事件***.com/questions/49697408/… 或者,您可以监听selection:created 事件,并检查对象是否是您想要的对象:fabricjs.com/events

添加或删除对象时如何添加动画 - Fabricjs

】添加或删除对象时如何添加动画-Fabricjs【英文标题】:Howtoaddanimationwhenaddingorremovinganobject-Fabricjs【发布时间】:2017-06-1314:12:50【问题描述】:我将FabricJS用于我的图像处理库。我想知道如何将动画添加到画布中/从画布中删除的... 查看详情

画布上的 FabricJS AngularJS 事件

】画布上的FabricJSAngularJS事件【英文标题】:FabricJSAngularJSEventsonCanvas【发布时间】:2015-08-1422:55:45【问题描述】:我正在开发一个MEANStack应用程序,我在上面使用FabricJS。为了更轻松地工作,我找到了https://github.com/michaeljcalkins/an... 查看详情

如何在fabricJS中向圆形对象添加文本?

】如何在fabricJS中向圆形对象添加文本?【英文标题】:HowtoaddtexttoacircleobjectinfabricJS?【发布时间】:2016-08-0120:13:02【问题描述】:我在这里搜索fabricJS-circle,但没有找到添加数字1或2或3等文本的方法...在画布上的圆圈内?这是... 查看详情

FabricJS动画:鼠标:向上和:向下期间画布上的选定对象

】FabricJS动画:鼠标:向上和:向下期间画布上的选定对象【英文标题】:FabricJSanimating:selectedobjectoncanvasduringmouse:upand:down【发布时间】:2017-09-1405:39:34【问题描述】:我正在尝试使用FabricJS在任何对象被选中时为其设置动画。Sow... 查看详情

将图像拖放到画布(FabricJS)

】将图像拖放到画布(FabricJS)【英文标题】:DragAndDropImagetoCanvas(FabricJS)【发布时间】:2015-11-0702:32:31【问题描述】:问题我想用图像而不是canvas对象来做到这一点。这意味着您必须先添加要添加到画布的内容并作为画布的一部... 查看详情

使用fabricjs从json到图像

】使用fabricjs从json到图像【英文标题】:Fromjsontoimageusingfabricjs【发布时间】:2020-02-2608:12:49【问题描述】:我将一个fabricjs画布作为json保存在我的数据库中。我无意修改它,我只是想恢复它,调整它的大小,最后创建一个PNG或JP... 查看详情

如何从熊猫数据框中创建汇总新行并将其添加回相同的数据框仅用于特定列

】如何从熊猫数据框中创建汇总新行并将其添加回相同的数据框仅用于特定列【英文标题】:HowtocreateasummarizenewrowfromapandasDataframeandadditbacktothesameDataframeforonlyspecificcolumns【发布时间】:2021-12-0710:41:31【问题描述】:我有以下熊猫... 查看详情

Unity:添加画布后如何回滚到上一个场景

】Unity:添加画布后如何回滚到上一个场景【英文标题】:Unity:HowtorollbacktothepreviousSceneafteraddingacanvas【发布时间】:2019-02-2510:02:31【问题描述】:我应该是一个非常新手的问题,但是在谷歌上搜索了很多时间后我真的没有得到答... 查看详情

如何从画布中清除图表以便无法触发悬停事件?

】如何从画布中清除图表以便无法触发悬停事件?【英文标题】:Howtoclearachartfromacanvassothathovereventscannotbetriggered?【发布时间】:2014-09-0901:14:08【问题描述】:我正在使用Chartjs显示折线图,效果很好://getlinechartcanvasvartargetCanvas=... 查看详情

Fabric JS组选择和缩放弄乱了单个对象的位置属性

】FabricJS组选择和缩放弄乱了单个对象的位置属性【英文标题】:FabricJSgroupselectionandscalingmessingupindividualobjectpositionattributes【发布时间】:2021-09-1311:30:28【问题描述】:我正在尝试实现一个功能,使画布上的每个对象的大小均等... 查看详情

如何使用事件侦听器向对象数组添加新元素并将其显示在 html 页面上

】如何使用事件侦听器向对象数组添加新元素并将其显示在html页面上【英文标题】:Howtoaddnewelementstoanobjects-arrayusingeventlistenerandshowitonthehtmlpage【发布时间】:2020-01-0818:33:33【问题描述】:我正在尝试制作一个todo应用程序,然后... 查看详情

Fabric JS clipPath:裁剪后如何使图像适合画布?

】FabricJSclipPath:裁剪后如何使图像适合画布?【英文标题】:FabricJSclipPath:howtofittheimagetothecanvasaftercropping?【发布时间】:2020-07-0402:23:35【问题描述】:我使用FabricJS和clipPath属性实现了图像裁剪。问题是如何使图像在裁剪后适合... 查看详情

如何使fabricJS画布在移动设备上可水平拖动?

】如何使fabricJS画布在移动设备上可水平拖动?【英文标题】:HowtomakeafabricJScanvasdraggablehorizontallyonmobile?【发布时间】:2021-06-0811:38:39【问题描述】:我正在尝试创建一个比我的手机屏幕更宽的画布,用户可以左右拖动以查看画... 查看详情

在 FabricJS 画布上拖放和删除对象

】在FabricJS画布上拖放和删除对象【英文标题】:Drag,dropanddeleteobjectsonFabricJScanvas【发布时间】:2017-08-0814:53:13【问题描述】:我在使用JQuery处理FabricJS时遇到问题。选择一个对象并单击删除没有问题。这是我的代码演示Fiddle我可... 查看详情

Fabricjs:在画布上更新 SVG

】Fabricjs:在画布上更新SVG【英文标题】:Fabricjs:UpdateSVGonthecanvas【发布时间】:2019-01-2022:23:35【问题描述】:我使用的是fabricjs1.6.4,我想用新的svg更新现有的svg。我正在使用此代码添加新的SVG:fabric.loadSVGFromURL(url,function(objects,... 查看详情

使用 FabricJs 的裁剪功能

】使用FabricJs的裁剪功能【英文标题】:CropFunctionalityusingFabricJs【发布时间】:2013-09-1423:41:15【问题描述】:如何在使用fabric.js加载到画布上的图像上实现裁剪工具?我在画布上加载了一个图像。现在我想实现裁剪工具,允许用... 查看详情

如何从 JSON 重新加载自定义 fabricJS 画布对象?

】如何从JSON重新加载自定义fabricJS画布对象?【英文标题】:HowdoIreloadcustomfabricJScanvasobjectsfromJSON?【发布时间】:2021-06-1700:49:01【问题描述】:我正在使用fabricJS和自定义类。我遇到了canvas.loadFromJSON()的问题,所以我从anotherquesti... 查看详情

画布库如何适应 Flux 模式和 React?

...分离和单向数据流,但这也让我想知道我应该如何合并像fabricJS这样的画布库。FabricJS在原生画布元素上创建对象模型以扩展和简化功能。我的问题是是否在View(React组件)中初始化 查看详情