<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>1141326491 (JessYan)</title>
    <link>https://w2solo.com/1141326491</link>
    <description/>
    <language>en-us</language>
    <item>
      <title>✨ Pictode：十分钟 DIY 图形编辑器💡很轻松</title>
      <description>&lt;p&gt;原文阅读：&lt;a href="https://juejin.cn/post/7286307632193142843" rel="nofollow" target="_blank"&gt;https://juejin.cn/post/7286307632193142843&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;利用两个多月的业余时间，使用 Konva.js 实现了一个名为【Pictode】的图形编辑器&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;体验地址: &lt;a href="https://jessyan0913.github.io/pictode-playground/#/" rel="nofollow" target="_blank"&gt;https://jessyan0913.github.io/pictode-playground/#/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src="https://img.way2solo.com/photo/1141326491/2b790bc9-3350-4345-82cc-eb28d8cce3fb.png?imageView2/2/w/1920/q/100" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="缘起"&gt;缘起&lt;/h2&gt;
&lt;p&gt;在掘金上看到众多技术大咖打造自己的图形编辑器项目。通过阅读大咖们的文章让我深受启发，我既敬佩这些大咖坚持创作和分享的精神，也自豪于自己也有编辑器项目的经验。这些因素汇聚，催生了我开发一个自己的图形编辑器的想法。&lt;/p&gt;

&lt;p&gt;虽然我以前在工作中已经实现了一些编辑器项目，如基于 Three.js 的 3D 编辑器、基于 bpmn.js 的流程编辑器、基于 X6 的拓扑编辑器，还有基于 Vue 的低代码编辑器等，但受公司项目限制，这些编辑器无法达到我理想中的水平。&lt;/p&gt;

&lt;p&gt;今年 8 月份，我利用业余实践开始了名为&lt;code&gt;Pictode&lt;/code&gt;的图形编辑器项目。&lt;strong&gt;到目前为止，&lt;code&gt;Pictode&lt;/code&gt;集成了众多实用功能，如工具切换、属性编辑、右键菜单、本地保存、导出图片、画布缩放、画布拖拽、历史记录、语言切换、主题切换等&lt;/strong&gt;。经过这段时间努力，我认为&lt;code&gt;Pictode&lt;/code&gt;已初步具备雏形，因此我决定向大家介绍它。&lt;/p&gt;
&lt;h2 id="Pictode主要功能演示"&gt;Pictode 主要功能演示&lt;/h2&gt;&lt;h3 id="图形绘制"&gt;图形绘制&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://img.way2solo.com/photo/1141326491/c38e342e-c279-4fa0-92a6-1d467f5b0ef0.png?imageView2/2/w/1920/q/100" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="选择/变换"&gt;选择/变换&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://img.way2solo.com/photo/1141326491/573ad62e-13c9-4aef-889f-cdac5270e1c9.png?imageView2/2/w/1920/q/100" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="层级移动"&gt;层级移动&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://img.way2solo.com/photo/1141326491/976b470c-4614-4a5e-b891-42c586264750.png?imageView2/2/w/1920/q/100" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="对齐/分布"&gt;对齐/分布&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://img.way2solo.com/photo/1141326491/2bce02fd-93a0-41d7-8518-c906030b9e82.png?imageView2/2/w/1920/q/100" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="组合/解除组合"&gt;组合/解除组合&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://img.way2solo.com/photo/1141326491/588ce896-728a-4417-b75c-351a1c4f3113.png?imageView2/2/w/1920/q/100" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="导出图片"&gt;导出图片&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://img.way2solo.com/photo/1141326491/29523853-60d9-4176-ac82-d2786e1dc311.png?imageView2/2/w/1920/q/100" title="" alt=""&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;温馨提示🔔：看图固然好，实际体验方知妙处！吾友，诚挚邀请前往&lt;a href="https://jessyan0913.github.io/pictode-playground/#/" rel="nofollow" target="_blank" title=""&gt;pictode&lt;/a&gt;一试身手，领略其中奥妙！ 🎨✨&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="Pictode能为你带来什么"&gt;Pictode 能为你带来什么&lt;/h2&gt;
&lt;p&gt;也许你已经在掘金上看到许多技术大咖分享如何实现画板或图片编辑器的方法。他们或许详细解释了编辑器的原理和代码实现，有些甚至直接使用原生 Canvas 构建编辑器。但你是否和我有相同的感受？&lt;/p&gt;

&lt;p&gt;我们既敬佩技术大咖，又感到自己阅读后除了感叹：“🐮🍺！” 外收获很少。原因在于我们无法将他们的代码应用到项目中。虽然阅读、点赞和收藏了这些文章，但仍感头脑空空，实际收获有限。&lt;/p&gt;

&lt;p&gt;把图形编辑器嵌入自己的项目，有时真麻烦。比如，编辑器用 React 构建，你的项目用 Vue；或者编辑器不够灵活。Pictode 就是你的救星，像🚀一样，解决这些问题，让你事半功倍。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;故吾决心，以&lt;code&gt;Pictode&lt;/code&gt;引领特异之经验。&lt;code&gt;Pictode&lt;/code&gt;独立于 UI 框架，展示不朽之图形编辑构建。其 API 举重若轻，依托威能之 Konva.js 库。故不论尔用 React，或 Vue，亦或他框架，以&lt;code&gt;Pictode&lt;/code&gt;，成本可微，缔造专有图形编辑器，无往不利。&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="DIY画板"&gt;DIY 画板&lt;/h2&gt;
&lt;p&gt;现在，让我们一起亲身体验&lt;code&gt;Pictode&lt;/code&gt;，并快速创建一个图形编辑器。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;放心食用：&lt;a href="https://codesandbox.io/p/sandbox/pictode-playground-7rm8zq" rel="nofollow" target="_blank" title=""&gt;DIY 画板源码&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="创建画板"&gt;创建画板&lt;/h3&gt;
&lt;p&gt;使用&lt;code&gt;Pictode&lt;/code&gt;创建画板只需要几个简单的步骤：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;安装&lt;code&gt;@pictode/core&lt;/code&gt;依赖包。该核心包负责管理舞台、图层、工具、插件，以及处理鼠标事件分发等功能。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @pictode/core
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;实例化&lt;code&gt;App&lt;/code&gt;对象。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@pictode/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;提供一个 DIV 容器，使用&lt;code&gt;app.mount(..)&lt;/code&gt;方法挂在画布。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@pictode/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvasRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLDivElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvasRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvasRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"canvasRef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/23a5766f146944d0bac308a33a82f508~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=740&amp;amp;h=683&amp;amp;s=8819&amp;amp;e=png&amp;amp;b=ffffff" title="" alt="image.png"&gt;&lt;/p&gt;

&lt;p&gt;当然，在这一步，画布仍然是空白的。接下来，我们将介绍如何添加绘图工具。&lt;/p&gt;
&lt;h3 id="绘图工具"&gt;绘图工具&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Pictode&lt;/code&gt;提供了一个基本的绘图工具包，其中包括了一些基于 Konva.js 的常用图形绘制工具。使用这些工具非常简单，只需几个步骤：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;安装&lt;code&gt;@pictode/tools&lt;/code&gt;依赖包。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @pictode/tools
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;实例化一个矩形工具。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RectTool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@pictode/tools&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RectTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gray&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cornerRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;使用&lt;code&gt;app.setTool(..)&lt;/code&gt;方法切换到矩形工具。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RectTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gray&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;cornerRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;在画布上通过鼠标开始绘制矩形。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/968ad6a12dd145eea1b0db6a516047af~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=756&amp;amp;h=687&amp;amp;s=103407&amp;amp;e=gif&amp;amp;f=158&amp;amp;b=fdfafe" title="" alt="Kapture 2023-09-26 at 22.12.08.gif"&gt;&lt;/p&gt;
&lt;h3 id="选中/变换"&gt;选中/变换&lt;/h3&gt;
&lt;p&gt;现在，让我们为图形编辑器添加选中、平移、旋转和缩放等功能。&lt;code&gt;Pictode&lt;/code&gt; 提供了名为 &lt;code&gt;@pictode/plugin-selector&lt;/code&gt; 的插件，它简化了这些操作。以下是集成插件的步骤：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;安装 &lt;code&gt;@pictode/plugin-selector&lt;/code&gt; 依赖包。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @pictode/plugin-selector
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;实例化 &lt;code&gt;selectorPlugin&lt;/code&gt; 插件。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SelectorPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@pictode/plugin-selector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectorPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SelectorPlugin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;使用 &lt;code&gt;app.use(selectorPlugin)&lt;/code&gt; 方法加载插件。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorPlugin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;通过 &lt;code&gt;鼠标点击&lt;/code&gt; 或 &lt;code&gt;app.select(...)&lt;/code&gt; 和 &lt;code&gt;app.cancelSelect(...)&lt;/code&gt; 方法来实现选中和取消选中图形的操作。同时，按下 &lt;code&gt;Shift&lt;/code&gt; 键可以实现多选和取消选择的功能。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/df40d21629cb4fdcbcaef71c6b7b50ab~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=662&amp;amp;h=662&amp;amp;s=476859&amp;amp;e=gif&amp;amp;f=304&amp;amp;b=fdfdfd" title="" alt="Kapture 2023-09-26 at 22.24.37.gif"&gt;&lt;/p&gt;
&lt;h4 id="选择工具"&gt;选择工具&lt;/h4&gt;
&lt;p&gt;插入 &lt;code&gt;selectorPlugin&lt;/code&gt; 后，你可能会观察到一个不太符合预期的行为：在绘制矩形时，蓝色框可能会叠加在矩形上，并且在移动矩形时，鼠标可能会继续绘制矩形。&lt;/p&gt;

&lt;p&gt;这是因为 &lt;code&gt;selectorPlugin&lt;/code&gt; 默认开启了框选功能，所以这时的 &lt;code&gt;pictode&lt;/code&gt; 无法判断是要进行绘制操作还是框选操作。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;解决方法很简单&lt;/strong&gt;：使用工具时禁用 &lt;code&gt;selectorPlugin&lt;/code&gt;，取消工具选择时重新启用。通过 &lt;code&gt;app.setTool(tool)&lt;/code&gt; 启用工具时，禁用 &lt;code&gt;selectorPlugin&lt;/code&gt;；通过 &lt;code&gt;app.setTool(null)&lt;/code&gt; 取消工具选择时，重新启用 &lt;code&gt;selectorPlugin&lt;/code&gt;，提升用户体验。&lt;/p&gt;

&lt;p&gt;我明白，这种方式可能不是每个人都喜欢的。因此，&lt;code&gt;@pictode/tools&lt;/code&gt; 提供了专门为 &lt;code&gt;Selector&lt;/code&gt; 预留的工具 - &lt;code&gt;SelectTool&lt;/code&gt;，包括 &lt;code&gt;onActive&lt;/code&gt; 和 &lt;code&gt;onInactive&lt;/code&gt; hooks：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;onActive&lt;/code&gt;&lt;/strong&gt;：在通过 &lt;code&gt;app.setTool()&lt;/code&gt; 设置工具时触发。&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;onInactive&lt;/code&gt;&lt;/strong&gt;：当其他工具替代当前工具时触发。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;使用&lt;code&gt;SelectTool&lt;/code&gt;会很自然的通过工具切换来解决选择器和绘图工具干扰问题：&lt;/p&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectTool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SelectTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;onActive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;selectorPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;onInactive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;selectorPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rectTool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RectTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gray&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cornerRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;onActive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cancelSelect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectTool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再配合 UI 来触发工具切换：&lt;/p&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"canvasRef"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"tools"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;user13=&lt;/span&gt;&lt;span class="s"&gt;"app.setTool(selectTool)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;选择&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;user14=&lt;/span&gt;&lt;span class="s"&gt;"app.setTool(rectTool)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;矩形&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/61189204a2ed4c6fa386a2bacdd3cb42~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1228&amp;amp;h=1322&amp;amp;s=1373617&amp;amp;e=gif&amp;amp;f=445&amp;amp;b=fdfdfd" title="" alt="Kapture 2023-10-01 at 23.36.29.gif"&gt;&lt;/p&gt;
&lt;h3 id="撤销/重做"&gt;撤销/重做&lt;/h3&gt;
&lt;p&gt;操作记录功能是一个重要的编辑器功能，&lt;code&gt;Pictode&lt;/code&gt; 当然也支持。名为 &lt;code&gt;@pictode/plugin-history&lt;/code&gt; 的插件，它可以为 &lt;code&gt;Pictode&lt;/code&gt; 添加撤销和重做的能力。下面是集成 &lt;code&gt;plugin-history&lt;/code&gt; 插件的步骤：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;安装 &lt;code&gt;@pictode/plugin-history&lt;/code&gt; 依赖包。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @pictode/plugin-selector
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;实例化 &lt;code&gt;historyPlugin&lt;/code&gt; 插件。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HistoryPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@pictode/plugin-history&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;historyPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;HistoryPlugin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;使用 &lt;code&gt;app.use(historyPlugin)&lt;/code&gt; 方法加载插件。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;historyPlugin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;之后，你可以通过 &lt;code&gt;app.undo()&lt;/code&gt; 和 &lt;code&gt;app.redo()&lt;/code&gt; 方法来实现撤销和重做的功能。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"canvasRef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;user19=&lt;/span&gt;&lt;span class="s"&gt;"app.undo()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;撤销&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;user20=&lt;/span&gt;&lt;span class="s"&gt;"app.redo()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;重做&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c432d97866c14f3a93e6a5b6313cee6d~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=662&amp;amp;h=708&amp;amp;s=304504&amp;amp;e=gif&amp;amp;f=310&amp;amp;b=fdfdfd" title="" alt="Kapture 2023-09-26 at 22.31.08.gif"&gt;&lt;/p&gt;

&lt;p&gt;这样，用户就可以轻松地撤销和重做他们的操作，提高了编辑器的灵活性和易用性。&lt;/p&gt;
&lt;h3 id="对齐/分布"&gt;对齐/分布&lt;/h3&gt;
&lt;p&gt;编辑图形时，需要确保图形之间的对齐和分布。&lt;code&gt;Pictode&lt;/code&gt; 提供了 &lt;code&gt;@pictode/plugin-alignment&lt;/code&gt; 插件，用于实现这些功能。使用以下步骤集成插件：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;安装 &lt;code&gt;@pictode/plugin-alignment&lt;/code&gt; 依赖包。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @pictode/plugin-selector
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;实例化 &lt;code&gt;alignmentPlugin&lt;/code&gt; 插件。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AlignmentPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@pictode/plugin-alignment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alignmentPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AlignmentPlugin&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;使用 &lt;code&gt;app.use(alignmentPlugin)&lt;/code&gt; 方法加载插件。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alignmentPlugin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;之后，你可以使用一系列方法来实现对齐操作，包括 &lt;code&gt;app.alignTop&lt;/code&gt;、&lt;code&gt;app.alignRight&lt;/code&gt;、&lt;code&gt;app.alignBottom&lt;/code&gt;、&lt;code&gt;app.alignLeft&lt;/code&gt;、&lt;code&gt;app.alignCenterX&lt;/code&gt;、&lt;code&gt;app.alignCenterY&lt;/code&gt; 等。&lt;/li&gt;
&lt;li&gt;此外，你还可以使用 &lt;code&gt;app.distributeX&lt;/code&gt; 和 &lt;code&gt;app.distributeY&lt;/code&gt; 方法来实现水平均分和垂直均分功能。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c6807f9b648d404ebf0e099218d6ca04~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=662&amp;amp;h=708&amp;amp;s=653331&amp;amp;e=gif&amp;amp;f=265&amp;amp;b=fdfdfd" title="" alt="Kapture 2023-09-26 at 22.38.36.gif"&gt;&lt;/p&gt;

&lt;p&gt;这些功能能够帮助你更方便地编辑和排列图形，提高了编辑效率。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;目前 &lt;code&gt;@pictode/*&lt;/code&gt; 相关的依赖包都是预发布版本&lt;/strong&gt;，因为我正在进行自测和 BUG 修复中 😅😅😅&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="小结"&gt;小结&lt;/h3&gt;
&lt;p&gt;通过上面的示例，&lt;strong&gt;你是否感受到了基于 Pictode 开发图形编辑器的简单和便捷&lt;/strong&gt;？不论你使用的是 Vue、React 还是原生开发，都可以轻松集成 Pictode 到你的项目中，&lt;strong&gt;使定制和扩展图形编辑器变得更加灵活和容易&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="架构与技术选型"&gt;架构与技术选型&lt;/h2&gt;
&lt;p&gt;Pictode 旨在构建通用的图形编辑器框架。因此，核心库选择了&lt;code&gt;konva.js&lt;/code&gt;作为核心技术。&lt;/p&gt;

&lt;p&gt;最初考虑了&lt;code&gt;fabric.js&lt;/code&gt;，但其代码结构混乱，还使用了过时的 JS 语法。此外，该库的下一个主要版本一直未发布，存在许多问题，如对象分组和 Transformer 功能。&lt;/p&gt;

&lt;p&gt;相比之下，&lt;code&gt;konva.js&lt;/code&gt;代码清晰易懂，支持 TS，社区活跃，并不断更新和改进。这让我最终选择&lt;code&gt;konva.js&lt;/code&gt;为 Pictode 的核心库，为编辑器提供了稳定的基础，以构建出色的图形编辑器框架。&lt;/p&gt;
&lt;h3 id="架构设计"&gt;架构设计&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Pictode 主要由两部分组成，一部分是编辑器的核心库与 UI 框架无关，另一部分是基于 Vue3 的使用 Pictode 核心库搭建的画板工具。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;经过上面的 DIY 编辑器的过程，相信你也一定能体会到通过&lt;code&gt;Pictode&lt;/code&gt;DIY 图形编辑器非常轻松和简单。&lt;code&gt;Pictode&lt;/code&gt;采用关注点分离的设计原则，使用事件驱动的方式来驱动图形编辑器的数据交互，提供了灵活的插件和图形工具机制，方便扩展和定制编辑器的能力。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3eedc1ccb127449591fcfd214dca028b~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1460&amp;amp;h=1296&amp;amp;s=105851&amp;amp;e=png&amp;amp;a=1&amp;amp;b=ffffff" title="" alt="Pictode-Wed Sep 27 2023 10_30_56 GMT+0800 (中国标准时间).png"&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⬆️这个图是用 Pictode 绘制的，虽然简陋，但能证明 Pictode 具备绘图和导出图片的能力。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="项目规划"&gt;项目规划&lt;/h2&gt;&lt;h3 id="v1.0.0"&gt;v1.0.0&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/62864bab4328465faa3cb80614aa4815~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1166&amp;amp;h=2484&amp;amp;s=416468&amp;amp;e=png&amp;amp;b=141414" title="" alt="Pictode v1.0.0规划.jpg"&gt;&lt;/p&gt;
&lt;h3 id="v2.0.0"&gt;v2.0.0&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/841e35a0b64c43e9bac432a3eccb6835~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=784&amp;amp;h=1362&amp;amp;s=113967&amp;amp;e=png&amp;amp;b=141414" title="" alt="Pictode v2.0.0规划.jpg"&gt;&lt;/p&gt;
&lt;h3 id="v3.0.0"&gt;v3.0.0&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3e6842ceddf14ac7933df758711d79af~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=716&amp;amp;h=504&amp;amp;s=50059&amp;amp;e=png&amp;amp;b=151515" title="" alt="Pictode v3.0.0规划.jpg"&gt;&lt;/p&gt;
&lt;h2 id="寻求开源之路"&gt;寻求开源之路&lt;/h2&gt;
&lt;p&gt;关于是否开源的问题，答案是：&lt;strong&gt;肯定开源&lt;/strong&gt;。虽然我个人没有太多的开源经验，但我非常愿意将 &lt;strong&gt;Pictode&lt;/strong&gt; 开源，以便更好地服务大家。&lt;/p&gt;

&lt;p&gt;我正在积极准备将项目开源，但为了确保项目的开源能够既有利于开发者，又能为用户提供便捷的使用体验，还需要一些时间和努力。具体来说，我需要时间来选择适合项目的开源许可证，规范问题追踪系统和讨论区，并确保项目能够持续发展。&lt;/p&gt;

&lt;p&gt;如果你是一位具有开源经验的掘友，并且愿意分享你的经验，帮助我将 &lt;strong&gt;Pictode&lt;/strong&gt; 开源，那么请不要犹豫，随时私信我🫰。&lt;/p&gt;

&lt;p&gt;感谢你的慷慨支持和分享精神！&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;如果你希望获取 &lt;strong&gt;Pictode&lt;/strong&gt; 的源代码，或者关注项目的开源进展，请务必关注我的&lt;a href="https://juejin.cn/user/3562073405789294" rel="nofollow" target="_blank" title=""&gt;掘金账号&lt;/a&gt;，这样你将能第一时间获得相关信息。感谢你的关注和支持！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="最后"&gt;最后&lt;/h2&gt;
&lt;p&gt;如果你觉得 &lt;strong&gt;Pictode&lt;/strong&gt; 很有趣，请不吝点赞、收藏、以及关注，你的支持对我来说意义重大，也是我坚持下去的动力。&lt;/p&gt;

&lt;p&gt;如果你的项目需要图形编辑类的功能，而且想要使用 &lt;strong&gt;Pictode&lt;/strong&gt;，请随时私信我，我会尽力提供支持。&lt;/p&gt;

&lt;p&gt;如果你有兴趣一起参与 &lt;strong&gt;Pictode&lt;/strong&gt; 的维护和发展，欢迎加入我们的学习交流群。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://img.way2solo.com/photo/1141326491/158e1ce6-0e39-4b19-9a5d-2f2148bcb1c1.png?imageView2/2/w/1920/q/100" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>1141326491</author>
      <pubDate>Sat, 07 Oct 2023 14:15:51 +0800</pubDate>
      <link>https://w2solo.com/topics/4175</link>
      <guid>https://w2solo.com/topics/4175</guid>
    </item>
  </channel>
</rss>
