绘画板 13——变形 (下)
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;
})();