实现效果图:
image.png
1. 创建vue2项目
vue create vue2-board
2. 将项目进行一个简单的配置,比如全局scss样式文件,将p标签、ul li标签、h1、h2等标签
的默认样式去除,ps:推荐样式重置文件reset.css
,样式地址:https://meyerweb.com/eric/tools/css/reset/
2.1 在src
路径下新建styles
文件夹,内建index.scss
,然后在main.js
内引入该文件。import './styles/index.scss'
代码如下:
/* http://meyerweb.com/eric/tools/css/reset/ */
/* v1.0 | 20080212 */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
/* remember to define focus styles! */
:focus {
outline: 0;
}
/* remember to highlight inserts somehow! */
ins {
text-decoration: none;
}
del {
text-decoration: line-through;
}
/* tables still need 'cellspacing="0"' in the markup */
table {
border-collapse: collapse;
border-spacing: 0;
}
2.2 安装必要的插件element-ui
,fabric
cnpm i element-ui fabric --save
2.3 main.js
引入插件element-ui
,fabric
在需要的页面在导入
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
2.4 清空App.vue,开始编码,在此页面引入 fabric
<template>
<div id="app">页面初始化</div>
</template>
<script>
import { fabric } from "fabric";
export default {
name: "App",
};
</script>
<style lang="scss">
html,
body {
width: 100%;
height: 100%;
}
#app {
height: 100%;
background-color: #eee;
}
</style>
3. 先开发静态页面,也就是右侧的操作栏,
//竖形div,定位到右侧
<div class="tools"></div>
//css
.tools {
width: 46px;
height: 500px;
background: rgba(51, 51, 51, 0.4);
border-radius: 4px;
position: absolute;
right: 10px;
top: 10%;
}
<template>
<div id="app">
<!-- 右侧操作栏 -->
<div class="tools">
<ul>
<el-tooltip class="item" effect="dark" content="画笔" placement="left">
<li>
<i class="el-icon-edit"></i>
</li>
</el-tooltip>
<li>
<i class="el-icon-top-left"></i>
</li>
<li>
<i class="el-icon-minus"></i>
</li>
<li>
<i class="el-icon-full-screen"></i>
</li>
<li>
<i class="el-icon-edit-outline"></i>
</li>
<li>
<el-color-picker v-model="fontColor"></el-color-picker>
</li>
<li>
<i class="el-icon-d-arrow-left"></i>
</li>
<li>
<i class="el-icon-brush"></i>
</li>
</ul>
</div>
</div>
</template>
<script>
import { fabric } from "fabric";
export default {
name: "App",
data() {
return {
fontColor: "#409EFF",
};
},
};
</script>
<style lang="scss">
html,
body {
width: 100%;
height: 100%;
}
#app {
height: 100%;
background-color: #eee;
.tools {
// width: 46px;
// height: 500px;
background: rgba(51, 51, 51, 0.4);
border-radius: 4px;
position: absolute;
right: 10px;
top: 10%;
display: flex;
justify-content: center;
align-items: center;
padding: 10px 5px;
ul {
li {
width: 38px;
height: 38px;
background: #565656;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
color: #fff;
border-radius: 4px;
font-size: 20px;
cursor: pointer;
border: 1px solid transparent;
&:hover {
background: #333;
border: 1px solid #fff;
}
}
}
}
}
</style>
4. 既然是vue,我们就要循环渲染出来右侧的操作栏
<template>
<div id="app">
<!-- 右侧操作栏 -->
<div class="tools">
<ul>
<el-tooltip
v-for="(item, index) in brushModelData"
:key="index"
class="item"
effect="dark"
:content="item.tips"
placement="left"
>
<li v-if="item.type != 5">
<i :class="item.icon"></i>
</li>
<li v-if="item.type == 5">
<el-color-picker v-model="fontColor" size="mini"></el-color-picker>
</li>
</el-tooltip>
</ul>
</div>
</div>
</template>
<script>
import { fabric } from "fabric";
export default {
name: "App",
data() {
return {
fontColor: "#409EFF",
brushModelData: [
{ icon: "el-icon-edit", tips: "画笔", type: 0 },
{ icon: "el-icon-top-left", tips: "箭头", type: 1 },
{ icon: "el-icon-minus", tips: "直线", type: 2 },
{ icon: "el-icon-full-screen", tips: "矩形", type: 3 },
{ icon: "el-icon-edit-outline", tips: "文本", type: 4 },
{ icon: "el-icon-edit", tips: "颜色", type: 5 },
{ icon: "el-icon-d-arrow-left", tips: "撤销", type: 6 },
{ icon: "el-icon-brush", tips: "清空", type: 7 },
],
};
},
};
</script>
<style lang="scss">
html,
body {
width: 100%;
height: 100%;
}
#app {
height: 100%;
background-color: #eee;
.tools {
// width: 46px;
// height: 500px;
background: rgba(51, 51, 51, 0.4);
border-radius: 4px;
position: absolute;
right: 10px;
top: 10%;
display: flex;
justify-content: center;
align-items: center;
padding: 10px 5px;
ul {
li {
width: 38px;
height: 38px;
background: #565656;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 10px;
color: #fff;
border-radius: 4px;
font-size: 20px;
cursor: pointer;
border: 1px solid transparent;
&:hover {
background: #333;
border: 1px solid #fff;
}
i {
font-weight: bold;
}
&:last-child{
margin-bottom: 0;
}
}
}
}
}
</style>
5. 静态页面处理好了,下面来初始化 fabric
//设置一个画板区域,和当前页面同比大小
<!-- 画板区域 -->
<div class="conent">
<canvas id="canvas"></canvas>
</div>
.conent{
width: 100%;
height: 100%;
background: red;
}
methods:{
/**
* 初始化画板
*/
initBoard(){
//固定写法 ('canvas')括号内的参数 是canvas的id,{ }是一些参数
new fabric.Canvas('canvas',{
isDrawingMode:true,//默认开启自由绘画模式
})
}
},
mounted(){
this.initBoard()
}
image.png
可以看到画板太小了,下面设置下画板的大小和红色区域一般大
//首先把我们实例化出来的fabric赋值给一个变量
data() {
return {
canvas:null
};
},
/**
* 初始化画板
*/
initBoard(){
this.canvas = new fabric.Canvas('canvas',{
isDrawingMode:true,//默认开启自由绘画模式
})
//最好是定义一个可复用的方法
this.handleResize();
},
handleResize() {
/** 设置canvas画布大小 */
/** 先获取content的宽高,给content一个ref属性 canvasWrap */
// console.log(this.$refs.canvasWrap.offsetWidth);
let w = this.$refs.canvasWrap.offsetWidth
let h = this.$refs.canvasWrap.offsetHeight
this.canvas.setWidth(w);
this.canvas.setHeight(h);
},
mounted() {
this.initBoard();
//解决页面大小变化动态改变canvas画布的大小
window.addEventListener('resize',this.handleResize)
},
下面改变下画布的背景颜色和画笔的默认颜色和画笔的默认粗细
// 改变画布的背景颜色
this.canvas.backgroundColor = '#fff';
// 设置默认颜色
this.canvas.freeDrawingBrush.color = this.color;
// 设置默认画笔粗细
this.canvas.freeDrawingBrush.width = this.width;
当前模式是自由绘制模式,我们给左侧的操作栏一个默认选择状态 active
,并且实现动态切换active
image.png
<li v-if="item.type != 5" :class="{ active: isActive == index }" @click="setBrushModel(index, item)">
<i :class="item.icon"></i>
</li>
<li v-if="item.type == 5" :class="{ active: isActive == index }" @click="setBrushModel(index, item)">
<el-color-picker v-model="fontColor" size="mini"></el-color-picker>
</li>
* 点击切换画笔功能
*/
setBrushModel(index, item) {
if (item.type !== 5 && item.type !== 6 && item.type !== 7) {
this.isActive = index;
}
},
li.active {
background-color: #333;
border-color: #fff;
i {
font-weight: bold;
}
}
下面实现一个最简单的,变换画笔的颜色
<el-color-picker v-model="fontColor" size="mini" @change="changePenColor"></el-color-picker>
/** 改变画笔颜色 */
changePenColor(){
this.canvas.freeDrawingBrush.color = this.fontColor;
}
下面实现 最简单的撤销和清空的操作
switch (item.type) {
//撤销
case 6:
if (this.canvas._objects.length > 0) {
this.canvas._objects.pop();
// 重绘
this.canvas.renderAll();
}
break;
//清空
case 7:
this.canvas.clear();
this.canvas.backgroundColor = "#fff";
break;
default:
break;
}
网友评论