65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 KineticJS 对齐多个对象

2013 年 11 月 21 日

MIT

2分钟阅读

viewsIcon

13666

downloadIcon

151

本文基于上一篇文章,我们在其中使用 KineticJS 库通过拖动鼠标创建了一个选择框。 在本文中,我们将添加函数,以便将这些对象沿其左侧或右侧边缘、顶部或底部以及中间或中心对齐。

Sample Image - maximum width is 600 pixels

引言

本文基于 上一篇文章,我们在其中使用 KineticJS 库通过拖动鼠标创建了一个选择框。 在本文中,我们将添加函数,以便将这些对象沿其左侧或右侧边缘、顶部或底部以及中间或中心对齐。

背景

如果您尚未阅读 上一篇文章,请阅读。 本文假定您已具备上一篇文章中的所有内容。 如果您不熟悉 HTML5 canvas 标签,请访问 HTML5CanvasTutorials.com。 如果您不熟悉 KineticJS 库,请点击 此处 了解更多信息以及它们如何使 Web 浏览器的图形体验焕然一新。 此示例适用于 KineticJS 库的 4.7.4 版本,可以在 此处 找到。 本文是使用 KineticJS 库选择和操作 HTML5 canvas 对象的系列文章的第二篇。

Using the Code

对齐顶部、底部、左侧、右侧、中间和中心是一组用户在许多图形编辑工具中期望的功能。 我们在示例中首先要做的是添加知道如何操作对象的功能。 让我们开始做一些数学运算吧。

对于我们的对齐函数,首先需要知道哪个对象是最顶端或最左侧的对象。 无论我们是在水平轴还是垂直轴上对齐,最顶端或最左侧的对象都将作为我们对齐所有其他对象的对象。 这两个函数为我们找到了这些对象。

function FindLeftmost()
{
	var lowestX = 100000;
	var grpLeft = null;

	for (var i = 0; i < arSelected.length; i++)
	{
		var grp = layer.get("." + arSelected[i])[0];
		if (parseInt(grp.attrs.x) < lowestX)
		{
			grpLeft = grp;
			lowestX = parseInt(grp.attrs.x);
		}
	}
	return grpLeft;
}

function FindTopmost()
{
	var lowestY = 10000;
	var grpTop = null;

	for (var i = 0; i < arSelected.length; i++)
	{
		var grp = layer.get("." + arSelected[i])[0];
		if (parseInt(grp.attrs.y) < lowestY)
		{
			grpTop = grp;
			lowestY = parseInt(grp.attrs.y);
		}
	}
	return grpTop;
}

接下来,我们拥有实际执行对齐的函数。 它们都以相同的方式工作:获取参考对象(最顶端或最左侧)的绝对位置,然后计算正确的数学公式,以按照用户请求的方式将所有选定的对象与之对齐。

///////////////////////////////////////////////
//// Alignment functions 
///////////////////////////////////////////////
function AlignLefts()
{
	var grpTop = FindTopmost();

	if (grpTop == null)
	{
		return;
	}
	var topPos = grpTop.getAbsolutePosition();
	for (i = 0; i < arSelected.length; i++)
	{
		var grp = layer.get("." + arSelected[i])[0];
		var newX = topPos.x;
		var newY = parseInt(grp.attrs.y);
		grp.setAbsolutePosition(newX, newY);
	}
	RemoveHighlights();
	layer.draw();
}

function AlignRights()
{
	var grpTop = FindTopmost();

	if (grpTop == null)
	{
		return;
	}
	var topPos = grpTop.getAbsolutePosition();
	var end = topPos.x + parseInt(grpTop.getWidth());

	for (i = 0; i < arSelected.length; i++)
	{
		var grp = layer.get("." + arSelected[i])[0];
		var newX = end - grp.getWidth();
		var newY = grp.getY();
		grp.setAbsolutePosition(newX, newY);
	}
	RemoveHighlights();
	layer.draw();
}

function AlignTops()
{
	var grpLeft = FindLeftmost();

	if (grpLeft == null)
	{
		return;
	}
	var leftPos = grpLeft.getAbsolutePosition();

	for (i = 0; i < arSelected.length; i++)
	{
		var grp = layer.get("." + arSelected[i])[0];
		var newX = grp.getX();
		var newY = leftPos.y;
		grp.setAbsolutePosition(newX, newY);
	}
	RemoveHighlights();
	layer.draw();
}

function AlignBottoms()
{
	var grpLeft = FindLeftmost();

	if (grpLeft == null)
	{
		return;
	}
	var leftPos = grpLeft.getAbsolutePosition();
	var bottom = leftPos.y + grpLeft.getHeight();

	for (i = 0; i < arSelected.length; i++)
	{
		var grp = layer.get("." + arSelected[i])[0];
		var newX = grp.getX();
		var newY = bottom - grp.getHeight();
		grp.setAbsolutePosition(newX, newY);
	}
	RemoveHighlights();
	layer.draw();
}

function AlignCenters()
{
	var grpTop = FindTopmost();

	if (grpTop == null)
	{
		return;
	}
	var topPos = grpTop.getAbsolutePosition();
	var middle = topPos.x + (grpTop.getWidth() / 2);

	for (i = 0; i < arSelected.length; i++)
	{
		var grp = layer.get("." + arSelected[i])[0];
		var newX = middle - (grp.getWidth() / 2);
		var newY = grp.getY();
		grp.setAbsolutePosition(newX, newY);
	}
	RemoveHighlights();
	layer.draw();
}

function AlignMiddles()
{
	var grpLeft = FindLeftmost();

	if (grpLeft == null)
	{
		return;
	}
	var leftPos = grpLeft.getAbsolutePosition();
	var middle = leftPos.x + (grpLeft.getHeight() / 2);

	for (i = 0; i < arSelected.length; i++)
	{
		var grp = layer.get("." + arSelected[i])[0];
		var newX = grp.getX();
		var newY = middle - (grp.getHeight() / 2);
		grp.setAbsolutePosition(newX, newY);
	}
	RemoveHighlights();
	layer.draw();
}

最后,我们只需要一种调用这些函数的方法。 为此,我们将使用 上一篇文章 中的 CreateButton 函数。

x = 10;
y = 290;
var grpAlignLeftButton = CreateButton(x, y, "Align Lefts");
grpAlignLeftButton.on("click", function (evt) { AlignLefts(); });

y = 330;
var grpAlignRightButton = CreateButton(x, y, "Align Rights");
grpAlignRightButton.on("click", function (evt) { AlignRights(); });

y = 370;
var grpAlignTopsButton = CreateButton(x, y, "Align Tops");
grpAlignTopsButton.on("click", function (evt) { AlignTops(); });

x = 160
y = 290;
var grpAlignBottomsButton = CreateButton(x, y, "Align Bottoms");
grpAlignBottomsButton.on("click", function (evt) { AlignBottoms(); });

y = 330;
var grpAlignMiddlesButton = CreateButton(x, y, "Align Middles");
grpAlignMiddlesButton.on("click", function (evt) { AlignMiddles(); });

y = 370;
var grpAlignCentersButton = CreateButton(x, y, "Align Centers");
grpAlignCentersButton.on("click", function (evt) { AlignCenters(); });

x = 85;
y = 410;
var grpResetButton = CreateButton(x, y, "Reset Blocks");
grpResetButton.on("click", function (evt) { DrawBlocks(); });

stage.add(layer);
layer.draw();

关注点

应该注意的是,调用 setAbsolutePosition 的行是绝对必要的。 如果您只设置 x y,位置将不会与鼠标点击相对舞台的位置相同,这将在您计算哪些项目落入选择框内时给您带来很大的痛苦。

您可以在 此处 查看此项目的运行演示。

历史

  • 2013 年 11 月 21 日:初始版本
© . All rights reserved.