您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

381 行
9.2 KiB

/*
* PS 钢笔工具 控制逻辑
*/
define( function ( require, exports, module ) {
// 资源引入
var Bezier = require( "graphic/bezier" ),
Color = require( "graphic/color" ),
Pen = require( "graphic/pen" ),
Utils = require( "core/utils" ),
Vector = require( "graphic/vector" ),
// 引入可绘制的点集合
PointGroup = require( "../ps-pen/demo.pointgroup" ),
BezierPoint = require( "graphic/bezierpoint" );
function Controller ( paper ) {
this.paper = paper || null;
this.bezier = null;
this.bezierPoints = null;
this.pointGroup = null;
this.drawState = false;
// 记录当前是否处于更新状态
this.modifyState = false;
// 记录更新状态的持久信息
this._modifyStatus = null;
// 允许重新拖动编辑的
this.editable = false;
}
Utils.extend( Controller.prototype, {
takeover: function ( paper ) {
paper && ( this.paper = paper );
initListener( this );
},
enableDraw: function () {
this.drawState = true;
},
disableDraw: function () {
this.drawState = false;
},
enableModify: function () {
this.modifyState = true;
},
disableModify: function () {
this.modifyState = false;
},
// 设置更新状态
setModifyStatus: function ( status ) {
this._modifyStatus = status;
},
clearModifySatus: function () {
this._modifyStatus = null;
},
getModifyStatus: function () {
return this._modifyStatus;
},
enableEdit: function () {
this.editable = true;
},
disableEdit: function () {
this.editable = false;
},
setBezier: function ( bezier ) {
this.bezier = bezier;
this.bezierPoints = [];
return this;
},
getBezier: function () {
return this.bezier;
},
setPointGroup: function ( pointGroup ) {
this.pointGroup = pointGroup;
return this;
},
getPointGroup: function () {
return this.pointGroup;
},
addPoint: function ( point ) {
this.bezierPoints && this.bezierPoints.push( point );
return this;
},
getPoints: function () {
return this.bezierPoints;
}
} );
return Controller;
// 私有方法实现
// 初始化交互事件监听器
function initListener ( controller ) {
// 记录是否允许所有事件的监听
var isBegin = false,
// 记录是否需要更新曲线
isUpdateable = false,
paper = controller.paper,
currentBezier = null,
currentPointGroup = null;
paper.on( "mousedown", function ( e ) {
var point = null;
e.preventDefault();
if ( !controller.drawState ) {
return;
}
// 切换监听状态
if ( !isBegin ) {
isBegin = true;
currentBezier = createBezier( paper );
currentPointGroup = createPointGroup( paper );
listenPointGroup( currentPointGroup, controller );
//设置当前controller处理的贝塞尔曲线
controller.setBezier( currentBezier );
controller.setPointGroup( currentPointGroup );
}
isUpdateable = false;
// 获取当前鼠标点击在用户坐标系上的映射点
point = e.getPosition();
updateBezier( controller, point );
} );
// 绘制时 更新控制点
paper.on( "mousemove", function ( e ) {
var point = null,
bezierPoint = null;
e.preventDefault();
if ( !controller.drawState ) {
return;
}
if ( !isBegin || isUpdateable ) {
return;
}
point = e.getPosition();
currentBezier.getLastPoint().setForward( point.x, point.y );
currentPointGroup.getLastPoint().setForward( point.x, point.y );
} );
// 编辑时拖动更新
paper.on( "mousemove", function ( e ) {
var mousePoint = null,
currentPoint = null,
pointIndex = -1;
e.preventDefault();
// 不可编辑
if ( !controller.editable ) {
return;
}
mousePoint = e.getPosition();
pointIndex = controller._modifyStatus.pointIndex;
currentPoint = currentPointGroup.getPointByIndex( pointIndex );
switch ( controller._modifyStatus.pointType ) {
case PointGroup.TYPE_FORWARD:
currentPoint.setForward( mousePoint.x, mousePoint.y );
currentBezier.getPoint( pointIndex ).setForward( mousePoint.x, mousePoint.y );
break;
case PointGroup.TYPE_BACKWARD:
currentPoint.setBackward( mousePoint.x, mousePoint.y );
currentBezier.getPoint( pointIndex ).setBackward( mousePoint.x, mousePoint.y );
break;
case PointGroup.TYPE_VERTEX:
currentPoint.moveTo( mousePoint.x, mousePoint.y );
currentBezier.getPoint( pointIndex ).moveTo( mousePoint.x, mousePoint.y );
break;
}
} );
paper.on( "mouseup", function () {
if ( controller.drawState ) {
isUpdateable = isBegin;
} else if ( controller.modifyState ) {
controller.disableEdit();
// 清空状态
controller.clearModifySatus();
}
} );
}
// 画贝塞尔曲线
function updateBezier ( controller, point ) {
var bezierPoint = new BezierPoint( point.x, point.y, true );
//添加可绘制控制点
controller.getPointGroup().addPoint( bezierPoint.clone() );
//记录贝塞尔的控制点
controller.addPoint( bezierPoint );
//更新贝塞尔曲线的点
controller.getBezier().setPoints( controller.getPoints() );
}
// 创建一个新的贝塞尔
function createBezier ( paper ) {
var bezier = new Bezier();
bezier.stroke( new Pen( new Color( "black" ) ).setWidth( 100 ) );
paper.addShape( bezier );
return bezier;
}
function createPointGroup ( paper ) {
var pointGroup = new PointGroup();
paper.addShape( pointGroup );
return pointGroup;
}
// 监听点上的事件
function listenPointGroup ( pointGroup, controller ) {
pointGroup.on( "pointmousedown", function ( e ) {
var currentPoint = null,
currentType = null,
index = -1,
vertexWidth = 0;
// 非modify状态, 不处理
if ( !controller.modifyState ) {
return;
}
index = e.targetPointIndex;
currentType = e.targetPointType;
currentPoint = pointGroup.getPointByIndex( index );
// 获取到当前顶点的宽度
vertexWidth = pointGroup.getVertexWidth();
// 检查当前点击的点的控制点是否和顶点重叠
// 如果重叠了, 则认为点击是发生在forward的控制点上的
if ( currentType === PointGroup.TYPE_VERTEX ) {
//更新点类型
switch ( checkOverlapping( currentPoint, vertexWidth ) ) {
case 1:
currentType = PointGroup.TYPE_FORWARD;
break;
case 2:
currentType = PointGroup.TYPE_BACKWARD
break;
}
}
// 运行更新
controller.enableEdit();
controller.setModifyStatus( {
pointType: currentType,
pointIndex: index
} );
//更新当前的点
this.selectPoint( index );
} );
}
// 工具方法, 检测贝塞尔曲线上的点的控制点和顶点是否重叠在一起
// 参数distance控制了点之间的最小距离, 如果不大于该距离, 则认为是重叠的
// 返回值有: 0: 无重叠, 1: forward重叠, 2: backward重叠
function checkOverlapping ( bezierPoint, distance ) {
var forward = bezierPoint.getForward(),
backward = bezierPoint.getBackward(),
vertex = bezierPoint.getVertex();
if ( Vector.fromPoints( forward, vertex ).length() <= distance ) {
// forward重叠
return 1;
} else if ( Vector.fromPoints( backward, vertex ).length() <= distance ) {
// backward重叠
return 2;
}
// 无重叠
return 0;
}
} );