canvas 图片合成及导出

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')// ...这里可以写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(); // 导出的Json如下图
	// console.log(currState, '导出当前画布信息', e)
	// return
	// 加载画布信息
	// card.loadFromJSON(lastState, () => {
	//     card.renderAll();
	// });
	const dataURL = card.toDataURL({
		format: 'jpeg', // jpeg或png
		quality: 1.8 // 图片质量,仅jpeg时可用
		// 截取指定位置和大小
		//left: 100,
		//top: 100,
		//width: 200,
		//height: 200
	});
	downloadIamge(dataURL, 'img')
}
card.on('object:modified', (e) => {
	// console.log(e.target) // e.target为当前编辑的Object
	objectMoving(e)
	objectModified(e)
	// ...旋转,缩放,移动等编辑图层的操作都监听
	// 所以如果有撤销/恢复的场景,这里可以保存编辑状态
});
// 设置画布背景颜色
card.backgroundColor = 'white';
function downloadIamge(imgsrc, name) { //下载图片地址和图片名
	let image = new Image();
	// 解决跨域 Canvas 污染问题
	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"); //得到图片的base64编码数据
		let a = document.createElement("a"); // 生成一个a元素
		let event = new MouseEvent("click"); // 创建一个单击事件
		a.download = name || "photo"; // 设置图片名称
		a.href = url; // 将生成的URL设置为a.href属性
		a.dispatchEvent(event); // 触发a的单击事件
	};
	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({
			// 通过scale来设置图片大小,这里设置和画布一样大
			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();
	// top-left corner
	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);
	}
	// bot-right corner
	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) { //true 确认
			isOk.showLoading();
			if (addtextByCanves(isOk.inputValue)) {
				isOk.hideLoading();
				done();
			}
		} else {
			clearTimeout(tmr);
			isOk.hideLoading();
			done();
		}
	});
}
//将输入的内容加入到canves中
function addtextByCanves(text) {
	const contant = new fabric.Textbox(text, {
		left: 50,
		top: 50,
		width: 150,
		fontSize: 20, // 字体大小
		fontWeight: 800, // 字体粗细
		// fill: 'red', // 字体颜色
		// fontStyle: 'italic',  // 斜体
		// fontFamily: 'Delicious', // 设置字体
		// stroke: 'green', // 描边颜色
		// strokeWidth: 3, // 描边宽度
		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)
});
//将图片加入canves
function addimgByCanves(imgUrl) {
	fabric.Image.fromURL(imgUrl, (img) => {
		img.set({
			hasControls: true, // 是否开启图层的控件
			borderColor: 'orange', // 图层控件边框的颜色
		});
		//生成的图片缩放到指定的尺寸。
		// img.scaleToWidth(500);
		img.scaleToHeight(100);
		// 添加对象
		card.add(img);
	});
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值