目录

  • 前言
  • 一 、实战效果
    • 技术选型
    • 核心功能
    • 代码实现
  • 二、Fabric.js 简介
    • 安装
    • 创建画布
    • 监听画布事件
    • 鼠标事件监听
    • 设置画布背景
    • 设置背景颜色
    • 向画布添加图层对象
    • 获取当前选中的对象
    • 控制图层层级
    • 将画布导出成图片
    • 下载为图片
    • 画布状态记录
    • 清除对象/图层
    • 清除画布

前言

canves 绘图的运用是前端必知必会的基础,但是canves 本身并不好用,而fabric.js是基于canves的一个绘图框架库,用起来可比canves友好多了!接下来带你看看案例和初识fabric.js~

一 、实战效果

编辑前:

编辑中:

技术选型

  • Vue3
  • Element-plus
  • Fabric.js
  • ES6

核心功能

主要实现H5 移动端简单的图片的可视化编辑、预览、下载等功能。

  • 文本编辑:实现画布上的文本框的添加、字体属性的设置、样式风格编辑、背景颜色个性化设置、文本内容的设置等;
  • 图片上传:点击上传图片,实现图片的读取并添加到画布编辑区上,自由设置背景图片;
  • 绘制图片:实现根据鼠标坐标自由绘制图形(目前仅实现矩形,其他类似,可参考fabric 文档说明自己实现);
  • 删除控件:编辑区上的控件可自由删除;
  • 预览图片:编辑完成后可预览自己编辑的图片效果,并在右侧100%显示;
  • 下载图片:可下载编辑好的图片;
  • 画布缩放:可放大或者缩小画布,画布上的内容同步缩放;
  • 一键清空:重置实现画布一键清空;

目前仅实现以上的功能,后续在继续完善更新~~

代码实现

editor.vue:

<template><el-container ><el-header ><el-menustyle="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-buttonclass="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-buttonclass="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-optionv-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-optionv-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-optionv-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-optionv-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-optionv-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-optionv-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-pickerclass="color-picker"v-model="bgcolor" circlesize="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="data: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 = truelet base64URl = editorCanvas.toDataURL({formart: 'png',multiplier: 1})this.imageBase64 = base64URlthis.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.leftthis.mouseTo.y = options.e.clientY - editorCanvas._offset.topthis.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 简介

Fabric.js是一个可以简化Canvas程序编写的canvas绘图库。
fabric.js官网:http://fabricjs.com/

Fabric.js可以做很多事情:

  • 在Canvas上创建、填充图形(包括图片、文字、规则图形和复杂路径组成图形);
  • 给图形填充渐变颜色;
  • 组合图形(包括组合图形、图形文字、图片等);
  • 设置图形动画集用户交互;
    等等

安装

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.leftthis.mouseTo.y = options.e.clientY - editorCanvas._offset.topthis.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;}})

设置画布背景

  1. 通过背景图片的方式设置:
// 读取图片地址,设置画布背景
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(); //重新渲染画布
});
  1. fabric图片对象的方式:
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");},

【前端开发】Vue + Fabric.js + Element-plus 实现简易的H5可视化图片编辑器相关推荐

  1. 【repost】一探前端开发中的JS调试技巧

    有请提示:文中涉及较多Gif演示动画,移动端请尽量在Wifi环境中阅读 前言:调试技巧,在任何一项技术研发中都可谓是必不可少的技能.掌握各种调试技巧,必定能在工作中起到事半功倍的效果.譬如,快速定位问 ...

  2. 学习 前端开发中的JS调试技巧(断点)

    http://seejs.me/2016/03/27/jsdebugger/ alert() console.log(xxxx) JS断点调试 JS断点调试,即是在浏览器开发者工具中为JS代码添加断点 ...

  3. 一探前端开发中的JS调试技巧

    转自:http://seejs.me/2016/03/27/%E3%80%90%E5%8E%9F%E5%88%9B%E3%80%91%E4%B8%80%E6%8E%A2%E5%89%8D%E7%AB% ...

  4. vue 创建图片坐标点_利用vue+fabric.js获取图片坐标,并实现图片拖拽、旋转、拉伸等功能...

    什么是Fabric.js? Fabric.js是一个可以简化Canvas程序编写的库. Fabric.js为Canvas提供所缺少的对象模型, svg parser, 交互和一整套其他不可或缺的工具. ...

  5. 前端开发中通过js设置cookie的一组方法

    js方法的完整代码如下: var cookie = {set:function(key,val,time){//设置cookie方法var date=new Date(); //获取当前时间var e ...

  6. 移动端canvas_web前端开发分享-css,js移动篇

    随着移动市场的逐步扩大及相关技术的日趋完善,对前端开发提出了新的岗位要求,在继承前人成果的基础上需要在新的历史条件下有新的创新.移动端的开发,虽然没有IE6众多问题的折磨,但是多平台,多设备的兼容,也 ...

  7. 前端开发Vue项目实战:电商后台管理系统(一)前后端搭建

    目录 1. 项目概述 2. 前端项目初始化步骤 3. 后台项目的环境安装配置 下载安装phpStudy,添加数据库 Postman测试工具 验证 1. 项目概述 电商项目基本业务概述: 根据不同的应用 ...

  8. 前端开发Vue项目实战:电商后台管理系统(二)-- 登录退出功能 --主页界面

    目录 1. 登录/退出功能 1.1 登录概述 1.2 token 原理分析 1.3 登录功能实现 1.3.1 Git 创建分支 1.3.2 渲染Login组件并实现路由重定向 1.3.3 设置背景颜色 ...

  9. 安装npm_前端开发:node.js的node包管理器npm安装以及使用

    在前端开发过程中,node.js进行包管理的时候会使用npm管理器来操作.npm(node package manager)包管理器,主要是用于第三方模块的下载.安装和管理,它具有强大的第三方资源,重 ...

最新文章

  1. outlook 2010 记忆式键入不工作的解决办法
  2. linux docker run 设置环境变量
  3. Request.Url.Port 获取不到正确的端口号
  4. Apple开发者账号申请学习方式
  5. 人类一败涂地显示服务器,人类一败涂地怎么开服务器 | 手游网游页游攻略大全...
  6. 用户自定义属性表结构设计_属性类型定制及其妙用
  7. Word+Excel 问题及解决
  8. php _get invalid,PHP 错误: ZipArchive::getFromName(): Invalid or unitialized Zip object in 解决方法...
  9. MFC中 使用Tab Control 控件在对话框中添加属性页
  10. 如何用计算机快捷键代替鼠标,什么快捷键代替鼠标左键
  11. pythonqq机器人酷q_基于NoneBot的QQ聊天机器人一
  12. datatables rows selected
  13. 阿里云服务器实例规格选型推荐(根据使用场景、典型应用推荐)
  14. 鹏哥C语言笔记分享P2
  15. matlab db dbm dbfs,dB
  16. 模拟按键 —— 鼠标
  17. 【mysql数据库】通过python 3.7 爬虫获取企查查公开的企业信息,并记录到数据库
  18. Pointnet语义分割任务S3DIS数据集上的注意点
  19. 【笔记】unity渲染类名词术语概念总结(30个点)
  20. Oracle DBA手记4:数据安全警示录

热门文章

  1. 免费开源JAVA报表工具对比 BIRT报表VS润乾报表之初体验
  2. 烧录软件BlueSuite.WIN.3.3 Installer_3.3.14.1471
  3. nginx 解决504超时问题
  4. Rectangle和RectangleF结构
  5. 空闲时间不要接私活,要提升自己
  6. 鼎信诺虚拟服务器导数,鼎信诺使用手册--自编版.docx
  7. python 如何判断当天为周几?判断当天是否为工作日?
  8. 冯诺依曼体系各硬件工作原理解析
  9. 给vue项目添加favicon.ico图标
  10. JAVA合并pdf,拆分pdf文档