JS油漆
基于像素完美的基于Web的MS Paint Remake等…尝试一下!然后加入Discord服务器分享您的艺术品!
JS Paint重新创建了MS油漆的每个工具和菜单,甚至还鲜为人知的功能,以高度的保真度。
它支持主题,其他文件类型和可访问性功能,例如停留点击器和语音识别。
啊,是的,好老油漆。不是带有丝带或新的Skeuomormormormormorphic的界面的那个,可以占据近一半的屏幕。 (而不是更新的油漆3D。)
Windows 95、98和XP是涂料的黄金年。您有一个工具箱和一个颜色盒,一个前景颜色和背景颜色,这就是您所需要的。
事情很简单。
但是我们想撤消三个以上的动作。我们想编辑透明图像。我们不能只继续使用旧油漆。
这就是为什么我要制作JS油漆。我想把优质的旧油漆带入现代时代。
当前的改进包括:
- 开源(MIT许可)
- 跨平台
- 移动友好
- 触摸支持:用两个手指振作起来,然后捏缩放
- 单击/点击选定的颜色区域以交换前景和背景颜色
- 查看>全屏到切换全屏模式,非常适合小屏幕
-
Extras>快速撤消按钮以添加浮动撤消按钮,以便更轻松访问
- (默认情况下,触摸设备的默认情况下可能会启用)
- 网络功能
- Extras>主题以更改应用程序的外观。
- 黑暗变体
- 矢量工具图标手工制作以匹配像素艺术版本,用于现代和经典主题
- 神秘的主题,以万圣节的精神
- 冬季主题,带有特殊的调色板,包括糖果甘蔗条纹和出现日历样式襟翼,揭示了每个工具的像素艺术
- Bubblegum主题,具有商务粉红色配色方案和AI生成的图标
- Extras>放大UI以使按钮和菜单更大,以便使用眼睛跟踪器,头部跟踪器或其他课程输入设备使用。对于平板电脑来说,也可能不错,但目前的电话也不太适合。
- Extras>“停留”点击器可以通过悬停在一个位置上,以使用眼睛跟踪器或头部跟踪器来自动单击。
- 突出显示的按钮将突出显示,并在延迟后执行点击。
- 支持拖动窗户并在画布上绘制。
- 只需使用一个网络摄像头,您就可以使用Extras> Head Tracker使用Enable ViaCam(Head Tracker),Gazepointer(Exewerter)或内置的Tracky Mouse头跟踪器进行尝试。
- 使用Tracky Mouse API可以轻松地将此功能添加到其他Web应用程序中。
- Extras>语音识别以用您的声音控制应用程序。
- 选择工具和颜色(“填充工具”,“橙色”等)
- 欣赏视图(“向下滚动并向左滚动”或“向西南”等)
- 探索菜单,或激活任何菜单项而不首先打开菜单
- 与Windows互动
- 用文本工具指示文本
- 从当前文档历史记录中创建动画GIF。可从Extras菜单或CTRL+Shift+G中访问。这很漂亮,您应该尝试一下!不过,您可能需要限制图像的大小。
- 加载并保存许多带有颜色的调色板格式>获得颜色和颜色>保存颜色。 (我为此做了一个库:Anypalette.js。)
- 您还可以将调色板文件拖放到应用程序中以进行加载。
编辑功能:
- 使用alt+鼠标轮缩放进出
- 编辑透明图像!要创建一个透明的图像,请转到Image>属性…然后选择透明,然后确定,然后图像>清除图像或使用橡皮擦工具。具有任何半透明像素的图像将以透明模式打开。
- 您可以在持有CTRL时进行选择来裁剪图像
- 旋转的键盘快捷键: CTRL+。和ctrl+, ( <和> )
- 图像中的任何任意角度旋转>翻转/旋转
- 在图像>伸展/偏斜中,您可以一次拉伸超过500%
- 缩放到任意比例的视图>缩放>自定义…
- 缩放将画布安装在窗口中,并带有视图>缩放>缩放>缩放到窗口
- 无关紧要的填充:使用填充工具时,通过保持换档来替换整个图像中的颜色
其他改进:
- 垂直颜色盒模式,可从额外访问>垂直颜色框访问
- 您可以在任何缩放级别使用文本工具(它可以预览最终在画布上的精确像素)。
- 如果您的浏览器支持它,则可以在文本框中使用SpellCheck。
- 与Windows 10的油漆相比,调整大小的调节大小更容易抓取。
- 省略了一些缩略图视图错误,例如在错误的位置显示的选择。
- 无限的undos/重做(与Windows XP中的3个相反,或Windows 7中的50个)
- 撤消历史是非线性的,这意味着如果您撤消并做其他重做的事情,那么重做就不会丢弃。相反,在历史树中创建了一个新的分支。通过编辑>“历史”或“ ctrl+shift+y”跳到历史上的任何点
- 自动保留图像的备份。每个图像只有一个备份,这不会给您带来很多安全。请记住使用文件>保存或ctrl+s保存!使用文件>管理存储管理备份。
限制:
使用工具的一些事情尚未完成。请参阅todo.md
Web应用程序中的完整剪贴板支持需要一个浏览器支持带有images的异步剪贴板API,即在撰写时76+ Chrome。
在其他浏览器中,您仍然可以使用CTRL+C复制,用CTRL+X切割,然后用Ctrl+V粘贴,但是从JS涂料中复制的数据只能粘贴到其他JS涂料的实例中。外部图像可以粘贴到中。
支持的文件格式
图像格式
配x节省JPEG会引入使用填充工具或透明选择时引起问题的工件。
配x节省某些格式将减少图像中的颜色数量。
与MS Paint不同,您可以使用Edit> Undo来恢复节省的色彩或质量降低。这不会撤消文件,但允许您使用文件>另存为更高质量的不同格式。
建议保存为PNG,因为它可以在保留全质量的同时提供小文件尺寸。
| 文件扩展 | 姓名 | 读 | 写 | 阅读调色板 | 写调色板 |
|---|---|---|---|---|---|
| .png | PNG | ✅ | ✅ | ||
| .bmp,.dib | 单色位图 | ✅ | ✅ | ✅ | |
| .bmp,.dib | 16颜色位图 | ✅ | ✅ | ✅ | |
| .bmp,.dib | 256颜色位图 | ✅ | ✅ | ✅ | |
| .bmp,.dib | 24位位图 | ✅ | ✅ | N/A。 | N/A。 |
| .tif,.tiff,.dng,.cr2,.nef | TIFF(加载第一页) | ✅ | ✅ | ||
| PDF(加载第一页) | ✅ | ||||
| .webp | WebP | ||||
| .gif | GIF | ||||
| .jpeg,.jpg | jpeg | N/A。 | N/A。 | ||
| .svg | SVG(仅默认尺寸) | ||||
| .ico | ICO(仅默认尺寸) |
当前,标记的功能保留到浏览器中以支持或不支持。如果标记了“写入”,则格式将出现在文件类型下拉列表中,但在尝试保存时可能不起作用。有关打开文件,请参见Wikipedia的浏览器映像格式支持表,以获取更多信息。
标记的功能可能很快即将到来,不适用的N/A手段。
“ Read Palette”是指自动将颜色加载到颜色框中(从索引的颜色图像),“ Write Palette”是指编写索引的颜色图像。
调色板格式
使用颜色>保存颜色和颜色>获得颜色,您可以以许多不同格式保存和加载颜色,以兼容各种程序。
如果您想在另一个应用程序中添加广泛的调色板支持,我将此功能作为库提供:Anypalette.js
| 文件扩展 | 姓名 | 程序 | 读 | 写 |
|---|---|---|---|---|
| 。朋友 | 即兴调色板 | Windows 95和Windows NT 4.0的MS油漆 | ✅ | ✅ |
| .gpl | gimp调色板 | gimp,inkscape,krita,kolourpaint,scribus,cinepaint,mypaint | ✅ | ✅ |
| .aco | Adobe颜色色板 | Adobe Photoshop | ✅ | ✅ |
| .ase | Adobe Swatch Exchange | Adobe Photoshop,Indesign和Illustrator | ✅ | ✅ |
| 。TXT | paint.net调色板 | paint.net | ✅ | ✅ |
| 。行为 | Adobe颜色表 | Adobe Photoshop和Illustrator | ✅ | ✅ |
| .pal,.psppalette | 油漆店Pro调色板 | Paint Shop Pro(JASC软件 / Corel) | ✅ | ✅ |
| .hpl | 家庭调色板 | Allaire Homesite / Macromedia Coldfusion | ✅ | ✅ |
| 。CS | Colorschemer | Colorschemer Studio | ✅ | |
| 。朋友 | 星际船调色板 | 星际争霸 | ✅ | ✅ |
| .wpe | 星形地形调色板 | 星际争霸 | ✅ | ✅ |
| .sketchpalette | 草图调色板 | 草图 | ✅ | ✅ |
| .spl | 滑雪调色板 | Skencil(以前称为素描) | ✅ | ✅ |
| .soc | Staroffice颜色 | Staroffice,OpenOffice,Libreoffice | ✅ | ✅ |
| 。颜色 | KolourPaint Color Collection | Kolourpaint | ✅ | ✅ |
| 。颜色 | 等离子桌面配色方案 | KDE等离子桌面 | ✅ | |
| 。主题 | Windows主题 | Windows桌面 | ✅ | |
| .themepack | Windows主题 | Windows桌面 | ✅ | |
| .css,.scss,.styl | 级联样式表 | 网络浏览器 /网页 | ✅ | ✅ |
| .html,.svg,.js | 任何具有CSS颜色的文本文件 | 网络浏览器 /网页 | ✅ |
你可知道?
-
有一个黑色和白色模式,带有图案,而不是调色板中的颜色,您可以从图像>属性…
-
如果您在正确的位置抓住颜色框和工具箱,则可以将其拖动。您甚至可以将它们拖到小窗户中。您可以双击其标题栏,将窗户放回侧面。
-
除了左键单击前景颜色和右键单击背景颜色外,还可以通过绘制CTRL访问第三种颜色。它从没有颜色开始,因此您需要保持CTRL并首先选择颜色。关于此颜色插槽的奇特之处在于,您可以在绘制时按和释放CTRL以切换颜色。
-
您可以将图像转换(例如翻转/旋转,伸展/偏斜或反转(在图像菜单中)应用于整个图像或选择。尝试使用自由形式的选择工具涂抹,然后进行图像>倒置
-
这些MS油漆教程中的技巧和技巧也可以在JS Paint中起作用:
- 刷缩放(在数字垫上+ & -调整刷子尺寸)
- “自定义刷子”(保持移位并拖动选择以涂抹它)
- “邮票”“工具”(保持轮换并单击选择以打印)
- 图像缩放(在数字垫上+ & -以2缩放选择的选择)
- 颜色更换(用橡皮擦右键鼠标按钮,以选择性地用背景颜色替换前景颜色)
- 网格( Ctrl+G &Zoom至4x+)
- 快速撤消(按第二个鼠标按钮取消您执行的动作。如果您偶然这样做,我也可以重做!)
- 滚动轮虫(嗯,也许不要重新创建这个?)
桌面应用
PWA
JS油漆可以安装为渐进式网络应用程序(PWA),尽管它尚未脱机。在地址栏中查找安装提示。
PWA功能:
- 没有地址栏;网络和本地之间的中间地面
- 跨平台(MacOS,Windows,Linux,Android,iOS)
- 基本文件集成:
- 文件>打开
- 文件>保存下载文件后,要求使用文件名和格式
- 将文件拖到窗口上以打开它们
缺少功能:
-
直接保存到文件已实现,但目前未启用。
我担心数据丢失的原因有两个:1。文件的行为>“保存 / ctrl+s的行为”的变化,从有效地执行直接覆盖文件,尽管我为此做了一个警告对话框,但不再显示选项; 2。有一个错误的错误,保存的文件最终完全空(零字节),我不知道这是我的代码还是铬中的错误。
-
离线支持未实施。
我已经对此进行了一些刺伤,但我不是唯一的一个,但是有一些巨大的警告,例如开发服务器无法在不破坏服务工作者的情况下实现重新负载。
电子
我还将其置于带电子和电子锻造的桌面应用程序中。您可以从“发行”页面下载它。
电子应用功能:
- 类似于本地的体验(在没有地址栏的窗口中运行)
- 跨平台(MacOS,Windows,Linux)
- 剪贴板支持
- 文件可以通过各种方式打开:
- 文件>打开
- 拖到窗口
- 拖放到MacOS上的码头图标
- 拖放到桌面快捷方式上
-
右键单击>在文件管理器中打开(MACOS和Linux)
- 在Windows上,您可以手动将通往可执行文件的路径粘贴到Open -with Dialog中,您可以通过在任务栏中右键单击应用程序,然后右键单击应用程序的名称并选择属性来找到。在“快捷”选项卡中,目标字段是通往可执行文件的路径。以这种方式打开应用程序后,该应用程序将显示在列表的开放式上,如果选择“始终”,它将成为该文件类型的默认应用程序。
- 命令行:在终端中键入jspaint Path/to/file.png
- 文件>保存将直接保存到文件
- 文件>设置为墙纸(瓷砖)和文件>设置为墙纸(中心)
- 在MacOS上,标题栏中显示了代表当前打开文件的图标。您可以将此图标拖到其他应用程序中,例如,在电子邮件中包括您要编辑的图像。有未保存的更改时,图标会变暗。
电子应用程序限制
- 基础:
- 默认情况下执行在Mac和Windows上被阻止
- 在MacOS上,您需要CTRL+单击该文件,然后说打开
- 在Windows上,您需要说“更多信息”,然后说“运行”(或“无论如何运行”?)
- 我需要支付代码签名费以避免这种费用。基本上是勒索的安全性。
- 没有自动更新。显然,我需要支付代码签名的费用才能获得此免费服务。
- 也就是说,关于油漆的帮助>至少在新闻更新方面,可以告诉您JS油漆是否过时。
- 电子已经过时。例如,它可能包含已修复的图像解码漏洞。但是,我采取了预防措施来沙箱应用程序,并将写入访问权限限制在应用程序中明确打开的文件列表中,该列表由主过程控制,与渲染器过程分开,该过程将处理图像解码。
- 只能一次打开一个单个编辑窗口。
- 文件菜单的最新文件列表尚未实现,也没有特定于OS的跳跃菜单。
- 默认情况下执行在Mac和Windows上被阻止
- 末节:
- 如果您在“管理存储对话框”中单击“打开链接”之前,请显示一个非常令人困惑的消息。
- WebGL错误消息告诉您刷新而不提供重新加载的方法;另外,将应用程序称为网页感觉没有打印
- 文件>“打开”对话框没有所有文件(*。*)选项,并且支持的文件类型列表并不详尽;例如,可以加载AVIF图像,但仅通过拖放来加载
- 拖放显示两个“将更改保存到x?”对话彼此?
- 我不确定所有这些仍然是问题,需要重新测试它们:
- 退出不会完全退出应用程序,只有在打开的窗口…预期的行为时才关闭窗口?不应该右键单击>退出真的退出吗? https://stac*kover**flow.com/questions/44316306/how-to-to-quit-electron-app-on-mac
- 当保存更改提示提示时,退出不会显示/焦点窗口
- Ctrl+C未在Mac/Linux电子/电子#5273上退出
- 这是因为editor_window.on(“关闭”)调用预防违规,可能是一个功能,但需要显示/聚焦窗口
- https://st*a*cko*verflow.com/questions/75362687/electron-js-processes-do-not-exit-on-app-quit
- 打开SVG文件也无法通过命令行参数(拖动到文件资源管理器中的快捷方式)工作),即使拖动并掉入窗口工作中也是如此。
- 似乎将加载SVG作为调色板加载…这是我遇到的东西吗?
开发设置
克隆仓库。
如果没有它,请安装Node.js,然后在项目目录中打开命令提示符 /终端。
质量保证
运行NPM运行皮棉以检查拼写错误,类型错误,代码样式问题和其他问题。
运行NPM运行格式以自动修复格式问题,或NPX ESLINT-修复所有可自动固定问题的文件。
格式规则配置为与VS Code的内置格式化器的兼容性。
运行NPM测试以使用柏树运行基于浏览器的测试。 (不幸的是,启动和运行测试很慢。)
运行NPM运行接受以接受任何视觉更改。不幸的是,这重新运行了所有测试,而不是接受先前测试的结果,因此您最终可能会得到与以前的测试不同的结果。如果使用GitHub桌面,则可以以四种不同的模式查看图像的差异。
要打开Cypress UI,请先运行NPM运行测试:start-server,然后同时进行NPM运行CY:打开
测试还与Travis CI连续集成。
Web应用程序(https://*jsp**aint.app)
使用NPM I安装依赖关系后,请使用NPM Run Dev启动实时填充服务器。
确保在balout.css中使用任何布局重要样式。在更新布局时,使用RTLCSS生成了样式表的左右版本。
您应该通过将语言更改为阿拉伯语或希伯来语来测试RTL布局。转到Extras>“语言>ال样”或“עברעבר” 。
有关如何控制RTL布局,请参见控制指令。
有一个VS代码启动任务,用于附加到Chrome进行调试。有关使用说明,请参见.vscode/启动。
桌面应用(电子)
- 使用NPM i安装依赖项
- 使用NPM运行电子启动电子应用:开始
包括电子选,因此您可以使用F5 / Ctrl+R进行重新加载,而F12 / Ctrl+Shift+I打开DevTools。
您可以使用NPM运行电子来构建生产:制作
有一个VS代码启动任务,用于调试电子主过程。对于渲染器过程,您可以使用嵌入式的Chrome DevTools。
部署
可以使用常规Web服务器部署JS涂料。
没有什么需要编译的。
CORS代理
可选地,如果将URL粘贴到JS Paint中,则可以设置Anywhere Server的CORS Anywhere Server,或使用#load:<URL>功能,其中不在同一域上。
默认情况下,它将使用设置的CORS使用CORS来与jspaint .App一起使用。
它是在Heroku上免费托管的,您可以设置自己的实例并将其配置为与自己的域一起使用。
您必须使用自己的实例URL查找并替换https://jspaint-cors-proxy.her**ok*uapp.com。
多人游戏支持
多人支持当前依赖于不是开源软件的Firebase。
您可以创建一个Firebase实时数据库实例,并编辑JS Paint的Sessions.js指向它,在设置Web应用程序时,用Firebase Console替换了传递给initializeapp的配置。
但是到目前为止,多人游戏模式非常卑鄙。应该用开源的东西代替,更安全,更高效,更健壮。
嵌入您的网站
简单的
将其添加到您的HTML:
< iframe src =\" https://j*spaint*.*app \" width =\" 100% \" height =\" 100% \" > </ iframe >
从图像开始
您可以通过向URL添加#load:<url>从URL加载图像。
< iframe src =\" https://j*spaint*.*app#load:https://j*spaint*.*app/favicon.ico \" width =\" 100% \" height =\" 100% \" > </ iframe >
先进的
如果要控制JS涂料,如何保存/加载文件或直接访问画布,则有一个不稳定的API。
首先,您需要克隆回购,因此您可以将iFrame指向本地副本。
JS油漆的本地副本必须托管与包含页面同一Web服务器,或者更具体地说,必须共享相同的来源。
拥有本地副本也意味着API随时都不会破裂。
如果将JS涂料克隆到一个名为jspaint的文件夹中,该文件夹与要嵌入的页面相同的文件夹中,您可以使用此信息:
jspaint -iframe\” width=\”100%\” height=\”100%\”></iframe>\”>
< iframe src =\" jspaint /index.html \" id =\" jspaint -iframe \" width =\" 100% \" height =\" 100% \" > </ iframe >
如果它居住在其他地方,则可能需要添加../到路径的开始,才能上升一个水平。例如,src =“ ../../ apps/ jspaint /index.html”。您也可以使用绝对URL,例如src =“ https://*e*xa*mple.com/cool-apps/jspaint/index.html”。
更改文件的保存/加载方式
您可以使用JS Paint的SystemHooks API覆盖文件保存和打开对话框。
jspaint-iframe\”);
var jspaint = iframe.contentWindow;
// Wait for systemHooks object to exist (the iframe needs to load)
waitUntil(()=> jspaint .systemHooks, 500, ()=> {
// Hook in
jspaint .systemHooks.showSaveFileDialog = async ({ formats, defaultFileName, defaultPath, defaultFileFormatID, getBlob, savedCallbackUnreliable, dialogTitle }) => { … };
jspaint .systemHooks.showOpenFileDialog = async ({ formats }) => { … };
jspaint .systemHooks.writeBlobToHandle = async (save_file_handle, blob) => { … };
jspaint .systemHooks.readBlobFromHandle = async (file_handle) => { … };
});
// General function to wait for a condition to be met, checking at regular intervals
function waitUntil(test, interval, callback) {
if (test()) {
callback();
} else {
setTimeout(waitUntil, interval, test, interval, callback);
}
}
</script>\”>
< script > var iframe = document . getElementById ( \" jspaint -iframe\" ) ; var jspaint = iframe . contentWindow ; // Wait for systemHooks object to exist (the iframe needs to load) waitUntil ( ( ) => jspaint . systemHooks , 500 , ( ) => { // Hook in jspaint . systemHooks . showSaveFileDialog = async ( { formats , defaultFileName , defaultPath , defaultFileFormatID , getBlob , savedCallbackUnreliable , dialogTitle } ) => { ... } ; jspaint . systemHooks . showOpenFileDialog = async ( { formats } ) => { ... } ; jspaint . systemHooks . writeBlobToHandle = async ( save_file_handle , blob ) => { ... } ; jspaint . systemHooks . readBlobFromHandle = async ( file_handle ) => { ... } ; } ) ; // General function to wait for a condition to be met, checking at regular intervals function waitUntil ( test , interval , callback ) { if ( test ( ) ) { callback ( ) ; } else { setTimeout ( waitUntil , interval , test , interval , callback ) ; } } </ script >
斑点代表内存中文件的内容。
文件句柄是可以识别文件的任何东西。您可以拥有此概念,并定义如何识别文件。从索引到数组到Dropbox文件ID,再到IPFS URL,再到文件路径,它可能是任何东西。我忘记了它可以是任何类型,也许它可能是字符串。
一旦有了文件句柄的概念,就可以使用系统挂钩实现文件拾取器,以及函数以读写文件。
| 命令 | 使用的钩子 |
|---|---|
| 文件>另存为 | systemhooks.showsavefiledialog,然后选择文件时,systemhooks.writeblobtohandle |
| 文件>打开 | systemhooks.showopenfiledialog,然后选择文件时,systemhooks.readblobfromhandle |
| 文件>保存 | systemhooks.writeblobtohandle(或与文件相同>保存,如尚未打开文件) |
| 编辑>复制到 | systemhooks.showsavefiledialog,然后选择文件时,systemhooks.writeblobtohandle |
| 编辑>粘贴 | systemhooks.showopenfiledialog,然后选择文件时,systemhooks.readblobfromhandle |
| 文件>设置为墙纸(瓷砖) | systemhooks.setWallPaperiled如果定义,else systemhooks.setwallpaperered如果定义,则与文件>另存为 |
| 文件>设置为墙纸(中心) | Systemhooks.setWallPaperered如果定义,则与文件>另存为 |
| Extras>渲染历史为GIF | 与文件相同>另存为 |
| 颜色>保存颜色 | 与文件相同>另存为 |
| 颜色>获得颜色 | 与文件相同>打开 |
最初加载文件
要使用加载用于编辑的文件启动该应用程序,请等待应用程序加载,然后使用文件句柄readBlobFromHandle调用,并告诉应用程序加载该文件blob。
const file_handle = \"initial-file-to-load\" ; systemHooks . readBlobFromHandle ( file_handle ) . then ( file => { if ( file ) { contentWindow . open_from_file ( file , file_handle ) ; } } , ( error ) => { // Note: in some cases, this handler may not be called, and instead an error message is shown by readBlobFromHandle directly. contentWindow . show_error_message ( `Failed to open file ${ file_handle } ` , error ) ; } ) ;
这很笨拙,将来可能会有一个查询字符串参数来通过其句柄加载初始文件。 (自我注意:它需要等待您的系统挂钩注册,以某种方式。)
已经有一个查询字符串参数可以从URL加载:
< iframe src =\" https://j*spaint*.*app?load:SOME_URL_HERE \" > </ iframe >
但这不会设置用于保存的文件句柄。
集成为墙纸
您可以定义两个功能来设置墙纸,将通过文件>设置为墙纸(瓷砖)和文件>设置为墙纸(中心) 。
- systemhooks.setWallPaperTiled =(canvas)=> {…};
- systemhooks.setWallPaperered =(canvas)=> {…};
如果仅定义SystemHooks.SetWallPaperered,JS Paint将尝试猜测屏幕的尺寸并铺图像,并通过调用SystemHooks.setWallPaperered功能应用它。
如果您不指定SystemHooks.setWallPaperered,则使用SystemHooks.showsavefiledialog和SystemHooks.writeBlobtoHandle保存文件(<原始文件名> wallpaper.png)。
这是一个完整的示例,支持持续的自定义墙纸作为包含页面上的背景:
jspaint.systemHooks.setWallpaperCentered = (canvas) => {
canvas.toBlob((blob) => {
setDesktopWallpaper(blob, \”no-repeat\”, true);
});
};
jspaint .systemHooks.setWallpaperTiled = (canvas) => {
canvas.toBlob((blob) => {
setDesktopWallpaper(blob, \”repeat\”, true);
});
};
function setDesktopWallpaper(file, repeat, saveToLocalStorage) {
const blob_url = URL.createObjectURL(file);
wallpaper.style.backgroundImage = `url(${blob_url})`;
wallpaper.style.backgroundRepeat = repeat;
wallpaper.style.backgroundPosition = \”center\”;
wallpaper.style.backgroundSize = \”auto\”;
if (saveToLocalStorage) {
const fileReader = new FileReader();
fileReader.onload = () => {
localStorage.setItem(\”wallpaper-data-url\”, fileReader.result);
localStorage.setItem(\”wallpaper-repeat\”, repeat);
};
fileReader.onerror = () => {
console.error(\”Error reading file (for setting wallpaper)\”, file);
};
fileReader.readAsDataURL(file);
}
}
// Initialize the wallpaper from localStorage, if it exists
try {
const wallpaper_data_url = localStorage.getItem(\”wallpaper-data-url\”);
const wallpaper_repeat = localStorage.getItem(\”wallpaper-repeat\”);
if (wallpaper_data_url) {
fetch(wallpaper_data_url).then(response => response.blob()).then(file => {
setDesktopWallpaper(file, wallpaper_repeat, false);
});
}
} catch (error) {
console.error(error);
}\”>
const wallpaper = document . querySelector ( \"body\" ) ; // or some other element jspaint . systemHooks . setWallpaperCentered = ( canvas ) => { canvas . toBlob ( ( blob ) => { setDesktopWallpaper ( blob , \"no-repeat\" , true ) ; } ) ; } ; jspaint . systemHooks . setWallpaperTiled = ( canvas ) => { canvas . toBlob ( ( blob ) => { setDesktopWallpaper ( blob , \"repeat\" , true ) ; } ) ; } ; function setDesktopWallpaper ( file , repeat , saveToLocalStorage ) { const blob_url = URL . createObjectURL ( file ) ; wallpaper . style . backgroundImage = `url( ${ blob_url } )` ; wallpaper . style . backgroundRepeat = repeat ; wallpaper . style . backgroundPosition = \"center\" ; wallpaper . style . backgroundSize = \"auto\" ; if ( saveToLocalStorage ) { const fileReader = new FileReader ( ) ; fileReader . onload = ( ) => { localStorage . setItem ( \"wallpaper-data-url\" , fileReader . result ) ; localStorage . setItem ( \"wallpaper-repeat\" , repeat ) ; } ; fileReader . onerror = ( ) => { console . error ( \"Error reading file (for setting wallpaper)\" , file ) ; } ; fileReader . readAsDataURL ( file ) ; } } // Initialize the wallpaper from localStorage, if it exists try { const wallpaper_data_url = localStorage . getItem ( \"wallpaper-data-url\" ) ; const wallpaper_repeat = localStorage . getItem ( \"wallpaper-repeat\" ) ; if ( wallpaper_data_url ) { fetch ( wallpaper_data_url ) . then ( response => response . blob ( ) ) . then ( file => { setDesktopWallpaper ( file , wallpaper_repeat , false ) ; } ) ; } } catch ( error ) { console . error ( error ) ; }
有点递归,对不起;可能会更简单。就像仅使用数据URL。 (实际上,我认为我想使用blob URL,以免它用超长的URL膨胀DOM Insportor。这实际上是DevTools UX错误。也许他们已经改善了这一点?)
指定画布大小
您可以加载具有所需尺寸的文件。目前没有特殊的API。
请参阅最初加载文件。
指定主题
您可以以编程方式更改主题:
jspaint-iframe\”);
var jspaint = iframe.contentWindow;
jspaint .set_theme(\”modern.css\”);\”>
var iframe = document . getElementById ( \" jspaint -iframe\" ) ; var jspaint = iframe . contentWindow ; jspaint . set_theme ( \"modern.css\" ) ;
但这将破坏用户的喜好。
Extras>“主题”菜单仍然可以使用,但是在重新加载页面时,偏好不会持续。
将来可能会有一个查询字符串参数来指定默认主题。您还可以分配jspaint更改默认主题。
指定语言
与主题类似,您可以尝试以编程方式更改语言:
jspaint-iframe\”);
var jspaint = iframe.contentWindow;
jspaint .set_language(\”ar\”);\”>
var iframe = document . getElementById ( \" jspaint -iframe\" ) ; var jspaint = iframe . contentWindow ; jspaint . set_language ( \"ar\" ) ;
但这实际上会要求用户重新加载应用程序以更改语言。
Extras>“语言”菜单仍将起作用,但是每次重新加载页面时,用户都会不愿更改语言。
将来可能会有一个查询字符串参数来指定默认语言。您还可以分配jspaint来更改默认语言。
添加自定义菜单
尚未支持。您可以分叉jspaint并添加自己的菜单。
直接访问画布
通过访问画布,您可以实现图纸的实时预览,例如,实时更新游戏引擎中的纹理。
jspaint-iframe\”);
// contentDocument here refers to the webpage loaded in the iframe, not the image document loaded in jspaint .
// We\’re just reaching inside the iframe to get the canvas.
var canvas = iframe.contentDocument.querySelector(\”.main-canvas\”);\”>
var iframe = document . getElementById ( \" jspaint -iframe\" ) ; // contentDocument here refers to the webpage loaded in the iframe, not the image document loaded in jspaint . // We\'re just reaching inside the iframe to get the canvas. var canvas = iframe . contentDocument . querySelector ( \".main-canvas\" ) ;
建议不要将其用于加载文档,因为它不会更改文档标题或重置撤消/重做历史记录等。而是使用open_from_file。
执行自定义操作
如果您想制作按钮或其他UI来对文档进行操作,则应该(可能)使其变得不可行。这很容易,只需将您的动作包裹在通话中。
jspaint-iframe\”);
var jspaint = iframe.contentWindow;
var icon = new Image();
icon.src = \”some-folder/some-image-15×11-pixels.png\”;
jspaint .undoable({
name: \”Seam Carve\”,
icon: icon, // optional
}, function() {
// do something to the canvas
});\”>
var iframe = document . getElementById ( \" jspaint -iframe\" ) ; var jspaint = iframe . contentWindow ; var icon = new Image ( ) ; icon . src = \"some-folder/some-image-15x11-pixels.png\" ; jspaint . undoable ( { name : \"Seam Carve\" , icon : icon , // optional } , function ( ) { // do something to the canvas } ) ;
async函数systemhooks.showsavefiledialog({格式,defaultFileName,defaultpath,defaultfileformatid,getBlob,savedcallbackunrable,dialogTitle})
定义此功能以覆盖默认保存对话框。这既用于保存图像,调色板文件和动画。
参数:
- 格式:代表文件类型的对象数组,并具有以下属性:
- 格式化:唯一标识格式的字符串(可能与模拟型相同)
- Mimetype(可选):文件格式的指定媒体类型,例如“ Image/png”(调色板格式没有此属性)
- 名称:文件格式的名称,例如“ WebP”
- nameWithExtensions:文件格式的名称,然后是扩展名列表,例如“ Tiff(*.tif;*。tiff)”
- 扩展:一个文件扩展名,不包括DOT,首选扩展名,例如[“ BMP”,“ DIB”]
- DefaultFilename(可选):建议的文件名,例如“ Untitled.png”或打开文档的名称
