diff --git a/README.md b/README.md index da33080..1508f36 100644 --- a/README.md +++ b/README.md @@ -19,5 +19,4 @@ fonteditor 在线ttf字体编辑器 6. 2014-12-7 ttf编辑器增加百度编辑器样式. -7. 2014-12-13 ttf编辑器增加列表和查看器命令栏. - +7. 2014-12-13 ttf编辑器增加列表和查看器命令栏,增加glyf点吸附. \ No newline at end of file diff --git a/src/editor/command/referenceline.js b/src/editor/command/referenceline.js index a2cd0d0..6ec387e 100644 --- a/src/editor/command/referenceline.js +++ b/src/editor/command/referenceline.js @@ -17,23 +17,21 @@ define( */ addreferenceline: function(x, y) { if(x > 20) { - this.axisLayer.addShape('line', { + this.referenceLineLayer.addShape('line', { p0: { x: x - }, - style: this.options.referenceline.style + } }); } if(y > 20) { - this.axisLayer.addShape('line', { + this.referenceLineLayer.addShape('line', { p0: { y: y - }, - style: this.options.referenceline.style + } }); } - this.axisLayer.refresh(); + this.referenceLineLayer.refresh(); }, /** @@ -46,12 +44,12 @@ define( lines.push(x); } - var axisLayer = this.axisLayer; + var referenceLineLayer = this.referenceLineLayer; var rightSideBearing = this.rightSideBearing; // 获取选中的参考线 if(x > 20 || y > 20) { - var result = this.axisLayer.getShapeIn(x, y); + var result = this.referenceLineLayer.getShapeIn(x, y); lines = lines.concat(result); } @@ -61,25 +59,25 @@ define( }); lines.forEach(function(l) { - axisLayer.removeShape(l); + referenceLineLayer.removeShape(l); }); - axisLayer.refresh(); + referenceLineLayer.refresh(); }, /** * 清除参考线 */ clearreferenceline: function() { - var axisLayer = this.axisLayer; + var referenceLineLayer = this.referenceLineLayer; var rightSideBearing = this.rightSideBearing; - var lines = axisLayer.shapes.filter(function(line) { + var lines = referenceLineLayer.shapes.filter(function(line) { return line.type === 'line' && line !== rightSideBearing; }); lines.forEach(function(l) { - axisLayer.removeShape(l); + referenceLineLayer.removeShape(l); }); - axisLayer.refresh(); + referenceLineLayer.refresh(); } }; } diff --git a/src/editor/controller/initAxis.js b/src/editor/controller/initAxis.js index bbfab49..a00b59f 100644 --- a/src/editor/controller/initAxis.js +++ b/src/editor/controller/initAxis.js @@ -37,7 +37,7 @@ define( })); // 右支撑 - this.rightSideBearing = this.axisLayer.addShape('line', { + this.rightSideBearing = this.referenceLineLayer.addShape('line', { id: 'rightSideBearing', p0: { x: options.unitsPerEm / 2 diff --git a/src/editor/controller/initFont.js b/src/editor/controller/initFont.js index a8ad643..e7eb227 100644 --- a/src/editor/controller/initFont.js +++ b/src/editor/controller/initFont.js @@ -74,7 +74,7 @@ define( // 设置参考线 var advanceWidth = font.advanceWidth; this.rightSideBearing.p0.x = originX + (advanceWidth || this.options.unitsPerEm) * scale; - this.axisLayer.refresh(); + this.referenceLineLayer.refresh(); this.setMode(); return this; @@ -249,7 +249,7 @@ define( if (undefined !== options.rightSideBearing) { this.font.rightSideBearing = options.rightSideBearing; this.rightSideBearing.p0.x = box.x + box.width + offset + options.rightSideBearing * scale; - this.axisLayer.refresh(); + this.referenceLineLayer.refresh(); } } else { diff --git a/src/editor/controller/initLayer.js b/src/editor/controller/initLayer.js index 0031c0e..d43b7f2 100644 --- a/src/editor/controller/initLayer.js +++ b/src/editor/controller/initLayer.js @@ -16,12 +16,10 @@ define( */ function initLayer() { - this.coverLayer = this.render.addLayer('cover', lang.extend({ - level: 30, - fill: false, - strokeColor: 'green', - fillColor: 'white' - }, this.options.coverLayer)); + this.axisLayer = this.render.addLayer('axis', { + level: 10, + fill: false + }); this.fontLayer = this.render.addLayer('font', lang.extend({ level: 20, @@ -31,13 +29,22 @@ define( strokeSeparate: false }, this.options.fontLayer)); - this.axisLayer = this.render.addLayer('axis', { - level: 10, - fill: false + this.coverLayer = this.render.addLayer('cover', lang.extend({ + level: 30, + fill: false, + strokeColor: 'green', + fillColor: 'white' + }, this.options.coverLayer)); + + this.referenceLineLayer = this.render.addLayer('referenceline', { + level: 40, + fill: false, + strokeColor: this.options.referenceline.style.strokeColor }); + this.graduationLayer = this.render.addLayer('graduation', { - level: 40, + level: 50, fill: false, disabled: true }); diff --git a/src/editor/group/ShapesGroup.js b/src/editor/group/ShapesGroup.js index 901b4a8..331a619 100644 --- a/src/editor/group/ShapesGroup.js +++ b/src/editor/group/ShapesGroup.js @@ -54,33 +54,54 @@ define( // 设置吸附选项 if (this.mode === 'move' && this.editor.sorption.isEnable()) { - var sorptionShapes = []; - var shapes = this.shapes; - var bound = this.bound; - // 加入bound - sorptionShapes.push({ - points: [ - { - x: bound.x, - y: bound.y, - onCurve: true - }, - { - x: bound.x + bound.width, - y: bound.y + bound.height, - onCurve: true + if (this.editor.sorption.enableShape) { + var sorptionShapes = []; + var shapes = this.shapes; + var bound = this.bound; + + // 加入此group的bound + sorptionShapes.push({ + points: [ + { + x: bound.x, + y: bound.y, + onCurve: true + }, + { + x: bound.x + bound.width, + y: bound.y + bound.height, + onCurve: true + } + ] + }); + + // 过滤需要吸附的对象 + this.editor.fontLayer.shapes.forEach(function(shape) { + if (shapes.indexOf(shape) < 0) { + sorptionShapes.push(shape); } - ] - }); + }); - // 过滤需要吸附的对象 - this.editor.fontLayer.shapes.forEach(function(shape) { - if (shapes.indexOf(shape) < 0) { - sorptionShapes.push(shape); - } - }); - this.editor.sorption.setShapes(sorptionShapes); + // 添加参考线 + var referenceLines = this.editor.referenceLineLayer.shapes; + var xAxisArray = []; + var yAxisArray = []; + referenceLines.forEach(function(shape) { + if (undefined !== shape.p0.x) { + xAxisArray.push(shape.p0.x); + } + if (undefined !== shape.p0.y) { + yAxisArray.push(shape.p0.y); + } + }); + + + this.editor.sorption.clear(); + sorptionShapes.length && this.editor.sorption.addShapes(sorptionShapes); + xAxisArray.length && this.editor.sorption.addXAxis(xAxisArray); + yAxisArray.length && this.editor.sorption.addYAxis(yAxisArray); + } } }; @@ -91,7 +112,8 @@ define( ShapesGroup.prototype.transform = function(point, camera, key) { if (this.mode === 'move') { moveTransform.call( - this, camera, + this, + camera, key.ctrlKey ? false : key.altKey, key.ctrlKey ? false : key.shiftKey, this.editor.sorption.isEnable() diff --git a/src/editor/mode/bound.js b/src/editor/mode/bound.js index 5305b87..4ff0fab 100644 --- a/src/editor/mode/bound.js +++ b/src/editor/mode/bound.js @@ -35,7 +35,7 @@ define( } // 参考线模式 - var result = this.axisLayer.getShapeIn(e); + var result = this.referenceLineLayer.getShapeIn(e); if(result) { var line = result[0]; this.setMode('referenceline', referenceline.dragLine, line, e); diff --git a/src/editor/mode/point.js b/src/editor/mode/point.js index 01766a1..053a0ae 100644 --- a/src/editor/mode/point.js +++ b/src/editor/mode/point.js @@ -39,12 +39,6 @@ define( this.contextMenu.hide(); var command = e.command; - // 是否编辑器支持 - if(this.supportCommand(command)) { - this.execCommand(command); - return; - } - var fontLayer = this.fontLayer; var command = e.command; var shape = this.curShape; @@ -74,6 +68,10 @@ define( else if (command == 'asStart') { shape.points = points.slice(pointId).concat(points.slice(0, pointId)); } + else if(this.supportCommand(command)) { + this.execCommand(command); + return; + } refreshControlPoints.call(this, shape); @@ -161,6 +159,37 @@ define( this.curPoint._style = lang.clone(this.curPoint.style); this.curPoint.style.fillColor = 'green'; + // 设置吸附选项 + if (this.sorption.isEnable()) { + + if (this.sorption.enableShape) { + + var xAxisArray = []; + var yAxisArray = []; + + // 过滤需要吸附的对象 + this.curShape.points.forEach(function(p) { + xAxisArray.push(p.x); + yAxisArray.push(p.y); + }); + + // 添加参考线 + var referenceLines = this.referenceLineLayer.shapes; + referenceLines.forEach(function(shape) { + if (undefined !== shape.p0.x) { + xAxisArray.push(shape.p0.x); + } + if (undefined !== shape.p0.y) { + yAxisArray.push(shape.p0.y); + } + }); + + this.sorption.clear(); + xAxisArray.length && this.sorption.addXAxis(xAxisArray); + yAxisArray.length && this.sorption.addYAxis(yAxisArray); + } + } + this.coverLayer.refresh(); } }, @@ -189,6 +218,18 @@ define( current.y = reserved.y + camera.event.deltaY; } + if (this.sorption.isEnable()) { + var result; + + if (result = this.sorption.detectX(current.x)) { + current.x = result.axis; + } + + if (result = this.sorption.detectY(current.y)) { + current.y = result.axis; + } + } + current.point.x = current.x; current.point.y = current.y; @@ -201,6 +242,11 @@ define( var reserved = this.curShape.points[this.curPoint.pointId]; reserved.x = this.curPoint.x; reserved.y = this.curPoint.y; + + if (this.sorption.isEnable()) { + this.sorption.clear(); + } + this.fontLayer.refresh(); } this.fire('change'); diff --git a/src/editor/mode/referenceline.js b/src/editor/mode/referenceline.js index 79c3489..33c8f3e 100644 --- a/src/editor/mode/referenceline.js +++ b/src/editor/mode/referenceline.js @@ -32,12 +32,12 @@ define( else { line.p0.y += camera.my; } - this.axisLayer.refresh(); + this.referenceLineLayer.refresh(); } else if (this._dragMode === mode.newLine) { if (e.startX <= 20 && e.x > 20) { - this.currentLine = this.axisLayer.addShape('line', { + this.currentLine = this.referenceLineLayer.addShape('line', { p0: { x: e.x }, @@ -46,7 +46,7 @@ define( this.render.setCursor('col-resize'); } else if (e.startY <= 20 && e.y > 20) { - this.currentLine = this.axisLayer.addShape('line', { + this.currentLine = this.referenceLineLayer.addShape('line', { p0: { y: e.y }, @@ -72,7 +72,7 @@ define( // 如果右支撑被移除去了 if(line === this.rightSideBearing && line.p0.x < 20) { line.p0.x = this.p0.x; - this.axisLayer.refresh(); + this.referenceLineLayer.refresh(); } // 拖出刻度线,代表删除 else if ( diff --git a/src/editor/options.js b/src/editor/options.js index d051869..70480e3 100644 --- a/src/editor/options.js +++ b/src/editor/options.js @@ -27,7 +27,7 @@ define( // 辅助线 referenceline: { style: { - strokeColor: 'darkblue' + strokeColor: '#0FF' } }, diff --git a/src/editor/widget/Sorption.js b/src/editor/widget/Sorption.js index 11e48b0..a05452b 100644 --- a/src/editor/widget/Sorption.js +++ b/src/editor/widget/Sorption.js @@ -53,6 +53,8 @@ define( this.delta = options.delta || 5; // 吸附对象 offset this.enableGrid = options.enableGrid || false; this.enableShape = options.enableShape || true; + this.xAxis = []; + this.yAxis = []; } /** @@ -70,9 +72,10 @@ define( * * @return {this} */ - Sorption.prototype.setShapes = function(shapes) { - var xAxis = []; - var yAxis = []; + Sorption.prototype.addShapes = function(shapes) { + var xAxis = this.xAxis; + var yAxis = this.yAxis; + for (var i = shapes.length - 1; i >= 0; i--) { var box = computeBoundingBox.computePath(shapes[i].points); var cx = box.x + box.width / 2; @@ -113,14 +116,47 @@ define( yAxis.sort(function(a, b) { return a.axis - b.axis; }); + }; - this.xAxis = xAxis; - this.yAxis = yAxis; + /** + * 设置x轴吸附 + * @param {Array.} xAxisArray x轴坐标集合 + * @return {this} + */ + Sorption.prototype.addXAxis = function(xAxisArray) { + var xAxis = this.xAxis; + xAxisArray.forEach(function(x) { + xAxis.push({ + axis: x, + y: 0 + }); + }); + xAxis.sort(function(a, b) { + return a.axis - b.axis; + }); + }; + + /** + * 设置y轴吸附 + * @param {Array.} yAxisArray y轴坐标集合 + * @return {this} + */ + Sorption.prototype.addYAxis = function(yAxisArray) { + var yAxis = this.yAxis; + yAxisArray.forEach(function(y) { + yAxis.push({ + axis: y, + x: 0 + }); + }); + yAxis.sort(function(a, b) { + return a.axis - b.axis; + }); }; /** * 检查x轴是否有可用的吸附 - * + * @param {number} x x坐标 * @return {this} */ Sorption.prototype.detectX = function(x) { @@ -149,7 +185,7 @@ define( /** * 检查y轴是否有可用的吸附 - * + * @param {number} y y坐标 * @return {this} */ Sorption.prototype.detectY = function(y) { @@ -189,7 +225,8 @@ define( * @return {this} */ Sorption.prototype.clear = function() { - this.xAxis = this.yAxis = null; + this.xAxis.length = 0; + this.yAxis.length = 0; }; /**