addpath support drag curve
This commit is contained in:
@@ -30,3 +30,5 @@ fonteditor 在线ttf字体编辑器
|
||||
11. 2015-1-26 改变项目存储方式为IndexedDB.
|
||||
|
||||
12. 2015-1-29 增加移动方向键改变glyf顺序.
|
||||
|
||||
13. 2015-2-5 添加轮廓支持拖拽曲线,支持`ctrl+Z`回退.
|
||||
|
||||
@@ -94,7 +94,11 @@ define(
|
||||
* 添加path
|
||||
*/
|
||||
addpath: function () {
|
||||
this.setMode('addpath');
|
||||
var me = this;
|
||||
// 此处由于监听down事件,需要延迟处理
|
||||
setTimeout(function () {
|
||||
me.setMode('addpath');
|
||||
}, 20);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -264,7 +264,7 @@ define(
|
||||
this.currentGroup.refresh();
|
||||
this.currentGroup.setMode('scale');
|
||||
|
||||
if (prevMode === 'bound') {
|
||||
if (prevMode === 'bound' || prevMode === 'addpath') {
|
||||
this.clicked = false;
|
||||
}
|
||||
else {
|
||||
|
||||
73
src/render/shape/BezierCurve.js
Normal file
73
src/render/shape/BezierCurve.js
Normal 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);
|
||||
}
|
||||
);
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user