<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>fabric</title>
<script src="https://picture.52hrttpic.com/cdn/js/fabric.min.js"></script>
<script src="./index.js"></script>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
ul {
display: flex;
list-style: none;
}
ul li {
width: 50px;
height: 30px;
line-height: 30px;
border: 1px solid
margin-right: 20px;
text-align: center;
}
</style>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<ul class="bottom">
<li class="back">
<p>撤销</p>
</li>
<li class="restore">
<p>恢复</p>
</li>
<li class="write">
<p>手写</p>
</li>
<li class="characters">
<p>文字</p>
</li>
<li class="rights">
<p>打钩</p>
</li>
<li class="error">
<p>打叉</p>
</li>
<li class="rotate">
<p>旋转</p>
</li>
<li class="save">
<p>保存</p>
</li>
<li class="test">
<p>测试</p>
</li>
<!-- <li @click="zoomIn">
<p>放大</p>
</li>
<li @click="zoomOut"><p>缩小</p></li> -->
</ul>
<script>
new myFabric({
id: 'canvas',
url: 'http://1251481829.vod2.myqcloud.com/48804df0vodtransgzp1251481829/8eeca8613270835010470728685/sampleSnapshot/sampleSnapshot_10_1.jpg'
})
// 恢复
let restore = document.querySelector('.restore')
// 撤销
let back = document.querySelector('.back')
// 文字
let characters = document.querySelector('.characters')
// 手写
let write = document.querySelector('.write')
// 打勾
let right = document.querySelector('.rights')
// 打叉
let error = document.querySelector('.error')
// 旋转
let rotate = document.querySelector('.rotate')
// 保存
let save = document.querySelector('.save')
// 测试
let test = document.querySelector('.test')
// 自由绘画
write.onclick = function(){
myCanvas.DrawingMode()
}
// 文字
characters.onclick = function(){
myCanvas.addText()
}
// 打勾
right.onclick = function(){
myCanvas.addImg('right')
}
// 打叉
error.onclick = function(){
myCanvas.addImg('error')
}
// 旋转
rotate.onclick = function(){
myCanvas.rotate(90)
}
// 保存
save.onclick = function(){
myCanvas.save(90)
}
// 恢复
restore.onclick = function(){
myCanvas.restore()
}
// 撤销
back.onclick = function(){
myCanvas.back()
}
// 测试
test.onclick = function(){
myCanvas.test()
}
</script>
</body>
</html>
class myFabric {
delList = []; // 被删除的数据
canvasId = ''; // classId
url = ''; // 图片的地址
isDrawingMode = false; // 是否开启自由绘画
canvas = null; // 主体
backgroundImage = null; // 背景图的引用
angle = 0; // 图片旋转角度
constructor(config) {
this.canvasId = config.id
this.url = config.url
this.canvas = new fabric.Canvas(config.id, {
//backgroundVpt: false // 不受视口变换影响(也就是不管拖拽还是缩放画布,背景图都不受影响)
})
this.getBase64FromImageUrl(config.url).then(res => {
fabric.Image.fromURL(res, // 参数1:图片路径
img => { // 参数2:图片加载完成后的回调函数
const imgWidth = img.width;
const imgHeight = img.height;
const canvasWidth = this.canvas.width;
const canvasHeight = this.canvas.height;
const imgAspectRatio = imgHeight / imgWidth;
const canvasAspectRatio = canvasHeight / canvasWidth;
let imgScaleX = 1;
let imgScaleY = 1;
if (imgAspectRatio > canvasAspectRatio) { // 图片以高度为约束
imgScaleY = Number((canvasHeight / imgHeight).toFixed(2));
imgScaleX = imgScaleY
} else { // 图片以宽度为约束
imgScaleX = Number((canvasWidth / imgWidth).toFixed(2));
imgScaleY = imgScaleX
}
img.set({
left: this.canvas.width / 2, // 图片左边的位置
top: this.canvas.height / 2, // 图片顶部的位置
scaleX: imgScaleX, // 计算出图片要拉伸的宽度
scaleY: imgScaleY, // 计算出图片要拉伸的高度
originX: 'center', // 设置旋转中心为图片的中心点
originY: 'center',
centeredRotation: true, // 设置物体围绕旋转中心进行旋转
})
this.canvas.setBackgroundImage(img)
// 保存背景图片对象的引用
this.backgroundImage = img;
// 重新渲染页面
this.canvas.renderAll()
}
)
})
}
// 是否开启自由绘画
DrawingMode() {
this.isDrawingMode = !this.isDrawingMode
this.canvas.isDrawingMode = this.isDrawingMode
}
// 添加文字
addText() {
// 创建Text元素
const itext = new fabric.IText('双击可编辑', {
top: 60, // 文本到画布顶部的距离
left: 100, // 文本到画布左侧的距离
splitByGrapheme: true, // 自动换行
})
this.canvas.add(itext)
}
// 添加钩叉图片
addImg(imgName) {
let rightImgUrl = './img/right-icon.png'
let errorImgUrl = './img/wrong-icon.png'
let url = ''
if (imgName == 'right') {
url = rightImgUrl
} else if (imgName == 'error') {
url = errorImgUrl
}
fabric.Image.fromURL(
url, // 图片路径
img => {
img.top = 100,
img.left = 300,
this.canvas.add(img) // 将图片插入到画布中
}
)
}
// 旋转
rotate(angle) {
this.angle += 90
if (this.angle == 360) {
this.angle = 0
}
this.backgroundImage.set({
angle: this.angle // 累积旋转角度
});
// 重新渲染页面
this.canvas.renderAll();
console.log(this.backgroundImage.angle);
}
// 保存
save() {
const backgroundImage = this.backgroundImage;
const bgLeft = backgroundImage.left;
const bgTop = backgroundImage.top;
const bgWidth = backgroundImage.width * backgroundImage.scaleX;
const bgHeight = backgroundImage.height * backgroundImage.scaleY;
const cropLeft = bgLeft - bgWidth / 2; // 裁剪区域左边的位置
const cropTop = bgTop - bgHeight / 2; // 裁剪区域顶部的位置
const cropWidth = bgWidth; // 裁剪区域的宽度
const cropHeight = bgHeight; // 裁剪区域的高度
console.log(cropLeft, cropTop, cropWidth, cropHeight);
console.log(backgroundImage);
let dataURL;
let bool = backgroundImage.angle === 180 || backgroundImage.angle === 0;
console.log(bool);
if (bool) {
dataURL = this.canvas.toDataURL({
left: cropLeft,
top: cropTop,
width: cropWidth,
height: cropHeight
});
} else {
dataURL = this.canvas.toDataURL({
left: cropTop,
top: cropLeft,
width: cropHeight,
height: cropWidth
});
}
console.log(dataURL);
}
// 撤销
back() {
if (this.canvas._objects.length > 0) {
this.delList.push(this.canvas._objects.pop());
this.canvas.renderAll();
}
}
// 恢复
restore() {
if (this.delList.length > 0) {
this.isRedoing = true;
this.canvas.add(this.delList.pop());
this.canvas.renderAll();
}
}
test() {
console.log(this.canvas);
}
// 创建一个用于读取图片的 Promise 函数
getBase64FromImageUrl(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
let dataURL
if (url.indexOf('jpg') > -1 || url.indexOf('jpeg') > -1) {
dataURL = canvas.toDataURL('image/jpeg');
} else if (url.indexOf('png') > -1) {
dataURL = canvas.toDataURL('image/png');
}
resolve(dataURL);
};
img.onerror = reject;
img.src = url;
});
}
}