绘画板 13——变形 (下)

本贴最后更新于 3006 天前,其中的信息可能已经物是人非

github 地址: https://github.com/wangyuheng/painter

DEMO 地址: http://painter.crick.wang/

变形

变形这部分代码比较多,所以分为上下两部分。在(上)中已经实现了左侧中间点的变形操作。但是一共有 8 个操作点,为了避免混乱,抽离 handle.border.listener.js 提供 8 个点的变形方法。

y 轴移动

之前左侧中间点的操作可以视为 x 轴移动,现在只需要实现 y 轴移动的算法,即可实现 8 个点的移动。因为角落的四个点其实就是同时向 2 个方向移动。

以 topCenter 为例,设定 Top,以上为正方向,1 为向上运动,-1 为向下运动。

var tTop = 1;

计算鼠标 y 轴移动距离

var dy = currPoint.y - lastPoint.y;

屏幕左上角为(0,0)点,所以图形的新高度为

var height = ele.height() - tTop * dy;

判断 height,如果小于 0,说明达到图形的 y 轴 0 点,要根据 y 轴进行翻转。

var height = ele.height() - tTop * dy;
if (height > 0) {
	var newY = ele.y() + tTop * dy;
	ele.y(newY).height(height);
} else {
	//invert
	tTop = -tTop;
	ele.height(-height).matrix(new SVG.Matrix(ele).flip('y', ele.bbox().cy));
}

成员变量

根据 x、y 两个方向的移动,推测出需要如下成员变量

var lastPoint;
var xLeft;
var yTop;
var ele;

ele 可以在初始化时完成,为当前操作的元素,lastPoint、xLeft、yTop 需要在开始拖拽时初始化。

通用方法

为了节省代码,抽象了 4 个通用方法 left(dx)、right(dx)、top(dy)、bottom(dy)

8 个操作点根据需要,获取当前的鼠标移动距离,并调用其中的 1 或 2 个通用方法,即可实现变形效果。

绑定并触发

在构造函数中,除了初始化 ele,还需要给 ele 绑定对应的事件。

在 HandleBorder 中,监听 8 个操作点的 dragstart 和 dragmove 事件,调用对应方法。

var HandleBorderListener = function(targetElement) {
	ele = targetElement;
	ele.on('leftCenterDragStart', leftCenterDragStart);
	ele.on('leftCenterDragMove', leftCenterDragMove);
	ele.on('rightCenterDragStart', rightCenterDragStart);
	ele.on('rightCenterDragMove', rightCenterDragMove);
	ele.on('topCenterDragStart', topCenterDragStart);
	ele.on('topCenterDragMove', topCenterDragMove);
	ele.on('bottomCenterDragStart', bottomCenterDragStart);
	ele.on('bottomCenterDragMove', bottomCenterDragMove);
	ele.on('leftTopDragStart', leftTopDragStart);
	ele.on('leftTopDragMove', leftTopDragMove);
	ele.on('leftBottomDragStart', leftBottomDragStart);
	ele.on('leftBottomDragMove', leftBottomDragMove);
	ele.on('rightTopDragStart', rightTopDragStart);
	ele.on('rightTopDragMove', rightTopDragMove);
	ele.on('rightBottomDragStart', rightBottomDragStart);
	ele.on('rightBottomDragMove', rightBottomDragMove);
}

在 HandleBorder 中,在 create 方法中

_this.rectLeftCenter.on("dragstart", function() {
	_this.currentElement.fire("leftCenterDragStart", {
		currPoint: event.detail.p
	});
});
_this.rectLeftCenter.on("dragmove", function() {
	_this.currentElement.fire("leftCenterDragMove", {
		currPoint: event.detail.p
	});
});
_this.rectLeftCenter.on("afterdragmove", function() {
	_this.rebound(_this.currentElement.bbox());
});

完整代码

完整代码如下

(function() {
	var lastPoint;
	var xLeft;
	var yTop;
	var ele;

	function left(dx) {
		var width = ele.width() - xLeft * dx;
		if (width > 0) {
			var newX = ele.x() + xLeft * dx;
			ele.x(newX).width(width);
		} else {
			//invert
			xLeft = -xLeft;
			ele.x(ele.bbox().x2).width(-width).matrix(new SVG.Matrix(ele).flip('x', ele.bbox().cx));
		}
	}

	function right(dx) {
		var width = ele.width() - xLeft * dx;
		if (width > 0) {
			ele.width(width);
		} else {
			//invert
			xLeft = -xLeft;
			ele.width(-width).matrix(new SVG.Matrix(ele).flip('x', ele.bbox().cx));
		}
	}

	function top(dy) {
		var height = ele.height() - tTop * dy;
		if (height > 0) {
			var newY = ele.y() + tTop * dy;
			ele.y(newY).height(height);
		} else {
			//invert
			tTop = -tTop;
			ele.height(-height).matrix(new SVG.Matrix(ele).flip('y', ele.bbox().cy));
		}
	}

	function bottom(dy) {
		var height = ele.height() - tTop * dy;
		if (height > 0) {
			ele.height(height);
		} else {
			//invert
			tTop = -tTop;
			ele.height(-height).matrix(new SVG.Matrix(ele).flip('y', ele.bbox().cy));
		}
	}

	function leftCenterDragStart(data) {
		lastPoint = data.detail.currPoint;
		xLeft = 1;
	}

	function leftCenterDragMove(data) {
		var currPoint = data.detail.currPoint;
		var dx = currPoint.x - lastPoint.x;
		left(dx);
		lastPoint = currPoint;
	}

	function rightCenterDragStart(data) {
		lastPoint = data.detail.currPoint;
		xLeft = -1;
	}

	function rightCenterDragMove(data) {
		var currPoint = data.detail.currPoint;
		var dx = currPoint.x - lastPoint.x;
		right(dx);
		lastPoint = currPoint;
	}

	function topCenterDragStart(data) {
		lastPoint = data.detail.currPoint;
		tTop = 1;
	}

	function topCenterDragMove(data) {
		var currPoint = data.detail.currPoint;
		var dy = currPoint.y - lastPoint.y;
		top(dy);
		lastPoint = currPoint;
	}

	function bottomCenterDragStart(data) {
		lastPoint = data.detail.currPoint;
		tTop = -1;
	}

	function bottomCenterDragMove(data) {
		var currPoint = data.detail.currPoint;
		var dy = currPoint.y - lastPoint.y;
		bottom(dy);
		lastPoint = currPoint;
	}

	function leftTopDragStart(data) {
		lastPoint = data.detail.currPoint;
		xLeft = 1;
		tTop = 1;
	}

	function leftTopDragMove(data) {
		var currPoint = data.detail.currPoint;
		var dx = currPoint.x - lastPoint.x;
		var dy = currPoint.y - lastPoint.y;
		left(dx);
		top(dy);
		lastPoint = currPoint;
	}

	function leftBottomDragStart(data) {
		lastPoint = data.detail.currPoint;
		xLeft = 1;
		tTop = -1;
	}

	function leftBottomDragMove(data) {
		var currPoint = data.detail.currPoint;
		var dx = currPoint.x - lastPoint.x;
		var dy = currPoint.y - lastPoint.y;
		left(dx);
		bottom(dy);
		lastPoint = currPoint;
	}

	function rightTopDragStart(data) {
		lastPoint = data.detail.currPoint;
		xLeft = -1;
		tTop = 1;
	}

	function rightTopDragMove(data) {
		var currPoint = data.detail.currPoint;
		var dx = currPoint.x - lastPoint.x;
		var dy = currPoint.y - lastPoint.y;
		right(dx);
		top(dy);
		lastPoint = currPoint;
	}

	function rightBottomDragStart(data) {
		lastPoint = data.detail.currPoint;
		xLeft = -1;
		tTop = -1;
	}

	function rightBottomDragMove(data) {
		var currPoint = data.detail.currPoint;
		var dx = currPoint.x - lastPoint.x;
		var dy = currPoint.y - lastPoint.y;
		right(dx);
		bottom(dy);
		lastPoint = currPoint;
	}

	var HandleBorderListener = function(targetElement) {
		ele = targetElement;
		ele.on('leftCenterDragStart', leftCenterDragStart);
		ele.on('leftCenterDragMove', leftCenterDragMove);
		ele.on('rightCenterDragStart', rightCenterDragStart);
		ele.on('rightCenterDragMove', rightCenterDragMove);
		ele.on('topCenterDragStart', topCenterDragStart);
		ele.on('topCenterDragMove', topCenterDragMove);
		ele.on('bottomCenterDragStart', bottomCenterDragStart);
		ele.on('bottomCenterDragMove', bottomCenterDragMove);
		ele.on('leftTopDragStart', leftTopDragStart);
		ele.on('leftTopDragMove', leftTopDragMove);
		ele.on('leftBottomDragStart', leftBottomDragStart);
		ele.on('leftBottomDragMove', leftBottomDragMove);
		ele.on('rightTopDragStart', rightTopDragStart);
		ele.on('rightTopDragMove', rightTopDragMove);
		ele.on('rightBottomDragStart', rightBottomDragStart);
		ele.on('rightBottomDragMove', rightBottomDragMove);
	}

	this.HandleBorderListener = HandleBorderListener;
})();
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    407 引用 • 3578 回帖
  • SVG
    24 引用 • 73 回帖
  • Painter
    14 引用 • 31 回帖
  • 变形
    2 引用 • 7 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...