javascript - 如何有效地存储手绘线(画布)?
问题描述
背景
我正在制作一个简单的在线绘图应用程序,以便我可以练习我的 JS 和画布技能。进展非常顺利,可以自由绘制,也可以绘制直线。
我的绘图应用程序如何工作
它注册处理所有绘图和保存的鼠标和触摸事件。
这是一些示例代码:
var tools={
"pencil":{
"started": false,
... (some data used by the pencil tool),
"start":function(e){
if(currentTool!=="pencil")return;
// Make sure that the selected tool on the toolbar is the pencil
// code for mousedown/touchstart
tools.pencil.started=true;
},
"move":function(e){
if(!tools.pencil.started)return;
// code for mousemove/touchmove
},
"end":function(e){
if(!tools.pencil.started)return;
// code for mouseup/touchend
tools.pencil.started=false;
}
},
"other tools":{
...
}
};
// And here would be a function which adds the mouse and touch events
这是我的铅笔工具:
var tools={
pencil:{
started:false,
start:function(e){
if(currentTool!=="pencil")return; // Make sure the pencil tool is selected
e.preventDefault();
e=e.clientX?e:e.touches[0]; // Allow touch
context.beginPath(); // Begin drawing
context.moveTo(e.clientX-50,e.clientY); // Set the position of the pencil
tools.pencil.started=true; // Mark the pencil tool as started
},
move:function(e){
if(tools.pencil.started){ // Make sure the pencil is started
e.preventDefault();
e=e.clientX?e:e.touches[0];
context.lineTo(e.clientX-50,e.clientY); // Draw a line
context.stroke(); // Make the line visible
}
},
end:function(e){
if(tools.pencil.started){
e.preventDefault();
//tools.pencil.move(e); // Finish drawing the line
tools.pencil.started=false; // Mark the pencil tool as not started
}
}
}
};
忽略-50
部分(它们只是用侧边栏调整)。这有效,但不能保存到localStorage
.
问题
TL;DR:我需要将画布上的所有内容保存到某个存储中(我目前正在使用localStorage
,但任何东西都可以,尽管我更喜欢只使用客户端)。我不知道如何有效地存储它,其中“有效”意味着快速和准确(准确,因为它存储了整条线)。线可以存,但是手绘的东西我还没弄明白。
解释:
当用户调整窗口大小时,画布会调整为窗口大小(我做到了,不是错误)。我能够做到,当您调整大小时,它首先将绘图保存到临时画布上,然后在主画布调整大小后,重新绘制它们。但是有一个问题。这是一个清楚的例子:
- 您打开绘图应用程序并用绘图填充屏幕。
- 你打开 DevTools,一些图纸被覆盖了
- 当你关闭 DevTools 时,那些绘图就消失了。
原因是因为画布变小了,从上面掉下来的图纸就丢失了,当它恢复到原来的大小时,它们就看不见了(因为它们已经消失了)。我决定保存所有内容localStorage
以便我可以保留它们(以及我可能添加的更多功能)。线条正在工作(因为他们只需要说,“我是一条线,我从 x,y 开始,在 x,y 结束”。对于任何大小的线条都是如此。但对于手绘图像,他们可以去任何地方,所以他们需要说,“我是一个像素,我在 x,y 处”,但对于即使是远程复杂的图像也有很多次。
尝试的解决方案
每当他们移动鼠标时,它都会保存到一个变量中,然后更新为localStorage
. 这样做的问题是,如果你走得很快,那么这些行就不完整(里面有洞)并且localStorage
会存储大量文本。
问题
如何有效地存储用户的所有手绘(铅笔工具)图像(首选客户端操作)?
解决方案
我的建议是考虑这个应用程序的目标用途并从它向后工作。
如果您正在做类似 MS Paint 绘图应用程序,将画布存储为位图可能会更好。为了处理裁剪问题,我建议您使用预定义的画布大小或设置阶段(具有最大大小以防止保存到 LocalStorage 的问题)。
如果您担心图像大小因内存上限而受到限制,您也可以使用压缩。
IE。
canvas.toDataURL('image/jpeg', 0.5);
将压缩图像并返回一个对 localStorage 友好的字符串
另一方面✋,如果您正在构建更像excalidraw 应用程序的东西,您希望在其中保持编辑任何绘制对象的能力,那么您需要单独存储每个对象。无论您使用画布还是 SVG 并不重要,但是 SVG 可以让它更容易一些,因为已经建立了如何存储每个元素的定义,所以您不需要重新发明轮子,可以这么说,只需要实现它。使用 SVG 并不一定会阻止您使用画布,因为有几个 SVG-in-canvas 实现,但是如果您将其作为一个学习项目(尤其是对于画布),它可能不是您想要的路线拿。
推荐阅读
- reactjs - React JS - 如何在对话框的 PaperProps 中添加样式(material-ui)
- c# - TcpListener 没有从 SmtpClient 接收到数据
- ionic3 - 在 Ionic 3 中使用 HttpClient 下载文件
- c - 如何通过C编程实时获取本地监听端口?
- google-sheets - 如何创建一个运行总计公式,当新行添加到我的电子表格时自动扩展
- azure - 是否可以在 Azure 仪表板中嵌入 PowerBi 报告
- sql - 多列连接成一列 SQL
- c# - 在 C# 中使用套接字
- c# - 从 4 个球体中获取 X、Y、Z 位置
- facebook-graph-api - 使用 Facebook Instagram API business_discovery 获取特定媒体的 like_count 和 comments_count