addpath support drag curve

This commit is contained in:
kekee000
2015-02-05 02:09:07 +08:00
parent 99cea1be3f
commit 9b260d7f7a
7 changed files with 225 additions and 33 deletions

View File

@@ -30,3 +30,5 @@ fonteditor 在线ttf字体编辑器
11. 2015-1-26 改变项目存储方式为IndexedDB.
12. 2015-1-29 增加移动方向键改变glyf顺序.
13. 2015-2-5 添加轮廓支持拖拽曲线,支持`ctrl+Z`回退.

View File

@@ -94,7 +94,11 @@ define(
* 添加path
*/
addpath: function () {
this.setMode('addpath');
var me = this;
// 此处由于监听down事件需要延迟处理
setTimeout(function () {
me.setMode('addpath');
}, 20);
},
/**

View File

@@ -51,6 +51,8 @@ define(
}
}
/* eslint-disable max-depth */
/**
* 初始化渲染器
*/
@@ -219,11 +221,21 @@ define(
}
// 撤销
else if (e.keyCode === 90 && e.ctrlKey) {
me.execCommand('undo');
if (me.mode.undo) {
me.mode.undo.call(me, e);
}
else {
me.execCommand('undo');
}
}
// 恢复
else if (e.keyCode === 89 && e.ctrlKey) {
me.execCommand('redo');
if (me.mode.redo) {
me.mode.redo.call(me, e);
}
else {
me.execCommand('redo');
}
}
else {
@@ -249,6 +261,7 @@ define(
me.render.refresh();
});
}
/* eslint-enable max-depth */
return initRender;
}

View File

@@ -12,7 +12,7 @@ define(
var mode = {
click: function (e) {
down: function (e) {
var coverLayer = this.coverLayer;
var result = coverLayer.getShapeIn(e);
@@ -21,11 +21,16 @@ define(
if (result[0] && this.points.length > 1 && result[0] === this.points[0]) {
var points = this.points.map(function (p) {
return {
var ret = {
x: p.x,
y: p.y,
onCurve: true
y: p.y
};
if (p.onCurve) {
ret.onCurve = true;
}
return ret;
});
var shape = this.fontLayer.addShape('path', {
@@ -33,7 +38,9 @@ define(
});
this.fontLayer.refresh();
this.fire('change');
this.setMode('shapes', [shape]);
this.setMode('shapes', [shape], 'addpath');
}
// 添加控制点
else {
@@ -55,34 +62,61 @@ define(
var point = coverLayer.addShape({
type: 'point',
x: x,
y: y
y: y,
onCurve: true
});
if (this.points.length === 0) {
this.points.push(point);
if (this.points.length === 1) {
point.style = {
strokeColor: 'red'
};
}
else {
var p0 = this.points[this.points.length - 1];
coverLayer.addShape({
type: 'line',
p0: {
x: p0.x,
y: p0.y
},
p1: {
x: point.x,
y: point.y
}
});
var p0 = this.points[this.points.length - 2];
if (p0.onCurve) {
coverLayer.addShape({
type: 'line',
p0: {
x: p0.x,
y: p0.y
},
p1: {
x: point.x,
y: point.y
}
});
}
else {
coverLayer.addShape({
type: 'beziercurve',
points: this.points.slice(this.points.length - 3)
});
}
}
this.dashedLine.p0.x = point.x;
this.dashedLine.p0.y = point.y;
this.points.push(point);
coverLayer.refresh();
}
// 标记鼠标按住
this.downMouse = true;
},
up: function (e) {
this.downMouse = false;
if (this.curCurve) {
this.curCurve = null;
// 增加一个悬空的点,用来创建平滑曲线
this.points.push({
x: e.x,
y: e.y,
onCurve: false
});
}
},
move: function (e) {
@@ -96,11 +130,13 @@ define(
this.render.setCursor('crosshair');
}
var points = this.points;
var x = e.x;
var y = e.y;
var last = points[points.length - 1]; // 最后一个点
if (this.points.length) {
var last = this.points[this.points.length - 1];
// 配合shift和alt键设置水平或者垂直拖拽
if ((e.shiftKey || e.altKey) && points.length) {
if (e.shiftKey) {
y = last.y;
}
@@ -110,15 +146,78 @@ define(
}
}
// 如果鼠标被按住则可以拖出bezier曲线
if (this.downMouse && points.length > 2) {
// 设置倒数第二个点
var last2 = points[points.length - 2];
// 如果已经创建了曲线,则需要改变曲线形状
if (!this.curCurve && last2.onCurve) {
// 更新dashLine
this.dashedLine.p1.x = x;
this.dashedLine.p1.y = y;
this.dashedLine.disabled = false;
points.splice(points.length - 1, 0, {
x: 2 * last.x - x,
y: 2 * last.y - y,
onCurve: false
});
this.coverLayer.refresh();
this.coverLayer.shapes.splice(this.coverLayer.shapes.length - 1, 1);
this.curCurve = this.coverLayer.addShape({
type: 'beziercurve',
points: points.slice(points.length - 3)
});
}
else {
last2.x = 2 * last.x - x;
last2.y = 2 * last.y - y;
}
this.dashedLine.disabled = true;
this.coverLayer.refresh();
}
else if (points.length) {
// 更新dashLine
this.dashedLine.p1.x = x;
this.dashedLine.p1.y = y;
this.dashedLine.disabled = false;
this.coverLayer.refresh();
}
},
undo: function (e) {
// 移除上一个控制点
if (this.points.length) {
var points = this.points;
var shapes = this.coverLayer.shapes;
var last = points[points.length - 1];
var last2 = points[points.length - 2];
// 如果本段是曲线,并且上一个是悬空点
if (last && !last.onCurve) {
points.splice(points.length - 3, 3);
shapes.splice(shapes.length - 2, 2);
}
// 如果本段是曲线,并且上一个不是悬空点
else if (last2 && !last2.onCurve) {
points.splice(points.length - 2, 2);
shapes.splice(shapes.length - 2, 2);
}
else {
points.splice(points.length - 1, 1);
shapes.splice(shapes.length - 2, 2);
}
if (points.length) {
var point = points[points.length - 1];
this.dashedLine.p0.x = point.x;
this.dashedLine.p0.y = point.y;
}
else {
this.dashedLine.disabled = true;
}
this.coverLayer.refresh();
}
},
begin: function () {
this.coverLayer.clearShapes();
@@ -136,7 +235,7 @@ define(
end: function () {
this.points = this.dashedLine = null;
this.points = this.dashedLine = this.downMouse = this.curCurve = null;
this.coverLayer.clearShapes();
this.coverLayer.refresh();
this.render.setCursor('default');

View File

@@ -264,7 +264,7 @@ define(
this.currentGroup.refresh();
this.currentGroup.setMode('scale');
if (prevMode === 'bound') {
if (prevMode === 'bound' || prevMode === 'addpath') {
this.clicked = false;
}
else {

View File

@@ -0,0 +1,73 @@
/**
* @file 绘制bezier曲线
* @author mengke01(kekee000@gmail.com)
*/
define(
function (require) {
var isInsidePath = require('../../graphics/isInsidePath');
var pathAdjust = require('graphics/pathAdjust');
var computeBoundingBox = require('graphics/computeBoundingBox');
var proto = {
type: 'beziercurve',
adjust: function (shape, camera) {
var ratio = camera.ratio;
var x = camera.center.x;
var y = camera.center.y;
pathAdjust(shape.points, ratio, ratio, -x, -y);
pathAdjust(shape.points, 1, 1, x, y);
},
move: function (shape, mx, my) {
pathAdjust(shape.points, 1, 1, mx, my);
return shape;
},
getRect: function (shape) {
return computeBoundingBox.computePath(shape.points);
},
isIn: function (shape, x, y) {
var bound = computeBoundingBox.computePath(shape.points);
if (
x <= bound.x + bound.width
&& x >= bound.x
&& y <= bound.y + bound.height
&& y >= bound.y
) {
return isInsidePath(shape.points, {
x: x,
y: y
});
}
return false;
},
draw: function (ctx, shape) {
var points = shape.points;
// 二次bezier曲线
if (points.length === 3) {
ctx.moveTo(points[0].x, points[0].y);
ctx.quadraticCurveTo(points[1].x, points[1].y, points[2].x, points[2].y);
}
// 三次bezier曲线
else if (points.length === 4) {
ctx.moveTo(points[0].x, points[0].y);
ctx.bezierCurveTo(
points[1].x, points[1].y,
points[2].x, points[2].y,
points[3].x, points[3].y
);
}
}
};
return require('./Shape').derive(proto);
}
);

View File

@@ -19,7 +19,8 @@ define(
path: require('./Path'),
axis: require('./Axis'),
graduation: require('./Graduation'),
line: require('./Line')
line: require('./Line'),
beziercurve: require('./BezierCurve')
};
return support;