canvas 制作海报
引入fabric.js 库
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
<script src="https://unpkg.com/coco-modal/coco-modal.min.js"></script>
DOM层
<canvas width="500" height="500" style="border: 1px solid #000;" id="canvas"></canvas>
<div class="button-box">
<div class="upload-box">
<button class="button"><label for="addBgImg">添加背景图片</label></button>
<input style="display: none;" class="button" type="file" accept="image/*" name="uploader-input"
class="uploader-file" id="addBgImg">
</div>
<div class="upload-box">
<button class="button"><label for="addimg">添加图片</label></button>
<input style="display: none;" class="button" type="file" accept="image/*" name="uploader-input"
class="uploader-file" id="addimg">
</div>
<button class="button" id="addtext">添加文字</button>
<button class="button" id="remove">删除元素</button>
<button class="button" id="exportCanves">导出图片</button>
</div>
js部分代码
const card = new fabric.Canvas('canvas')
const exportCanves = document.getElementById("exportCanves")
const addimg = document.getElementById("addimg")
const addBgImg = document.getElementById("addBgImg")
const addtext = document.getElementById("addtext")
const remove = document.getElementById("remove")
exportCanves.onclick = function (e) {
const currState = card.toJSON();
const dataURL = card.toDataURL({
format: 'jpeg',
quality: 1.8
});
downloadIamge(dataURL, 'img')
}
card.on('object:modified', (e) => {
objectMoving(e)
objectModified(e)
});
card.backgroundColor = 'white';
function downloadIamge(imgsrc, name) {
let image = new Image();
image.setAttribute("crossOrigin", "anonymous");
image.onload = function () {
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
let url = canvas.toDataURL("image/png");
let a = document.createElement("a");
let event = new MouseEvent("click");
a.download = name || "photo";
a.href = url;
a.dispatchEvent(event);
};
image.src = imgsrc;
}
addBgImg.onchange = function (event) {
var $file = event.currentTarget;
var formData = new FormData();
var file = $file.files;
formData = new FormData();
formData.append(file[0].name, file[0]);
var path = window.URL.createObjectURL(file[0]);
fabric.Image.fromURL(path, (img) => {
img.set({
scaleX: card.width / img.width,
scaleY: card.height / img.height,
});
card.setBackgroundImage(img, card.renderAll.bind(card));
card.renderAll();
});
}
addtext.onclick = function (e) {
getDialog()
}
remove.onclick = function (e) {
card.remove(card.getActiveObject())
card.renderAll()
}
function objectMoving(e) {
var obj = e.target;
if (obj.currentHeight > obj.canvas.height || obj.currentWidth > obj.canvas.width) {
return;
}
obj.setCoords();
if (obj.getBoundingRect().top < 0 || obj.getBoundingRect().left < 0) {
obj.top = Math.max(obj.top, obj.top - obj.getBoundingRect().top);
obj.left = Math.max(obj.left, obj.left - obj.getBoundingRect().left);
}
if (obj.getBoundingRect().top + obj.getBoundingRect().height >
obj.canvas.height || obj.getBoundingRect().left + obj.getBoundingRect().width > obj.canvas.width) {
obj.top = Math.min(obj.top, obj.canvas.height -
obj.getBoundingRect().height + obj.top -
obj.getBoundingRect().top);
obj.left = Math.min(obj.left, obj.canvas.width -
obj.getBoundingRect().width + obj.left - obj.getBoundingRect().left);
}
}
function objectModified(e) {
let obj = e.target;
let boundingRect = obj.getBoundingRect(true);
if (boundingRect.left < 0 || boundingRect.top < 0 || boundingRect.left + boundingRect.width >
obj.canvas.getWidth() || boundingRect.top + boundingRect.height > obj.canvas.getHeight()) {
obj.top = obj._stateProperties.top;
obj.left = obj._stateProperties.left;
obj.angle = obj._stateProperties.angle;
obj.scaleX = obj._stateProperties.scaleX;
obj.scaleY = obj._stateProperties.scaleY;
obj.setCoords();
obj.saveState();
} else {
obj.saveState();
}
}
function getDialog() {
window.CocoConfig = {
maskClose: true,
header: true,
footer: true,
title: '提示',
text: '',
width: '300px',
top: '30vh',
inputAttrs: true,
escClose: true,
okButton: true,
cancelButton: true,
okText: '确定',
cancelText: '取消',
closeButton: true,
html: '',
zIndexOfModal: 1995,
zIndexOfMask: 2008,
zIndexOfActiveModal: 2020,
autoFocusOkButton: true,
autoFocusInput: true,
fullScreen: false,
borderRadius: '6px',
blur: false,
buttonColor: '#4285ff',
hooks: {
open() { },
opened() {
},
close() { },
closed() { },
},
destroy: true,
animation: true
}
coco({
title: "请输入你要添加的内容",
html: '',
}).onClose((cc, isOk, done) => {
let tmr = null;
if (cc) {
isOk.showLoading();
if (addtextByCanves(isOk.inputValue)) {
isOk.hideLoading();
done();
}
} else {
clearTimeout(tmr);
isOk.hideLoading();
done();
}
});
}
function addtextByCanves(text) {
const contant = new fabric.Textbox(text, {
left: 50,
top: 50,
width: 150,
fontSize: 20,
fontWeight: 800,
hasControls: false,
borderColor: 'orange',
editingBorderColor: 'blue'
});
card.add(contant);
return true
}
document.getElementById('addimg').addEventListener('change', function (event) {
var $file = event.currentTarget;
var formData = new FormData();
var file = $file.files;
formData = new FormData();
formData.append(file[0].name, file[0]);
let path = window.URL.createObjectURL(file[0]);
addimgByCanves(path)
});
function addimgByCanves(imgUrl) {
fabric.Image.fromURL(imgUrl, (img) => {
img.set({
hasControls: true,
borderColor: 'orange',
});
img.scaleToHeight(100);
card.add(img);
});
}