先说结论:经细致调研Canvas-editor完全可以在vue3中使用(虽然不是开箱即用版本),其内部为typeScript的写法,校之市面上其他editor有较为灵活的选择,如果你苦于寻找一款适合你项目的某个特殊功能的editor又不知道是否合适时,可以使用一下这个,绝对会是一个好的选择
-
关于canvas-editor
-
关于canvas-editor的文档
如您所见,文档中的demo还是不错的,而这个文档的存在价值好比鸡肋,主打体现一个“有”。
文档中所有的函数几乎都没有注释,参数基本全靠阅读源码,在开发过程中我们只需要-------------打开官网 ----》 找到github地址 ----》 然后关闭官网就可以了。
-
关于canvas-editor的使用
不需要npm 不需要npm 不需要npm下载canvas-editor 我们只要下载源码包就可以了
该editor编辑器主要使用canvas进行渲染,运行起来还是不错的
- 下载源码后,最后将源码跑起来就能得到官网中所示的demo
- 源码中我们只需要取用关键的部分即可
然后对关键部分中不合适的再删除掉
- 在自己的项目中新建组件Canvas-editor 将整个editor内的文件都复制进去,而后新建index.vue将以下部分html放到template中
<div class="menu" editor-component="menu"> <div class="menu-item"> <div class="menu-item__undo"> <i></i> </div> <div class="menu-item__redo"> <i></i> </div> <div class="menu-item__painter" title="格式刷(双击可连续使用)"> <i></i> </div> <div class="menu-item__format" title="清除格式"> <i></i> </div> </div> <div class="menu-divider"></div> <div class="menu-item"> <div class="menu-item__font"> <span class="select" title="字体">微软雅黑</span> <div class="options"> <ul> <li data-family="Microsoft YaHei" style="font-family: "Microsoft YaHei"">微软雅黑</li> <li data-family="华文宋体" style="font-family: "华文宋体"">华文宋体</li> <li data-family="华文黑体" style="font-family: "华文黑体"">华文黑体</li> <li data-family="华文仿宋" style="font-family: "华文仿宋"">华文仿宋</li> <li data-family="华文楷体" style="font-family: "华文楷体"">华文楷体</li> <li data-family="华文琥珀" style="font-family: "华文琥珀"">华文琥珀</li> <li data-family="华文楷体" style="font-family: "华文楷体"">华文楷体</li> <li data-family="华文隶书" style="font-family: "华文隶书"">华文隶书</li> <li data-family="华文新魏" style="font-family: "华文新魏"">华文新魏</li> <li data-family="华文行楷" style="font-family: "华文行楷"">华文行楷</li> <li data-family="华文中宋" style="font-family: "华文中宋"">华文中宋</li> <li data-family="华文彩云" style="font-family: "华文彩云"">华文彩云</li> <li data-family="Arial" style="font-family: "Arial"">Arial</li> <li data-family="Segoe UI" style="font-family: "Segoe UI"">Segoe UI</li> <li data-family="Ink Free" style="font-family: "Ink Free"">Ink Free</li> <li data-family="Fantasy" style="font-family: "Fantasy"">Fantasy</li> </ul> </div> </div> <div class="menu-item__size"> <span class="select" title="字体">小四</span> <div class="options"> <ul> <li data-size="56">初号</li> <li data-size="48">小初</li> <li data-size="34">一号</li> <li data-size="32">小一</li> <li data-size="29">二号</li> <li data-size="24">小二</li> <li data-size="21">三号</li> <li data-size="20">小三</li> <li data-size="18">四号</li> <li data-size="16">小四</li> <li data-size="14">五号</li> <li data-size="12">小五</li> <li data-size="10">六号</li> <li data-size="8">小六</li> <li data-size="7">七号</li> <li data-size="6">八号</li> </ul> </div> </div> <div class="menu-item__size-add"> <i></i> </div> <div class="menu-item__size-minus"> <i></i> </div> <div class="menu-item__bold"> <i></i> </div> <div class="menu-item__italic"> <i></i> </div> <div class="menu-item__underline"> <i></i> <span class="select"></span> <div class="options"> <ul> <li data-decoration-style="solid"> <i></i> </li> <li data-decoration-style="double"> <i></i> </li> <li data-decoration-style="dashed"> <i></i> </li> <li data-decoration-style="dotted"> <i></i> </li> <li data-decoration-style="wavy"> <i></i> </li> </ul> </div> </div> <div class="menu-item__strikeout" title="删除线(Ctrl+Shift+X)"> <i></i> </div> <div class="menu-item__superscript"> <i></i> </div> <div class="menu-item__subscript"> <i></i> </div> <div class="menu-item__color" title="字体颜色"> <i></i> <span></span> <input type="color" id="color" /> </div> <div class="menu-item__highlight" title="高亮"> <i></i> <span></span> <input type="color" id="highlight" /> </div> </div> <div class="menu-divider"></div> <div class="menu-item"> <div class="menu-item__title"> <i></i> <span class="select" title="切换标题">正文</span> <div class="options" style="width: 120px"> <ul> <li style="font-size: 16px">正文</li> <li data-level="first" style="font-size: 26px">标题1</li> <li data-level="second" style="font-size: 24px">标题2</li> <li data-level="third" style="font-size: 22px">标题3</li> <li data-level="fourth" style="font-size: 20px">标题4</li> <li data-level="fifth" style="font-size: 18px">标题5</li> <li data-level="sixth" style="font-size: 16px">标题6</li> </ul> </div> </div> <div class="menu-item__left"> <i></i> </div> <div class="menu-item__center"> <i></i> </div> <div class="menu-item__right"> <i></i> </div> <div class="menu-item__alignment"> <i></i> </div> <div class="menu-item__justify"> <i></i> </div> <div class="menu-item__row-margin"> <i title="行间距"></i> <div class="options"> <ul> <li data-rowmargin="0.5">0.5</li> <li data-rowmargin="1">1</li> <li data-rowmargin="1.25">1.25</li> <li data-rowmargin="1.5">1.5</li> <li data-rowmargin="1.75">1.75</li> <li data-rowmargin="2">2</li> <li data-rowmargin="2.5">2.5</li> <li data-rowmargin="3">3</li> </ul> </div> </div> <div class="menu-item__list"> <i></i> <div class="options" style="width: 160px"> <ul> <li> <label>取消列表</label> </li> <li data-list-type="ol" data-list-style="decimal"> <label>有序列表:</label> <ol> <li>________</li> </ol> </li> <li data-list-type="ul" data-list-style="checkbox"> <label>复选框列表:</label> <ul style="list-style-type: "☑️ ""> <li>________</li> </ul> </li> <li data-list-type="ul" data-list-style="disc"> <label>实心圆点列表:</label> <ul style="list-style-type: disc"> <li>________</li> </ul> </li> <li data-list-type="ul" data-list-style="circle"> <label>空心圆点列表:</label> <ul style="list-style-type: circle"> <li>________</li> </ul> </li> <li data-list-type="ul" data-list-style="square"> <label>空心方块列表:</label> <ul style="list-style-type: "☐ ""> <li>________</li> </ul> </li> </ul> </div> </div> </div> <div class="menu-divider"></div> <div class="menu-item"> <div class="menu-item__table"> <i title="表格"></i> </div> <div class="menu-item__table__collapse"> <div class="table-close">×</div> <div class="table-title"> <span class="table-select">插入</span> <span>表格</span> </div> <div class="table-panel"></div> </div> <div class="menu-item__image"> <i title="图片"></i> <input type="file" id="image" accept=".png, .jpg, .jpeg, .svg, .gif" /> </div> <div class="menu-item__hyperlink"> <i title="超链接"></i> </div> <div class="menu-item__separator"> <i title="分割线"></i> <div class="options"> <ul> <li data-separator="0,0"> <i></i> </li> <li data-separator="1,1"> <i></i> </li> <li data-separator="3,1"> <i></i> </li> <li data-separator="4,4"> <i></i> </li> <li data-separator="7,3,3,3"> <i></i> </li> <li data-separator="6,2,2,2,2,2"> <i></i> </li> </ul> </div> </div> <div class="menu-item__watermark"> <i title="水印(添加、删除)"></i> <div class="options"> <ul> <li data-menu="add">添加水印</li> <li data-menu="delete">删除水印</li> </ul> </div> </div> <div class="menu-item__codeblock" title="代码块"> <i></i> </div> <div class="menu-item__page-break" title="分页符"> <i></i> </div> <div class="menu-item__control"> <i title="控件"></i> <div class="options"> <ul> <li data-control="text">文本</li> <li data-control="number">数值</li> <li data-control="select">列举</li> <li data-control="date">日期</li> <li data-control="checkbox">复选框</li> <li data-control="radio">单选框</li> </ul> </div> </div> <div class="menu-item__checkbox" title="复选框"> <i></i> </div> <div class="menu-item__radio" title="单选框"> <i></i> </div> <div class="menu-item__latex" title="LateX"> <i></i> </div> <div class="menu-item__date"> <i title="日期"></i> <div class="options"> <ul> <li data-format="yyyy-MM-dd"></li> <li data-format="yyyy-MM-dd hh:mm:ss"></li> </ul> </div> </div> <div class="menu-item__block" title="内容块"> <i></i> </div> </div> <div class="menu-divider"></div> <div class="menu-item"> <div class="menu-item__search" data-menu="search"> <i></i> </div> <div class="menu-item__search__collapse" data-menu="search"> <div class="menu-item__search__collapse__search"> <input type="text" /> <label class="search-result"></label> <div class="arrow-left"> <i></i> </div> <div class="arrow-right"> <i></i> </div> <span>×</span> </div> <div class="menu-item__search__collapse__replace"> <input type="text" /> <button>替换</button> </div> </div> <div class="menu-item__print" data-menu="print"> <i></i> </div> </div> </div> <div class="catalog" editor-component="catalog" v-show="props.options.isUseCatalog"> <div class="catalog__header"> <span>目录</span> <div class="catalog__header__close"> <i></i> </div> </div> <div class="catalog__main"></div> </div> <div class="editor"></div> <div class="comment" editor-component="comment"></div> <div class="footer" editor-component="footer" v-show="props.options.isUseFooter"> <div> <div class="catalog-mode" title="目录"> <i></i> </div> <div class="page-mode"> <i title="页面模式(分页、连页)"></i> <div class="options"> <ul> <li data-page-mode="paging" class="active">分页</li> <li data-page-mode="continuity">连页</li> </ul> </div> </div> <span> 可见页码: <span class="page-no-list">1</span> </span> <span> 页面: <span class="page-no">1</span> / <span class="page-size">1</span> </span> <span> 字数: <span class="word-count">0</span> </span> <span> 行: <span class="row-no">0</span> </span> <span> 列: <span class="col-no">0</span> </span> </div> <div class="editor-mode" title="编辑模式(编辑、清洁、只读、表单、设计)">编辑模式</div> <div> <div class="page-scale-minus" title="缩小(Ctrl+-)"> <i></i> </div> <span class="page-scale-percentage" title="显示比例(点击可复原Ctrl+0)">100%</span> <div class="page-scale-add" title="放大(Ctrl+=)"> <i></i> </div> <div class="paper-size"> <i title="纸张类型"></i> <div class="options"> <ul> <li data-paper-size="794*1123" class="active">A4</li> <li data-paper-size="1593*2251">A2</li> <li data-paper-size="1125*1593">A3</li> <li data-paper-size="565*796">A5</li> <li data-paper-size="412*488">5号信封</li> <li data-paper-size="450*866">6号信封</li> <li data-paper-size="609*862">7号信封</li> <li data-paper-size="862*1221">9号信封</li> <li data-paper-size="813*1266">法律用纸</li> <li data-paper-size="813*1054">信纸</li> </ul> </div> </div> <div class="paper-direction"> <i title="纸张方向"></i> <div class="options"> <ul> <li data-paper-direction="vertical" class="active">纵向</li> <li data-paper-direction="horizontal">横向</li> </ul> </div> </div> <div class="paper-margin" title="页边距"> <i></i> </div> <div class="fullscreen" title="全屏显示"> <i></i> </div> <div class="editor-option" title="编辑器设置"> <i></i> </div> </div> </div>
-
然后将组件script搭建起来,调用init方法传入基本配置项。解决掉相关的引用报错就可以使用了
const options = { // 获取 CSS 变量值 background: { color: getComputedStyle(document.documentElement).getPropertyValue("--el-bg-color").trim(), }, cursor: { color: "#fff", }, defaultColor: "#fff", paperDirection: "vertical", pageMode: "continuity", margins: [0, 21, 0, 21], searchMatchColor: "#fff", //搜索高亮颜色 table: { defaultBorderColor: "#374352" }, isReadonly: false, // 是否是只读模式 isUseCatalog: false, //是否使用目录 isUseComment: false, //是否使用日志 isUseFooter: false, // 是否使用底部工具栏 } const initPage = () => { nextTick(() => { const { offsetWidth: width, offsetHeight: height } = document.querySelector(".canvas-editor"); window.instance = Init(".canvas-editor", { ....options, width: width, height: height }); }); };
以上,最后祝各位使用顺遂!!!
-
关于自己项目中使用最后的问题解决及优化
1. 因该组件开始使用是有i诸多不适配的地方,故做了许多适配,如底板宽度,颜色,自适应等
2. 组件内将只读模式变为由父组件传入,在options提供isReadonly判断 底部栏和顶部栏都做了灵活使用isUseComment(签注),isUseFooter(底部栏),isUseCatalog(目录),其内部由原生事件做的事件绑定,已经针对做了错误处理
3. 新增pageMode: "continuity",时依旧能进行水印的功能
4. 新增设置disabled时enter按钮触发的bug问题
*** 在自己项目中做了许多小的修改和优化,各位如果需要有使用的话可自取 ***
https://gitee.com/cheng-nannan/gantt-fly.git
注: 数据中有disabled属性是控制当前行段是否可编辑的属性