From 2d6c852edf4a7bc3e70e5064795087d5bff9426d Mon Sep 17 00:00:00 2001 From: kekee000 Date: Tue, 9 Sep 2014 21:40:07 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=80=89=E6=8B=A9=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demo/css/render.css | 1 - demo/css/render.less | 1 - demo/editor.html | 29 ++++ demo/js/editor.js | 32 ++++ src/editor/Editor.js | 197 ++++++++++++++++++++++++ src/editor/ShapeGroup.js | 255 ++++++++++++++++++++++++++++++++ src/editor/main.js | 35 +++++ src/editor/util/adjustShape.js | 62 ++++++++ src/graphics/isSegmentCross.js | 15 +- src/render/Camera.js | 12 ++ src/render/Controller.js | 20 +-- src/render/Layer.js | 15 +- src/render/Painter.js | 10 ++ src/render/main.js | 10 +- src/render/render.js | 38 ++--- src/render/shape/CirclePoint.js | 67 +++++++++ src/render/shape/DashedRect.js | 65 ++++++++ src/render/shape/Path.js | 2 +- src/render/shape/Point.js | 77 ++++++++++ src/render/shape/Rect.js | 26 ++-- src/render/shape/support.js | 3 + 21 files changed, 909 insertions(+), 63 deletions(-) create mode 100644 demo/editor.html create mode 100644 demo/js/editor.js create mode 100644 src/editor/Editor.js create mode 100644 src/editor/ShapeGroup.js create mode 100644 src/editor/main.js create mode 100644 src/editor/util/adjustShape.js create mode 100644 src/render/shape/CirclePoint.js create mode 100644 src/render/shape/DashedRect.js create mode 100644 src/render/shape/Point.js diff --git a/demo/css/render.css b/demo/css/render.css index f992f9d..13c67fc 100644 --- a/demo/css/render.css +++ b/demo/css/render.css @@ -22,6 +22,5 @@ html { #render-view { width: 100%; height: 100%; - background: #F0F0F0; position: relative; } diff --git a/demo/css/render.less b/demo/css/render.less index 3397ee8..56ec46f 100644 --- a/demo/css/render.less +++ b/demo/css/render.less @@ -7,6 +7,5 @@ body, html { #render-view { width: 100%; height: 100%; - background: #F0F0F0; position: relative; } \ No newline at end of file diff --git a/demo/editor.html b/demo/editor.html new file mode 100644 index 0000000..90c04c4 --- /dev/null +++ b/demo/editor.html @@ -0,0 +1,29 @@ + + + + + 测试render + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/demo/js/editor.js b/demo/js/editor.js new file mode 100644 index 0000000..b61c100 --- /dev/null +++ b/demo/js/editor.js @@ -0,0 +1,32 @@ +/** + * @file render.js + * @author mengke01 + * @date + * @description + * editor 组件测试 + */ + +define( + function(require) { + + var editor = require('editor/main'); + var shape_baidu = require('./shape-baidu'); + + var currentEditor; + + var entry = { + + /** + * 初始化 + */ + init: function () { + currentEditor = editor.create($('#render-view').get(0)); + currentEditor.setFont(shape_baidu); + } + }; + + entry.init(); + + return entry; + } +); diff --git a/src/editor/Editor.js b/src/editor/Editor.js new file mode 100644 index 0000000..4e1566c --- /dev/null +++ b/src/editor/Editor.js @@ -0,0 +1,197 @@ +/** + * @file Editor.js + * @author mengke01 + * @date + * @description + * 字体编辑控制器 + */ + + +define( + function(require) { + var lang = require('common/lang'); + var selectShape = require('render/util/selectShape'); + var computeBoundingBox = require('graphics/computeBoundingBox'); + var pathAdjust = require('render/util/pathAdjust'); + var glyf2path = require('ttf/util/glyf2path'); + var ShapeGroup = require('./ShapeGroup'); + + /** + * 初始化 + */ + function initRender() { + var me = this; + var render = this.render; + + render.capture.on('wheel', function(e) { + var defaultRatio = render.options.defaultRatio || 1.2; + var ratio = e.delta > 0 ? defaultRatio : 1 / defaultRatio; + + render.camera.ratio = ratio; + render.camera.center.x = e.x; + render.camera.center.y = e.y; + render.camera.scale *= ratio; + + render.painter.refresh(); + render.camera.ratio = 1; + + }); + + render.capture.on('down', function(e) { + + var result = render.getLayer('cover').getShapeIn(e); + + if(result) { + if (me.currentGroup) { + me.currentPoint = lang.clone(result[0]); + me.currentGroup.beginTransform(me.currentPoint); + } + } + else { + + if (me.currentGroup) { + me.currentGroup.dispose(); + me.currentGroup = null; + } + + result = render.getLayer('font').getShapeIn(e); + + if(result) { + var shape = result[0]; + if (result.length > 1) { + shape = selectShape(result); + } + me.currentGroup = new ShapeGroup(shape, render); + } + } + + render.camera.startx = e.x; + render.camera.starty = e.y; + render.camera.x = e.x; + render.camera.y = e.y; + }); + + render.capture.on('drag', function(e) { + + if(me.currentGroup) { + + var mx = render.camera.x; + var my = render.camera.y; + + render.camera.x = e.x; + render.camera.y = e.y; + + if (me.currentPoint) { + me.currentGroup.transform(me.currentPoint, render.camera); + } + else { + me.currentGroup.move(e.x - mx, e.y - my); + } + } + }); + + render.capture.on('dragend', function(e) { + if (me.currentGroup) { + if (me.currentPoint) { + me.currentGroup.finishTransform(me.currentPoint); + me.currentPoint = null; + } + } + + }); + } + + function initLayer() { + this.render.addLayer('cover', { + level: 30, + stroke: true, + strokeColor: 'green' + }); + this.render.addLayer('font', { + level: 20 + }); + this.render.addLayer('axis', { + level: 10, + stroke: true + }); + } + + /** + * Render控制器 + * @param {Object} options 参数 + * @constructor + */ + function Editor(options) { + this.options = options || {}; + } + + /** + * 设置渲染器 + */ + Editor.prototype.setRender = function(render) { + this.render = render; + initRender.call(this); + initLayer.call(this); + return this; + }; + + /** + * 设置渲染器 + */ + Editor.prototype.setFont = function(font) { + var paths = glyf2path(font); + + var width = this.render.painter.width; + var height = this.render.painter.height; + var offsetX = (width - (font.xMax - font.xMin)) / 2; + var offsetY = (height - (font.yMax - font.yMin)) / 2; + + // 构造形状集合 + var shapes = paths.map(function(path) { + var shape = {}; + var bound = computeBoundingBox.computePath(path); + + shape.points = pathAdjust(path, 1, -bound.x, -bound.y); + shape.x = bound.x + offsetX; + shape.y = bound.y + offsetY; + shape.width = bound.width; + shape.height = bound.height; + return shape; + }); + + this.shapes = shapes; + this.font = font; + + // 渲染形状 + this.render.reset(); + + var fontLayer = this.render.painter.getLayer('font'); + + this.shapes.forEach(function(shape) { + fontLayer.addShape('path', shape); + }); + + this.render.refresh(); + + return this; + }; + + /** + * 刷新编辑器组件 + */ + Editor.prototype.refresh = function() { + this.render.refresh(); + return this; + }; + + /** + * 注销 + */ + Editor.prototype.dispose = function() { + this.render && this.render.dispose(); + this.options = this.render = null; + }; + + return Editor; + } +); diff --git a/src/editor/ShapeGroup.js b/src/editor/ShapeGroup.js new file mode 100644 index 0000000..324bdf2 --- /dev/null +++ b/src/editor/ShapeGroup.js @@ -0,0 +1,255 @@ +/** + * @file ShapeGroup.js + * @author mengke01 + * @date + * @description + * 字体编辑控制器 + */ + + +define( + function(require) { + var adjustShape = require('./util/adjustShape'); + var lang = require('common/lang'); + + /** + * 获取bound边界 + */ + function updateControls(bound) { + + if (!this.controls) { + this.controls = [{ + type: 'dashedrect', + selectable: false + }]; + for (var i = 0; i < 8; i++) { + this.controls.push({ + type: 'point' + }); + } + } + + var points = [ + // 虚线框 + { + x: bound.x, + y: bound.y, + width: bound.width, + height: bound.height + }, + + // 控制点 + /* + 1 5 2 + 8 6 + 4 7 3 + */ + {x: bound.x, y: bound.y, pos: 1}, + {x: bound.x + bound.width, y: bound.y, pos: 2}, + {x: bound.x + bound.width, y: bound.y + bound.height, pos: 3}, + {x: bound.x, y: bound.y + bound.height, pos: 4}, + {x: bound.x + bound.width / 2, y: bound.y, pos: 5}, + {x: bound.x + bound.width, y: bound.y + bound.height / 2, pos: 6}, + {x: bound.x + bound.width / 2, y: bound.y + bound.height, pos: 7}, + {x: bound.x, y: bound.y + bound.height / 2, pos: 8}, + ]; + + var controls = this.controls; + points.forEach(function(p, index) { + lang.extend(controls[index], p); + }); + + var coverLayer = this.render.getLayer('cover'); + coverLayer.clearShapes(); + controls.forEach(function(shape) { + coverLayer.addShape(shape); + }); + } + + /** + * 选择组控制器 + */ + function Group(shape, render) { + this.shape = shape; + this.render = render; + + updateControls.call(this, shape); + this.render.getLayer('cover').refresh(); + } + + /** + * 根据控制点做图形变换 + */ + Group.prototype.beginTransform = function(point) { + this.originShape = lang.clone(this.shape); + }; + + /** + * 根据控制点做图形变换 + */ + Group.prototype.transform = function(point, camera) { + var bound = this.originShape; + + var mx = camera.x - camera.startx; + var my = camera.y - camera.starty; + + // x, y, xscale, yscale + var matrix = [ + bound.x, + bound.y, + 1, 1 + ]; + + switch (point.pos) { + case 1: + matrix[2] = (bound.width - mx) / bound.width; + matrix[3] = (bound.height - my) / bound.height; + + if(matrix[2] >= 0 && matrix[3] >= 0) { + matrix[0] = camera.x; + matrix[1] = camera.y; + } + else if(matrix[2] < 0 && matrix[3] > 0) { + matrix[0] = bound.x + bound.width; + matrix[1] = camera.y; + } + else if(matrix[2] < 0 && matrix[3] < 0) { + matrix[0] = bound.x + bound.width; + matrix[1] = bound.y + bound.height; + } + else { + matrix[0] = camera.x; + matrix[1] = bound.y + bound.height; + } + break; + + case 2: + matrix[2] = (bound.width + mx) / bound.width; + matrix[3] = (bound.height - my) / bound.height; + + if(matrix[2] >= 0 && matrix[3] >= 0) { + matrix[0] = bound.x; + matrix[1] = camera.y; + } + else if(matrix[2] < 0 && matrix[3] > 0) { + matrix[0] = camera.x; + matrix[1] = camera.y; + } + else if(matrix[2] < 0 && matrix[3] < 0) { + matrix[0] = camera.x; + matrix[1] = bound.y + bound.height; + } + else { + matrix[0] = bound.x; + matrix[1] = bound.y + bound.height; + } + + break; + + case 3: + matrix[2] = (bound.width + mx) / bound.width; + matrix[3] = (bound.height + my) / bound.height; + matrix[0] = Math.min(bound.x, camera.x); + matrix[1] = Math.min(bound.y, camera.y); + break; + + case 4: + matrix[2] = (bound.width - mx) / bound.width; + matrix[3] = (bound.height + my) / bound.height; + + if(matrix[2] >= 0 && matrix[3] >= 0) { + matrix[0] = camera.x; + matrix[1] = bound.y; + } + else if(matrix[2] < 0 && matrix[3] > 0) { + matrix[0] = bound.x + bound.width; + matrix[1] = bound.y; + } + else if(matrix[2] < 0 && matrix[3] < 0) { + matrix[0] = bound.x + bound.width; + matrix[1] = camera.y; + } + else { + matrix[0] = camera.x; + matrix[1] = camera.y; + } + + break; + + case 5: + matrix[3] = (bound.height - my) / bound.height; + matrix[0] = bound.x; + matrix[1] = matrix[3] > 0 ? camera.y : bound.y + bound.height; + break; + + case 7: + matrix[3] = (bound.height + my) / bound.height; + matrix[0] = bound.x; + matrix[1] = matrix[3] > 0 ? bound.y : camera.y; + break; + + case 6: + matrix[2] = (bound.width + mx) / bound.width; + matrix[0] = matrix[2] > 0 ? bound.x : camera.x; + matrix[1] = bound.y; + break; + + case 8: + matrix[2] = (bound.width - mx) / bound.width; + matrix[0] = matrix[2] > 0 ? camera.x : bound.x + bound.width; + matrix[1] = bound.y; + break; + }; + + var shape = adjustShape(lang.clone(this.originShape), matrix); + + lang.extend(this.shape, shape); + + this.render.getLayer('font').refresh(); + var coverLayer = this.render.getLayer('cover'); + coverLayer.clearShapes(); + coverLayer.addShape({ + type: 'dashedrect', + x: shape.x, + y: shape.y, + width: shape.width, + height: shape.height + }); + coverLayer.refresh(); + }; + + /** + * 刷新group信息 + */ + Group.prototype.finishTransform = function() { + delete this.originShape; + updateControls.call(this, this.shape); + this.render.getLayer('cover').refresh(); + }; + + /** + * 移动到指定位置 + */ + Group.prototype.move = function(x, y) { + var fontLayer = this.render.painter.getLayer(this.shape.layerId); + fontLayer.move(x, y, this.shape) + fontLayer.refresh(); + + var coverLayer = this.render.getLayer('cover'); + coverLayer.move(x, y) + coverLayer.refresh(); + }; + + /** + * 注销 + */ + Group.prototype.dispose = function() { + var coverLayer = this.render.getLayer('cover'); + coverLayer.clearShapes(); + coverLayer.refresh(); + this.shape = this.controls = this.render = null; + }; + + return Group; + } +) \ No newline at end of file diff --git a/src/editor/main.js b/src/editor/main.js new file mode 100644 index 0000000..95d3a84 --- /dev/null +++ b/src/editor/main.js @@ -0,0 +1,35 @@ +/** + * @file main.js + * @author mengke01 + * @date + * @description + * 编辑器主函数 + */ + + +define( + function(require) { + + var render = require('render/main'); + var Editor = require('./Editor'); + var exports = {}; + + /** + * 创建一个编辑器 + * @param {HTMLElement} main 主控区域 + * @param {Object} options 创建参数 + * @param {Controller} controller 控制器函数 + * @return {Render} render对象 + */ + exports.create = function(main, options) { + options = options || {}; + var editor = new Editor(options); + var opt = options.renderOptions || {}; + opt.controller = editor; + render.create(main, opt); + return editor; + }; + + return exports; + } +); diff --git a/src/editor/util/adjustShape.js b/src/editor/util/adjustShape.js new file mode 100644 index 0000000..4981455 --- /dev/null +++ b/src/editor/util/adjustShape.js @@ -0,0 +1,62 @@ +/** + * @file adjustShape.js + * @author mengke01 + * @date + * @description + * 根据相对值,调整shape大小 + */ + + +define( + function(require) { + + /** + * 根据相对值,调整shape大小 + */ + function adjustShape(shape, matrix) { + var i = -1; + var l = shape.points.length; + var point; + + var scaleX = matrix[2]; + var scaleY = matrix[3]; + var offsetX = 0; + var offsetY = 0; + + if (scaleX < 0) { + offsetX = -shape.width; + } + + if(scaleY < 0) { + offsetY = -shape.height; + } + + while (++i < l) { + var point = shape.points[i]; + switch (point.c) { + case 'M': + case 'L': + point.p.x = scaleX * (point.p.x + offsetX); + point.p.y = scaleY * (point.p.y + offsetY); + break; + case 'Q': + point.p.x = scaleX * (point.p.x + offsetX); + point.p.y = scaleY * (point.p.y + offsetY); + point.p1.x = scaleX * (point.p1.x + offsetX); + point.p1.y = scaleY * (point.p1.y + offsetY); + break; + } + } + + shape.x = matrix[0]; + shape.y = matrix[1]; + shape.width = shape.width * Math.abs(scaleX); + shape.height = shape.height * Math.abs(scaleY); + + return shape; + } + + + return adjustShape; + } +); \ No newline at end of file diff --git a/src/graphics/isSegmentCross.js b/src/graphics/isSegmentCross.js index 0af9358..de90eb0 100644 --- a/src/graphics/isSegmentCross.js +++ b/src/graphics/isSegmentCross.js @@ -10,24 +10,13 @@ define( function(require) { var isBoundingBoxCross = require('./isBoundingBoxCross'); - var ceil = require('./util').ceil; + var ceil = require('./util').ceil; + var isPointInBound = require('./util').isPointInBound; var matrix = require('./matrix'); var multi = matrix.multi; var minus = matrix.minus; var plus = matrix.plus; - /** - * 判断点是否在bounding box内部 - * - * @return {boolean} 是否 - */ - function isPointInBound(bound, p) { - return p.x <= bound.x + bound.width - && p.x >= bound.x - && p.y <= bound.y + bound.height - && p.y >= bound.y - } - /** * 过滤相交重叠线段上的点 */ diff --git a/src/render/Camera.js b/src/render/Camera.js index c914c6d..3e5e912 100644 --- a/src/render/Camera.js +++ b/src/render/Camera.js @@ -26,6 +26,18 @@ define( this.scale = scale || 1; } + /** + * 重置camera + */ + Camera.prototype.reset = function() { + this.center = { + x: 0, + y: 0 + }; + this.ratio = 1; + this.scale = 1; + }; + /** * 注销Camera */ diff --git a/src/render/Controller.js b/src/render/Controller.js index b75b75f..b238b44 100644 --- a/src/render/Controller.js +++ b/src/render/Controller.js @@ -32,7 +32,7 @@ define( }); render.capture.on('down', function(e) { - var result = render.painter.getShapeIn(e); + var result = render.getShapeIn(e); if(result) { if (result.length > 1) { @@ -42,30 +42,30 @@ define( render.selectedShape = result[0]; } } - render.camera.mx = e.x; - render.camera.my = e.y; + render.camera.x = e.x; + render.camera.y = e.y; }); render.capture.on('drag', function(e) { var shape = render.selectedShape; if(shape) { - render.painter.getLayer(shape.layerId) - .move(e.x - render.camera.mx, e.y - render.camera.my, shape) + render.getLayer(shape.layerId) + .move(e.x - render.camera.x, e.y - render.camera.y, shape) .refresh(); } else { - render.painter.move(e.x - render.camera.mx, e.y - render.camera.my) + render.move(e.x - render.camera.x, e.y - render.camera.y) .refresh(); } - render.camera.mx = e.x; - render.camera.my = e.y; + render.camera.x = e.x; + render.camera.y = e.y; }); render.capture.on('dragend', function(e) { var shape = render.selectedShape; if(shape) { - render.painter.getLayer(shape.layerId) - .move(e.x - render.camera.mx, e.y - render.camera.my, shape) + render.getLayer(shape.layerId) + .move(e.x - render.camera.x, e.y - render.camera.y, shape) .refresh(); render.selectedShape = null; } diff --git a/src/render/Layer.js b/src/render/Layer.js index e67e464..f74d1e5 100644 --- a/src/render/Layer.js +++ b/src/render/Layer.js @@ -43,7 +43,7 @@ define( } if(options.strokeWidth) { - context.strokeWidth = options.strokeWidth; + context.strokeWidth = options.strokeWidth || 1; } } @@ -107,6 +107,7 @@ define( } }); + if(this.options.stroke) { this.context.stroke(); } @@ -194,6 +195,13 @@ define( return false; }, + /** + * 清空所有的shapes + */ + clearShapes: function() { + this.shapes.length = 0; + this.shapes = []; + }, /** * 获取当前坐标下的shape @@ -206,7 +214,10 @@ define( var shapes = this.shapes; var result = []; for(var i = 0, l = shapes.length; i < l; i++) { - if (support[shapes[i].type].isIn(shapes[i], p.x, p.y)) { + if ( + false !== shapes[i].selectable + && support[shapes[i].type].isIn(shapes[i], p.x, p.y) + ) { result.push(shapes[i]); } } diff --git a/src/render/Painter.js b/src/render/Painter.js index 7cab0f0..d2b1eeb 100644 --- a/src/render/Painter.js +++ b/src/render/Painter.js @@ -243,6 +243,16 @@ define( return this; }, + /** + * 清空所有的layer中的图形 + */ + clearShapes: function() { + var layers = this.layers; + for(var i = 0, l = layers.length; i < l; i++) { + layers[i].clearShapes(); + } + }, + /** * 注销本对象 */ diff --git a/src/render/main.js b/src/render/main.js index b246984..bafe9e5 100644 --- a/src/render/main.js +++ b/src/render/main.js @@ -22,14 +22,16 @@ define( exports.create = function(main, options) { options = options || {}; var render = new Render(main, options); - + var controller = options.controller; + // 设置render的默认控制器 - if (!options.controller) { + if (!controller) { controller = new Controller(); } - controller.setRender(render); - delete options.controller; + controller.setRender(render); + + delete options.controller; return render; }; diff --git a/src/render/render.js b/src/render/render.js index da2cbff..fa7baf2 100644 --- a/src/render/render.js +++ b/src/render/render.js @@ -1,5 +1,5 @@ /** - * @file render.js + * @file Render.js * @author mengke01 * @date * @description @@ -71,6 +71,15 @@ define( this.painter.refresh(); }; + /** + * 重置渲染器 + */ + Render.prototype.reset = function() { + this.painter.clearShapes(); + this.camera.reset(); + + }; + /** * 注销对象 * @@ -84,23 +93,16 @@ define( this.painter = this.capture = this.keyCapture = null; }; - /** - * 添加layer - * - * @return {Layer} Layer对象 - */ - Render.prototype.addLayer = function() { - return this.painter.addLayer.apply(this.painter, arguments); - }; - - /** - * 移除layer - * - * @return {boolean} 是否移除 - */ - Render.prototype.removeLayer = function() { - return this.painter.removeLayer.apply(this.painter, arguments); - }; + // 注册painter中的函数 + [ + 'addSupport', 'move', + 'getLayer', 'addLayer', 'removeLayer', + 'getShapeIn', 'clearShapes' + ].forEach(function(fnName) { + Render.prototype[fnName] = function() { + return this.painter[fnName].apply(this.painter, arguments); + }; + }); observable.mixin(Render.prototype); diff --git a/src/render/shape/CirclePoint.js b/src/render/shape/CirclePoint.js new file mode 100644 index 0000000..b304520 --- /dev/null +++ b/src/render/shape/CirclePoint.js @@ -0,0 +1,67 @@ +/** + * @file CirclePoint.js + * @author mengke01 + * @date + * @description + * 绘制控制圆 + */ + + +define( + function(require) { + + var POINT_SIZE = 6; + + var proto = { + + type: 'cpoint', + + // 调整大小 + adjust: function(shape, camera) { + return shape; + }, + + /** + * 获取shape的矩形区域 + * + * @param {Object} shape shape数据 + * @param {Object} 矩形区域 + */ + getRect: function(shape) { + return { + x: shape.x - POINT_SIZE, + y: shape.y - POINT_SIZE, + width: 2 * POINT_SIZE, + height: 2 * POINT_SIZE + }; + }, + + /** + * 判断点是否在shape内部 + * + * @param {Object} shape shape数据 + * @param {number} x x偏移 + * @param {number} y y偏移 + * @param {boolean} 是否 + */ + isIn: function(shape, x, y) { + return Math.pow(shape.x - x, 2) + Math.pow(shape.y - y, 2) <= Math.pow(POINT_SIZE, 2); + }, + + /** + * 绘制一个shape对象 + * + * @param {CanvasContext} ctx canvas的context + * @param {Object} shape shape数据 + */ + draw: function(ctx, shape) { + ctx.moveTo(shape.x + POINT_SIZE, shape.y); + ctx.arc(shape.x, shape.y, POINT_SIZE, 0, Math.PI * 2, true); + } + }; + + + + return require('./Shape').derive(proto); + } +); diff --git a/src/render/shape/DashedRect.js b/src/render/shape/DashedRect.js new file mode 100644 index 0000000..06494df --- /dev/null +++ b/src/render/shape/DashedRect.js @@ -0,0 +1,65 @@ +/** + * @file DashedRect.js + * @author mengke01 + * @date + * @description + * 绘制虚线矩形 + */ + + +define( + function(require) { + + var proto = { + + type: 'dashedrect', + + /** + * 获取shape的矩形区域 + * + * @param {Object} shape shape数据 + * @param {Object} 矩形区域 + */ + getRect: function(shape) { + return shape; + }, + + /** + * 判断点是否在shape内部 + * + * @param {Object} shape shape数据 + * @param {number} x x偏移 + * @param {number} y y偏移 + * @param {boolean} 是否 + */ + isIn: function(shape, x, y) { + var w = shape.width; + var h = shape.height; + return x <= shape.x + w + && x >= shape.x + && y <= shape.y + h + && y >= shape.y; + }, + + /** + * 绘制一个shape对象 + * + * @param {CanvasContext} ctx canvas的context + * @param {Object} shape shape数据 + */ + draw: function(ctx, shape) { + var w = shape.width; + var h = shape.height; + ctx.moveTo(shape.x, shape.y); + ctx.lineTo(shape.x + w, shape.y); + ctx.lineTo(shape.x + w, shape.y + h); + ctx.lineTo(shape.x, shape.y + h); + ctx.lineTo(shape.x, shape.y); + } + }; + + + + return require('./Shape').derive(proto); + } +); diff --git a/src/render/shape/Path.js b/src/render/shape/Path.js index 018f21d..b05828a 100644 --- a/src/render/shape/Path.js +++ b/src/render/shape/Path.js @@ -1,5 +1,5 @@ /** - * @file path.js + * @file Path.js * @author mengke01 * @date * @description diff --git a/src/render/shape/Point.js b/src/render/shape/Point.js new file mode 100644 index 0000000..1ccf5cc --- /dev/null +++ b/src/render/shape/Point.js @@ -0,0 +1,77 @@ +/** + * @file Point.js + * @author mengke01 + * @date + * @description + * 绘制控制点 + */ + + +define( + function(require) { + + var POINT_SIZE = 8; // 控制点的大小 + + var proto = { + + type: 'point', + + // 调整大小 + adjust: function(shape, camera) { + return shape; + }, + + /** + * 获取shape的矩形区域 + * + * @param {Object} shape shape数据 + * @param {Object} 矩形区域 + */ + getRect: function(shape) { + return { + x: shape.x - POINT_SIZE / 2 , + y: shape.y - POINT_SIZE / 2, + width: POINT_SIZE, + height: POINT_SIZE + }; + }, + + /** + * 判断点是否在shape内部 + * + * @param {Object} shape shape数据 + * @param {number} x x偏移 + * @param {number} y y偏移 + * @param {boolean} 是否 + */ + isIn: function(shape, x, y) { + var w = POINT_SIZE / 2; + var h = POINT_SIZE / 2; + return x <= shape.x + w + && x >= shape.x - w + && y <= shape.y + h + && y >= shape.y - h; + }, + + /** + * 绘制一个shape对象 + * + * @param {CanvasContext} ctx canvas的context + * @param {Object} shape shape数据 + */ + draw: function(ctx, shape) { + var w = POINT_SIZE / 2; + var h = POINT_SIZE / 2; + ctx.moveTo(shape.x - w, shape.y - h); + ctx.lineTo(shape.x + w, shape.y - h); + ctx.lineTo(shape.x + w, shape.y + h); + ctx.lineTo(shape.x - w, shape.y + h); + ctx.lineTo(shape.x - w, shape.y - h); + } + }; + + + + return require('./Shape').derive(proto); + } +); diff --git a/src/render/shape/Rect.js b/src/render/shape/Rect.js index ebd2637..b5dd4fd 100644 --- a/src/render/shape/Rect.js +++ b/src/render/shape/Rect.js @@ -1,5 +1,5 @@ /** - * @file Circle.js + * @file Rect.js * @author mengke01 * @date * @description @@ -22,8 +22,8 @@ define( */ getRect: function(shape) { return { - x: shape.x - shape.width / 2 , - y: shape.y - shape.height / 2, + x: shape.x, + y: shape.y, width: shape.width, height: shape.height }; @@ -38,12 +38,12 @@ define( * @param {boolean} 是否 */ isIn: function(shape, x, y) { - var w = shape.width / 2; - var h = shape.height / 2; + var w = shape.width; + var h = shape.height; return x <= shape.x + w - && x >= shape.x - w + && x >= shape.x && y <= shape.y + h - && y >= shape.y - h; + && y >= shape.y; }, /** @@ -53,13 +53,13 @@ define( * @param {Object} shape shape数据 */ draw: function(ctx, shape) { - var w = shape.width / 2; - var h = shape.height / 2; - ctx.moveTo(shape.x - w, shape.y - h); - ctx.lineTo(shape.x + w, shape.y - h); + var w = shape.width; + var h = shape.height; + ctx.moveTo(shape.x, shape.y); + ctx.lineTo(shape.x + w, shape.y); ctx.lineTo(shape.x + w, shape.y + h); - ctx.lineTo(shape.x - w, shape.y + h); - ctx.lineTo(shape.x - w, shape.y - h); + ctx.lineTo(shape.x, shape.y + h); + ctx.lineTo(shape.x, shape.y); } }; diff --git a/src/render/shape/support.js b/src/render/shape/support.js index c3418b4..5659c03 100644 --- a/src/render/shape/support.js +++ b/src/render/shape/support.js @@ -11,7 +11,10 @@ define( var support = { circle: require('./Circle'), + cpoint: require('./CirclePoint'), rect: require('./Rect'), + dashedrect: require('./DashedRect'), + point: require('./point'), font: require('./Font'), path: require('./Path') };