赞
踩
canves 绘图的运用是前端必知必会的基础,但是canves 本身并不好用,而fabric.js是基于canves的一个绘图框架库,用起来可比canves友好多了!接下来带你看看案例和初识fabric.js~
编辑前:
编辑中:
主要实现H5 移动端简单的图片的可视化编辑、预览、下载等功能。
目前仅实现以上的功能,后续在继续完善更新~~
editor.vue:
<template> <el-container > <el-header > <el-menu style="background: #6A60E3" mode="horizontal" > <div style="width: 400px; float: left;height:70px;color: #fff; background: #5951B6;line-height: 70px"> <h1 style="text-align: center">{{ templatesTitle }}</h1> </div> <el-form inline="inline" style="float: right; width: 1000px" > <el-button class="el-icon-plus btn_style" style="width: 140px" @click="addTextHandle('textbox', 'add')" > 添加文本框 </el-button> <el-button class="el-icon-plus btn_style" @click="imgDraw" > <input type="file" accept="image/*" style="display:none" id="uploadfile" @change="uploadFile" /> 上传图片 </el-button> <el-button class="el-icon-edit btn_style" @click="initD" > 绘 制 </el-button> <el-button class="btn-delete btn_style el-icon-delete" @click="deleteText" > 删除控件 </el-button> </el-form> </el-menu> </el-header> <el-container> <el-aside :width="isCollapsed ? '30px' : '300px'"> <div class="text-edit"> <div @click="closeSetting" class="title-setting" :tipTitle="isCollapsed ? '展开设置' : '收起设置'" > <span class="text-setting">{{ title }}</span> <i :class="isCollapsed ? 'el-icon-s-unfold' : 'el-icon-close'"/> </div> <el-form ref="form" > <el-form-item label="文本内容:"> <div id="textBox" style="width: 100% "> <el-input type="textarea" @input="changeText" @focus="changeText" id="in" ref="in" v-model="msg" ></el-input> </div> </el-form-item> <el-form-item label="字体:" label-width="82px"> <el-select v-model="fontFamilies.value" placeholder="请选择字体" @change="changeFontFamily"> <el-option v-for="item in fontFamilies" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> <el-form-item label="字体颜色:" > <el-select v-model="fontColor.value" placeholder="请选择字体颜色" @change="changeFontColor" > <el-option v-for="item in fontColor" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> <el-form-item label="字体粗细:" > <el-select v-model="fontWeight.value" placeholder="请选择字体粗细" @change="changefontWeight" > <el-option v-for="item in fontWeight" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> <el-form-item label="字体风格:" > <el-select v-model="fontStyle.value" placeholder="请选择字体风格" @change="changeFontStyle"> <el-option v-for="item in fontStyle" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> <el-form-item label="字体大小:" > <el-select v-model="fontSizes.value" placeholder="选择字体大小" @change="changeFontSize"> <el-option v-for="item in fontSizes" :key="item.value" :label="item.label" :value="item.value"> </el-option> </el-select> </el-form-item> <el-form-item label="对齐方式:" > <el-select v-model="textAlign.value" @change="changeTextAlign" placeholder="选择对齐方式"> <el-option v-for="item in textAlign" :key="item.value" :label="item.label" :value="item.value" ></el-option> </el-select> </el-form-item> <el-form-item label="背景颜色:" > <el-color-picker class="color-picker" v-model="bgcolor" circle size="small" show-alpha :predefine="predefineColors" @change="changeBgColor" color-format="hex" ></el-color-picker> </el-form-item> <el-form-item> <!-- <ul class="template-edit" id="template-edit" @click="chooseTemplate"> <li><img src="@/assets/logo.png" alt="" id="bg1" style="width: 100px;height: 50px" /></li> <li><img src="@/assets/logo.png" alt="" id="bg2" style="width: 100px;height: 50px" /></li> <li><img src="@/assets/logo.png" alt="" id="bg3" style="width: 100px;height: 50px" /></li> </ul>--> </el-form-item> </el-form> </div> </el-aside> <el-main style="height: 1040px" > <div class="content-show"> <div class="canvas"> <canvas ref="canvas" id="editorCanvas"></canvas> </div> </div> <el-form class="handleSave"> <el-button type="primary" class="btn-save" @click="downLoadImage1">预览图片</el-button> <el-button type="primary" class="btn-download" @click="downLoad">下载图片</el-button> <el-form-item inline="inline" class="btn-zoom" style="margin: 10px 0px"> <i class="el-icon-caret-left" @click="zoomIt(0.8)"></i> <span> {{ zoomCounter }} % </span> <i class="el-icon-caret-right" @click="zoomIt(1.2)"></i> </el-form-item> <el-button type="danger" class="btn-reset" @click="resetCanvas">重 置</el-button> </el-form> </el-main> <el-aside :width="isCollapsed ? '30px' : '375px'"> <div @click="closeSetting" class="title-setting" :tipTitle="isCollapsed ? '展开设置' : '收起设置'" > <span class="text-setting">{{ showTitle }}</span> <i :class="isCollapsed ? 'el-icon-s-unfold' : 'el-icon-close'"/> </div> <img :src="imageBase64" alt=""> </el-aside> </el-container> </el-container> </template> <script> import { fontFamilies, fontSizes, fontColor, fontStyle, fontWeight, backgroundColor, textAlign, } from "@/utils/fontData"; import { fabric } from "fabric"; let editorCanvas = ""; fabric.Object.prototype.set({ cornerStrokeColor: "#66b0ef", cornerColor: "#60abec", cornerStyle: "rectangele", cornerSize: 8, borderScaleFactor: 2, transparentCorners: false, borderColor: "#61abe8", }); export default { name: "Editor", data() { return { isHide: true, checkAll: false, isChecked:false, isIndeterminate: true, fontFamilies, fontSizes, fontColor, fontStyle, fontWeight, textAlign, backgroundColor, predefineColors: ["#ffffff", "#FF0000", "#000000","#FFF800","#00FF0A","#FD00FF","#0095FF"], checked: true, // 模板图片保存数组 templateImgs: [], zoomCounter: 100, tipTitle: "", imageBase64: "", isCollapsed: false, backColor: "#eec5c5", backGroundStatus: false, bgcolor: "#ff0000", itemWidth: "230px", done: false, // 文本控件属性 textStyleData: { type: "editText", text: "双击编辑文字", top: 50, left: 50, width: 100, opacity: 1, stroke: "#ffffff", strokeWidth: 0, textAlign: "left", lineHeight: 1, charSpacing: 1, fontFamily: "hyzktjjkt", fontSize: 40, fontWeight: "normal", fontStyle: "normal", fill: "#000000", textBackgroundColor: "rgba(0,0,0,0)", selectable: true, }, isOpen: false, isMove: false, src: "", msg: "", canvas: null, templatesTitle: "H5 可视化编辑", title: "文本设置", showTitle:"100% 预览", templateData: {}, mouseFrom: {}, mouseTo: {}, moveCount: 1, }; }, mounted() { this.initeditorCanvas(); }, methods: { downLoadImage1() { this.done = true let base64URl = editorCanvas.toDataURL({ formart: 'png', multiplier: 1 }) this.imageBase64 = base64URl this.done = false }, saveTemplates() { console.log("你点击了模板保存"); let base64URl = editorCanvas.toDataURL({ formart: "jpg", multiplier: 1, }); }, addTemplates() { console.log("添加模板"); }, initD() { // 监听鼠标按下 const obj = editorCanvas.getActiveObject(); editorCanvas.on("mouse:down", (options) => { // 记录当前鼠标的起点坐标 if(!obj) { this.mouseFrom.x = options.e.clientX - editorCanvas._offset.left; this.mouseFrom.y = options.e.clientY - editorCanvas._offset.top; } }); // 监听鼠标移动 editorCanvas.on("mouse:move", (options) => { // 记录当前鼠标移动终点坐标 if (!obj) { this.mouseTo.x = options.e.clientX - editorCanvas._offset.left this.mouseTo.y = options.e.clientY - editorCanvas._offset.top this.drawRect(); } }); editorCanvas.on("mouse:up", (options) => { if (!obj) { this.mouseFrom.x = options.e.clientX - editorCanvas._offset.left; this.mouseFrom.y = options.e.clientY - editorCanvas._offset.top; this.doDrawing = false; this.canvasObject = null; this.mouseFrom = {}; this.mouseTo = {} } }); editorCanvas.on("selection:created",(option) => { if (option) { this.doDrawing = false; } }) }, getTransformedPosX(x) { let zoom = Number(editorCanvas.getZoom()) return (x - editorCanvas.viewportTransform[4]) / zoom; }, getTransformedPosY(y) { let zoom = Number(editorCanvas.getZoom()) return (y - editorCanvas.viewportTransform[5]) / zoom; }, // 绘制矩形 drawRect() { // 计算矩形长宽 let left = this.getTransformedPosX(this.mouseFrom.x); let top = this.getTransformedPosY(this.mouseFrom.y); let width = this.mouseTo.x - this.mouseFrom.x; let height = this.mouseTo.y - this.mouseFrom.y; const canvasObject = new fabric.Rect({ left: left, top: top, width: width, height: height, fill: "#d70202", strokeWidth: 2, }); editorCanvas.add(canvasObject); }, // 初始化模板编辑画布 initeditorCanvas() { editorCanvas = new fabric.Canvas("editorCanvas", { devicePixelRatio: true, width: "375", height: "667", originX: "center", originY: "center", backgroundColor: "#ffffff", transparentCorners: false, }); editorCanvas.preserveObjectStacking = true; }, // 收起文本设置 closeSetting() { this.isCollapsed = !this.isCollapsed; }, // 载入图片 imgDraw() { document.getElementById("uploadfile").click(); }, uploadFile(e) { editorCanvas.isDrawingMode = false; let file = e.target.files[0]; let reader = new FileReader(); reader.onload = (e) => { let data = e.target.result; fabric.Image.fromURL(data, (img) => { editorCanvas.add(img).renderAll(); }); }; reader.readAsDataURL(file); e.target.value = ""; }, // 下载图片 downLoad() { this.done = true; const dataURL = editorCanvas.toDataURL({ width: editorCanvas.width, height: editorCanvas.height, left: 0, top: 0, format: "png", }); const link = document.createElement("a"); link.download = "图片.png"; link.href = dataURL; document.body.appendChild(link); link.click(); document.body.removeChild(link); }, // 清空画布 resetCanvas() { let children = editorCanvas.getObjects(); if (children.length > 0) { editorCanvas.remove(...children); } editorCanvas.setBackgroundColor("#fff"); }, // 缩放 zoomIt(factor) { let zoomCounter = this.zoomCounter; let cWidth = editorCanvas.width; let cHeight = editorCanvas.height; /* 同步缩小 */ if (factor < 1 && zoomCounter > 0) { this.zoomCounter -= 20; editorCanvas.setWidth(cWidth * factor); editorCanvas.setHeight(cHeight * factor); const objects = editorCanvas.getObjects(); for (let i in objects) { let scaleX = objects[i].scaleX; let scaleY = objects[i].scaleY; let left = objects[i].left; let top = objects[i].top; let tempScaleX = scaleX * factor; let tempScaleY = scaleY * factor; let tempLeft = left * factor; let tempTop = top * factor; objects[i].scaleX = tempScaleX; objects[i].scaleY = tempScaleY; objects[i].left = tempLeft; objects[i].top = tempTop; objects[i].setCoords(); let zoomPoint = new fabric.Point( editorCanvas.width / 2, editorCanvas.height / 2 ); editorCanvas.zoomToPoint(zoomPoint, factor); editorCanvas.renderAll(); editorCanvas.calcOffset(); } } /* 同步放大 */ if (factor > 1 && zoomCounter < 100) { this.zoomCounter += 20; editorCanvas.setWidth(cWidth * factor); editorCanvas.setHeight(cHeight * factor); const objects = editorCanvas.getObjects(); for (let i in objects) { let scaleX = objects[i].scaleX; let scaleY = objects[i].scaleY; let left = objects[i].left; let top = objects[i].top; let tempScaleX = scaleX * factor; let tempScaleY = scaleY * factor; let tempLeft = left * factor; let tempTop = top * factor; objects[i].scaleX = tempScaleX; objects[i].scaleY = tempScaleY; objects[i].left = tempLeft; objects[i].top = tempTop; objects[i].setCoords(); } let zoomPoint = new fabric.Point( editorCanvas.width / 2, editorCanvas.height / 2 ); editorCanvas.zoomToPoint(zoomPoint, factor); editorCanvas.renderAll(); editorCanvas.calcOffset(); } else { return; } }, // 删除当前鼠标活动控件 deleteText() { const obj = editorCanvas.getActiveObject(); if (obj) { editorCanvas.remove(obj); } editorCanvas.renderAll(); }, // 更改字体大小 changeFontSize(value) { let mfontSize = value; const obj = editorCanvas.getActiveObject(); if (obj) { obj.set({ fontSize: mfontSize, }); editorCanvas.renderAll(); } this.templateData.fontSize = mfontSize; }, // 背景颜色 changeBgColor(value) { let mbgColor = value; const obj = editorCanvas; if (obj) { obj.set({ backgroundColor: mbgColor, }); editorCanvas.renderAll(); } this.templateData.bgColor = mbgColor; }, // 字体颜色 changeFontColor(value) { let mfontColor = value; const obj = editorCanvas.getActiveObject(); if (obj) { obj.set({ fill: mfontColor, }); editorCanvas.renderAll(); } this.templateData.textColor = mfontColor; }, // 对齐方式 changeTextAlign(value) { let mtextAlign = value; const obj = editorCanvas.getActiveObject(); if (obj) { obj.set("textAlign", mtextAlign); obj.centerH(); editorCanvas.renderAll(); } this.templateData.horizontalAlign = mtextAlign; }, // 字体粗细 changefontWeight(value) { let mfontWeight = value; const obj = editorCanvas.getActiveObject(); if (obj) { obj.set("fontWeight", mfontWeight); editorCanvas.renderAll(); } this.templateData.fontWeight = mfontWeight; }, // 字体风格 changeFontStyle(value) { let mfontStyle = value; const obj = editorCanvas.getActiveObject(); if (obj) { obj.set("fontStyle", mfontStyle); editorCanvas.renderAll(); } this.templateData.fontStyle = mfontStyle; }, // 图片预览 downLoadImage() { let base64URl = editorCanvas.toDataURL({ formart: "png", multiplier: 1, }); this.imageBase64 = base64URl; this.done = false; }, }, ...... components: {}, created() {}, }; </script> <style scoped> * { margin: 0; padding: 0; } body { font-family: 'PingFang SC', "Helvetica Neue", Helvetica, "microsoft yahei", arial, STHeiTi, sans-serif; } a { text-decoration: none } .el-aside { background-color: #F3F3F3; color: #333; text-align: center; } .el-main { background-color: #EEEEEE; color: #333; text-align: center; line-height: 160px; } .el-main .content-show { display: flex; flex-direction: column; } .text-edit h6 { height: 40px; color: black; } .text-edit .el-form { margin: 15px; } .btn-delete { min-height: 36px; } .template-content { padding: 0px; margin: 0px; } ton-box:hover { color: white; opacity: 1; } .templateContent { width: 100%; padding: 0px; background-color: #fff; } .template-upload { width: 256px; height: 130px; border: 2px solid #adadad; margin: 10px auto; line-height: 130px; text-align: center; cursor: pointer; } .template-img { width: 300px; height: 130px; margin: 0px auto; line-height: 130px; text-align: center; cursor: pointer; } #editorCanvas { box-shadow: 0 0 25px #cac6c6; width: 100%; display: block; margin: 15px auto; height: 100%; } .text-setting { text-align: center; width: 80px; font-size: 18px; font-weight: 500; margin-right:170px; } .text-edit h4, .side-right h4, .show h1 { text-align: center; font-size: 16px; color: #585858; font-weight: normal; margin: 15px auto; } .show h1 { text-align: center; color: #585858; padding: 15px; font-weight: bold; font-size: 24px; margin: 15px auto; } .btn-zoom { display: inline-block; line-height: 1; height: 40px; width: 104px; white-space: nowrap; -webkit-appearance: none; text-align: center; -webkit-box-sizing: border-box; box-sizing: border-box; outline: 0; margin: 0; -webkit-transition: 0.1s; transition: 0.1s; font-weight: 500; font-size: 14px; border-radius: 4px; color: #fff; background-color: #6A60E3; border-color: #6A60E3; } .btn-download, .btn-save, .btn-load, .btn-reset { display: inline-block; line-height: 1; height: 40px; width: 104px; white-space: nowrap; -webkit-appearance: none; text-align: center; -webkit-box-sizing: border-box; box-sizing: border-box; outline: 0; margin: 0; -webkit-transition: 0.1s; transition: 0.1s; font-weight: 500; padding: 12px 20px; font-size: 14px; border-radius: 4px; color: #fff; background-color: #6A60E3; margin: 10px 0px 0px 10px; border-color: #6A60E3; } .btn-reset { height: 40px; color: #fff; width: 98px; background-color: #6A60E3; margin: 10px 0px 0px 10px; border-color: #6A60E3; } .el-form-item { margin: 15px auto; } .el-form { height: 70px; line-height: 70px; } .el-header { height: 60px; } .el-form--inline .el-form-item__content { margin: 0; padding: 0; height: 60px; } .btn_style { display: inline-block; height: 40px; margin-left: 15px; width: 120px; line-height: 40px; white-space: nowrap; -webkit-appearance: none; text-align: center; font-weight: 500; background: none; padding: 0px 20px 20px; font-size: 14px; border-radius: 4px; color: #fff; } </style>
文本属性数据:fontData.js
export const fontFamilies = [ { label: '宋体', value: "'sans-serif, cursive" }, { label: '黑体', value: "'SimHei', cursive" }, { label: '微软雅黑', value: "'Microsoft Yahei', cursive" }, { label: '微软正黑体', value: "'Microsoft JhengHei', cursive" }, { label: '楷体', value: "'KaiTi', cursive" }, { label: '仿宋', value: "'FangSong', cursive" }, { label: '苹方', value: "'PingFang SC', cursive" }, { label: '华文黑体', value: "'STHeiti', cursive" }, { label: '隶书', value: "'LiSu', cursive" }, { label: 'Yatra One', value: "'Yatra One', cursive" } ]; export const fontSizes = [ { label: '9', value: 9 }, { label: '10', value: 10 }, { label: '12', value: 12 }, { label: '14', value: 14 }, { label: '16', value: 16 }, { label: '18', value: 18 }, { label: '20', value: 20 }, { label: '24', value: 24 }, { label: '28', value: 28 }, { label: '32', value: 32 }, { label: '36', value: 36 }, { label: '40', value: 40 }, { label: '42', value: 42 }, { label: '50', value: 50 }, { label: '60', value: 64 }, { label: '72', value: 72 }, { label: '82', value: 82 }, { label: '90', value: 90 }, { label: '96', value: 96 } ]; export const fontStyle = [ { value: 'normal', label: '正常' }, { value: 'italic', label: '斜体' } ]; export const fontColor = [ { label: '黑色', value: 'block' }, { label: '白色', value: 'white' }, { label: '红色', value: 'red' }, { label: '绿色', value: 'green' }, { label: '蓝色', value: 'blue' }, { label: '紫色', value: 'purple' } ]; export const fontWeight = [ { value: 'normal', label: '正常' }, { value: 'bold', label: '粗体' }, { value: 'lighter', label: '细体' }, { value: '100', label: '100' }, { value: '200', label: '200' }, { value: '300', label: '300' }, { value: '400', label: '400' }, { value: '500', label: '500' }, { value: '600', label: '600' }, { value: '700', label: '700' }, { value: '800', label: '800' }, { value: '900', label: '900' } ]; export const backgroundColor = [ { label: '黑色', value: 'block' }, { label: '白色', value: 'white' }, { label: '红色', value: 'red' }, { label: '绿色', value: 'green' }, { label: '蓝色', value: 'blue' }, { label: '紫色', value: 'purple' } ]; export const textAlign = [ { label: '居中', value: 'center' }, { label: '两端对齐', value: 'justify' } /* { label: '左对齐', value: 'left' }, { label: '右对齐', value: 'right' },*/ ];
vue项目中main.js:
import { createApp } from 'vue'
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
import App from './App.vue';
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
代码有点长,没有全部放上去,需要源码的下面留言!
Fabric.js是一个可以简化Canvas程序编写的canvas绘图库。
fabric.js官网:http://fabricjs.com/
Fabric.js可以做很多事情:
vue项目里,通过npm 安装:
npm install fabric --save
html文件的可以通过通过cdn引用:
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
html 结构里,创建一个canves,并设置id
<canvas ref="canvas" id="editorCanvas"></canvas>
初始化fabric的canvas对象:
// 初始化模板编辑画布
initeditorCanvas() {
const editorCanvas = new fabric.Canvas("editorCanvas", {
devicePixelRatio: true,
width: "375",
height: "667",
originX: "center",
originY: "center",
backgroundColor: "#ffffff",
transparentCorners: false,
});
editorCanvas.preserveObjectStacking = true;
},
以上canves 画布就创建好了,可以在画布上操作添加内容了。
object:added 添加图层
object:modified 编辑图层
object:removed 移除图层
selection:created 初次选中图层
selection:updated 图层选择变化
selection:cleared 清空图层选中
// 监听鼠标按下 const obj = editorCanvas.getActiveObject(); editorCanvas.on("mouse:down", (options) => { // 记录当前鼠标的起点坐标 if(!obj) { this.mouseFrom.x = options.e.clientX - editorCanvas._offset.left; this.mouseFrom.y = options.e.clientY - editorCanvas._offset.top; } }); // 监听鼠标移动 editorCanvas.on("mouse:move", (options) => { // 记录当前鼠标移动终点坐标 if (!obj) { this.mouseTo.x = options.e.clientX - editorCanvas._offset.left this.mouseTo.y = options.e.clientY - editorCanvas._offset.top this.drawRect(); } }); // 鼠标抬起 editorCanvas.on("mouse:up", (options) => { if (!obj) { this.mouseFrom.x = options.e.clientX - editorCanvas._offset.left; this.mouseFrom.y = options.e.clientY - editorCanvas._offset.top; this.doDrawing = false; this.canvasObject = null; this.mouseFrom = {}; this.mouseTo = {} } }); editorCanvas.on("selection:created",(option) => { if (option) { this.doDrawing = false; } })
// 读取图片地址,设置画布背景
let imgScanle = 50;
fabric.Image.fromURL('xx/xx/bg.jpg', (img) => {
img.set({
// 通过scale来设置图片大小,这里设置和画布一样大
scaleX: 400,
scaleY: 400,
originX: 'left',
originY: 'top'
});
// 设置背景
editorCanvas.setBackgroundImage(img,editorCanvas.renderAll.bind(editorCanvas));
editorCanvas.renderAll(); //重新渲染画布
});
let img = new Image()
img.src = '../img/pic' //图片路径
img.onload = function () {
let _img = new fabric.Image(img)
canves.setBackgroundImage(_img, canves.renderAll.bind(canves), {
left: 0,
top: 0,
scaleX: imgScale,
scaleY: imgScale,
originX: 'left',
originY: 'top'
})
}
通过backgroundColor设置背景颜色:
editorCanvas.set({
backgroundColor: '#000',
});
editorCanvas.renderAll();
Fabric.js 里有 Image,Textbox,Group,Rect,Circle,Line,Ellipse,Polygon,Polyline等对象,可以实现对象内容的添加:
// 添加Textbox文本框 const textbox = new fabric.Textbox('我是TextBox', { left: 50, top: 50, width: 150, textAlign: "left", // 对齐方式 lineHeight: 1, // 字体行高 charSpacing: 1, // 字体间距 fontFamily: "hyzktjjkt", // 字体 fontSize: 40, // 字体大小 fontWeight: 'blod', // 字体粗细 fill: 'red', // 字体颜色 fontStyle: 'italic', // 斜体 fontFamily: 'Delicious', // 设置字体 stroke: 'green', // 描边颜色 strokeWidth: 3, // 描边宽度 hasControls: false, borderColor: 'red', // 字体描边颜色 type: "editText", // 类型 }); editorCanvas.add(textbox); // 通过add方法把对象添加到画布上
// 获取当前选中的对象
this.selectedObj = editorCanves.getActiveObject();
// 获取选中的图层
editorCanves.on('selection:created', (e) => {
this.selectedObj = e.target
})
向画布添加图层,默认是依次往上叠加,但是当你选中一个图层进入active状态时,该图层会默认置于顶层:
// 上移图层
this.selectedObj.bringForward();
// 下移图层
this.selectedObj.sendBackwards();
// 通过canvas对象的moveTo方法,移至图层到指定位置
editorCanves.moveTo(object, index);
禁止选中图层时指定:
// 在画布初始化后设置
editorCanves.preserveObjectStacking = true // 禁止选中图层时自定置于顶部
// 图片预览
downLoadImage() {
let base64URl = editorCanvas.toDataURL({
formart: "png",
multiplier: 1,
});
this.imageBase64 = base64URl;
this.done = false;
},
// 下载图片 downLoad() { this.done = true; const dataURL = editorCanvas.toDataURL({ width: editorCanvas.width, height: editorCanvas.height, left: 0, top: 0, format: "png", }); const link = document.createElement("a"); link.download = "图片.png"; link.href = dataURL; document.body.appendChild(link); link.click(); document.body.removeChild(link); },
框架提供了如 toJSON 和 loadFromJSON 方法,作用分别为导出当前画布的json信息,加载json画布信息来还原画布状态。
// 导出当前画布信息
const currState = editorCanves.toJSON();
// 移除某个选中的对象
editorCanves.remove(this.selectedObj)
editorCanves.renderAll() // 重新渲染
// 清除画布上的所有对象内容
editorCanves.clear();
editoeCanves.renderAll();
// 清空画布
resetCanvas() {
let children = editorCanvas.getObjects();
if (children.length > 0) {
editorCanvas.remove(...children);
}
editorCanvas.setBackgroundColor("#fff");
},
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。