Fabric.js添加辅助线的方法

Fabric.js高级点的教程1–添加辅助线的方法

Fabric.js添加辅助线的方法

Fabric.js 非常的强大,但是国内的资源教程很少,最近想加个功能给元素添加辅助参考线(类似 演示 )。这样某个元素移动缩放都会根据其他元素有个参考,就行ps里面的功能一样。虽然类似的功能我其他的项目有单独实现过,但是我本着能懒就懒的原则,于是乎我google了一下,官方的bug里有提到,安利给大家。

首先下载这个文件到你的项目中,

https://github.com/fabricjs/fabric.js/blob/master/lib/aligning_guidelines.js

然后你想import可以稍微加一句

export default initAligningGuidelines;

原文件(为了防止有一天上面文件链接失效)

function initAligningGuidelines(canvas) {
 
	var ctx = canvas.getSelectionContext(),
		aligningLineOffset = 5,
		aligningLineMargin = 4,
		aligningLineWidth = 1,
		aligningLineColor = 'rgb(255,255,0)',
		viewportTransform,
		zoom = 1;
 
	function drawVerticalLine(coords) {
		drawLine(
			coords.x + 0.5,
			coords.y1 > coords.y2 ? coords.y2 : coords.y1,
			coords.x + 0.5,
			coords.y2 > coords.y1 ? coords.y2 : coords.y1);
	}
 
	function drawHorizontalLine(coords) {
		drawLine(
			coords.x1 > coords.x2 ? coords.x2 : coords.x1,
			coords.y + 0.5,
			coords.x2 > coords.x1 ? coords.x2 : coords.x1,
			coords.y + 0.5);
	}
 
	function drawLine(x1, y1, x2, y2) {
		ctx.save();
		ctx.lineWidth = aligningLineWidth;
		ctx.strokeStyle = aligningLineColor;
		ctx.beginPath();
		ctx.moveTo(((x1+viewportTransform[4])*zoom), ((y1+viewportTransform[5])*zoom));
		ctx.lineTo(((x2+viewportTransform[4])*zoom), ((y2+viewportTransform[5])*zoom));
		ctx.stroke();
		ctx.restore();
	}
 
	function isInRange(value1, value2) {
		value1 = Math.round(value1);
		value2 = Math.round(value2);
		for (var i = value1 - aligningLineMargin, len = value1 + aligningLineMargin; i <= len; i++) {
			if (i === value2) {
				return true;
			}
		}
		return false;
	}
 
	var verticalLines = [],
		horizontalLines = [];
 
	canvas.on('mouse:down', function () {
		viewportTransform = canvas.viewportTransform;
		zoom = canvas.getZoom();
	});
 
	canvas.on('object:moving', function(e) {
 
		var activeObject = e.target,
			canvasObjects = canvas.getObjects(),
			activeObjectCenter = activeObject.getCenterPoint(),
			activeObjectLeft = activeObjectCenter.x,
			activeObjectTop = activeObjectCenter.y,
			activeObjectBoundingRect = activeObject.getBoundingRect(),
			activeObjectHeight = activeObjectBoundingRect.height / viewportTransform[3],
			activeObjectWidth = activeObjectBoundingRect.width / viewportTransform[0],
			horizontalInTheRange = false,
			verticalInTheRange = false,
			transform = canvas._currentTransform;
 
		if (!transform) return;
 
		// It should be trivial to DRY this up by encapsulating (repeating) creation of x1, x2, y1, and y2 into functions,
		// but we're not doing it here for perf. reasons -- as this a function that's invoked on every mouse move
 
		for (var i = canvasObjects.length; i--; ) {
 
			if (canvasObjects[i] === activeObject) continue;
 
			var objectCenter = canvasObjects[i].getCenterPoint(),
				objectLeft = objectCenter.x,
				objectTop = objectCenter.y,
				objectBoundingRect = canvasObjects[i].getBoundingRect(),
				objectHeight = objectBoundingRect.height / viewportTransform[3],
				objectWidth = objectBoundingRect.width / viewportTransform[0];
 
			// snap by the horizontal center line
			if (isInRange(objectLeft, activeObjectLeft)) {
				verticalInTheRange = true;
				verticalLines.push({
					x: objectLeft,
					y1: (objectTop < activeObjectTop)
						? (objectTop - objectHeight / 2 - aligningLineOffset)
						: (objectTop + objectHeight / 2 + aligningLineOffset),
					y2: (activeObjectTop > objectTop)
						? (activeObjectTop + activeObjectHeight / 2 + aligningLineOffset)
						: (activeObjectTop - activeObjectHeight / 2 - aligningLineOffset)
				});
				activeObject.setPositionByOrigin(new fabric.Point(objectLeft, activeObjectTop), 'center', 'center');
			}
 
			// snap by the left edge
			if (isInRange(objectLeft - objectWidth / 2, activeObjectLeft - activeObjectWidth / 2)) {
				verticalInTheRange = true;
				verticalLines.push({
					x: objectLeft - objectWidth / 2,
					y1: (objectTop < activeObjectTop)
						? (objectTop - objectHeight / 2 - aligningLineOffset)
						: (objectTop + objectHeight / 2 + aligningLineOffset),
					y2: (activeObjectTop > objectTop)
						? (activeObjectTop + activeObjectHeight / 2 + aligningLineOffset)
						: (activeObjectTop - activeObjectHeight / 2 - aligningLineOffset)
				});
				activeObject.setPositionByOrigin(new fabric.Point(objectLeft - objectWidth / 2 + activeObjectWidth / 2, activeObjectTop), 'center', 'center');
			}
 
			// snap by the right edge
			if (isInRange(objectLeft + objectWidth / 2, activeObjectLeft + activeObjectWidth / 2)) {
				verticalInTheRange = true;
				verticalLines.push({
					x: objectLeft + objectWidth / 2,
					y1: (objectTop < activeObjectTop)
						? (objectTop - objectHeight / 2 - aligningLineOffset)
						: (objectTop + objectHeight / 2 + aligningLineOffset),
					y2: (activeObjectTop > objectTop)
						? (activeObjectTop + activeObjectHeight / 2 + aligningLineOffset)
						: (activeObjectTop - activeObjectHeight / 2 - aligningLineOffset)
				});
				activeObject.setPositionByOrigin(new fabric.Point(objectLeft + objectWidth / 2 - activeObjectWidth / 2, activeObjectTop), 'center', 'center');
			}
 
			// snap by the vertical center line
			if (isInRange(objectTop, activeObjectTop)) {
				horizontalInTheRange = true;
				horizontalLines.push({
					y: objectTop,
					x1: (objectLeft < activeObjectLeft)
						? (objectLeft - objectWidth / 2 - aligningLineOffset)
						: (objectLeft + objectWidth / 2 + aligningLineOffset),
					x2: (activeObjectLeft > objectLeft)
						? (activeObjectLeft + activeObjectWidth / 2 + aligningLineOffset)
						: (activeObjectLeft - activeObjectWidth / 2 - aligningLineOffset)
				});
				activeObject.setPositionByOrigin(new fabric.Point(activeObjectLeft, objectTop), 'center', 'center');
			}
 
			// snap by the top edge
			if (isInRange(objectTop - objectHeight / 2, activeObjectTop - activeObjectHeight / 2)) {
				horizontalInTheRange = true;
				horizontalLines.push({
					y: objectTop - objectHeight / 2,
					x1: (objectLeft < activeObjectLeft)
						? (objectLeft - objectWidth / 2 - aligningLineOffset)
						: (objectLeft + objectWidth / 2 + aligningLineOffset),
					x2: (activeObjectLeft > objectLeft)
						? (activeObjectLeft + activeObjectWidth / 2 + aligningLineOffset)
						: (activeObjectLeft - activeObjectWidth / 2 - aligningLineOffset)
				});
				activeObject.setPositionByOrigin(new fabric.Point(activeObjectLeft, objectTop - objectHeight / 2 + activeObjectHeight / 2), 'center', 'center');
			}
 
			// snap by the bottom edge
			if (isInRange(objectTop + objectHeight / 2, activeObjectTop + activeObjectHeight / 2)) {
				horizontalInTheRange = true;
				horizontalLines.push({
					y: objectTop + objectHeight / 2,
					x1: (objectLeft < activeObjectLeft)
						? (objectLeft - objectWidth / 2 - aligningLineOffset)
						: (objectLeft + objectWidth / 2 + aligningLineOffset),
					x2: (activeObjectLeft > objectLeft)
						? (activeObjectLeft + activeObjectWidth / 2 + aligningLineOffset)
						: (activeObjectLeft - activeObjectWidth / 2 - aligningLineOffset)
				});
				activeObject.setPositionByOrigin(new fabric.Point(activeObjectLeft, objectTop + objectHeight / 2 - activeObjectHeight / 2), 'center', 'center');
			}
		}
 
		if (!horizontalInTheRange) {
			horizontalLines.length = 0;
		}
 
		if (!verticalInTheRange) {
			verticalLines.length = 0;
		}
	});
 
	canvas.on('before:render', function() {
		canvas.clearContext(canvas.contextTop);
	});
 
	canvas.on('after:render', function() {
		for (var i = verticalLines.length; i--; ) {
			drawVerticalLine(verticalLines[i]);
		}
		for (var i = horizontalLines.length; i--; ) {
			drawHorizontalLine(horizontalLines[i]);
		}
 
		verticalLines.length = horizontalLines.length = 0;
	});
 
	canvas.on('mouse:up', function() {
		verticalLines.length = horizontalLines.length = 0;
		canvas.renderAll();
	});
}
 
export default initAligningGuidelines;

引入这个js,然后

	import initAligningGuidelines from '@/libs/guidelines.js';
	let canvas = new fabric.Canvas('canvas');
	initAligningGuidelines(canvas)

再然后
在这里插入图片描述
看到没各位。。。一根黄色的辅助线就有了,辅助线的颜色,宽度等都可以调节,具体看代码aligningLineColor 等变量。

转载于:https://my.oschina.net/xmqywx/blog/1941539

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值