diff --git a/demo/css/render.css b/demo/css/render.css index b71c523..772a309 100644 --- a/demo/css/render.css +++ b/demo/css/render.css @@ -1,5 +1,5 @@ #render-view { - width: 600px; + width: 800px; height: 600px; background: #F0F0F0; position: relative; diff --git a/demo/css/render.less b/demo/css/render.less index 2a599af..2a45820 100644 --- a/demo/css/render.less +++ b/demo/css/render.less @@ -1,7 +1,7 @@ #render-view { - width: 600px; + width: 800px; height: 600px; background: #F0F0F0; position: relative; diff --git a/demo/js/render.js b/demo/js/render.js index 684adf1..f7780d4 100644 --- a/demo/js/render.js +++ b/demo/js/render.js @@ -12,6 +12,7 @@ define( var render = require('render/render'); var shape_baidu = require('./shape-baidu'); var shape_bdjk = require('./shape-bdjk'); + var glyfAdjust = require('ttf/util/glyfAdjust'); var currentRender; var entry = { @@ -65,14 +66,14 @@ define( level: 10 }); + shape_baidu = glyfAdjust(shape_baidu, 100 / 512); shape_baidu.x = 50; shape_baidu.y = 50; - shape_baidu.scale = 100 / 512; font.addShape('font', shape_baidu); - shape_bdjk.x = 400; - shape_bdjk.y = 300; - shape_bdjk.scale = 100 / 512; + shape_bdjk = glyfAdjust(shape_bdjk, 100 / 512); + shape_bdjk.x = 444; + shape_bdjk.y = 255; font.addShape('font', shape_bdjk); currentRender.refresh(); diff --git a/src/common/lang.js b/src/common/lang.js index ec008e1..5404eeb 100644 --- a/src/common/lang.js +++ b/src/common/lang.js @@ -110,17 +110,52 @@ define( return target; } + var hasOwnProperty = Object.prototype.hasOwnProperty; + + /** + * 深复制对象,仅复制数据 + * + * @param {Object} source 源数据 + * @return {Object} 复制的数据 + */ + function clone(source) { + if (!source || typeof source !== 'object') { + return source; + } + var cloned = source; + if (exports.isArray(source)) { + cloned = source.slice().map(clone); + } + else if (exports.isObject(source) && 'isPrototypeOf' in source) { + cloned = {}; + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + cloned[key] = clone(source[key]); + } + } + } + + return cloned; + } var exports = { extend: extend, bind: bind, inherits: inherits, curry: curry, - uncurry: generic + uncurry: generic, + clone: clone }; + // 生成 isXXX方法 + ['String', 'Array', 'Function', 'Date', 'Object'].forEach(function (type) { + exports['is' + type] = function (obj) { + return obj != null && toString.call(obj).slice(8, -1) === type; + }; + }); + return exports; } ); diff --git a/src/editor/common/glyf2canvas.js b/src/editor/common/glyf2canvas.js index 7e013fe..7351e6c 100644 --- a/src/editor/common/glyf2canvas.js +++ b/src/editor/common/glyf2canvas.js @@ -10,6 +10,8 @@ define( function(require) { + var glyfAdjust = require('ttf/util/glyfAdjust'); + /** * glyf canvas绘制 * @@ -35,20 +37,10 @@ define( // 对轮廓进行反向,以及坐标系调整,取整 - var xOffset = -glyf.xMin; - var yOffset = -glyf.yMin; - var middleYx2 = glyf.yMax + glyf.yMin; - var scale = options.scale || 1; - var coordinates = []; - - glyf.coordinates.forEach(function(p) { - coordinates.push({ - x: scale * (p.x + xOffset), - y: scale * (middleYx2 - p.y + yOffset), - isOnCurve: p.isOnCurve - }); - }); + glyf = glyfAdjust(glyf, options.scale); + + var coordinates = glyf.coordinates; var startPts = 0; // 起始点 var currentPts = 0; // 结束点 diff --git a/src/render/Camera.js b/src/render/Camera.js index 30e6be7..c914c6d 100644 --- a/src/render/Camera.js +++ b/src/render/Camera.js @@ -10,16 +10,28 @@ define( function(require) { + + /** * 视角对象 * * @constructor */ - function Camera(center, ratio) { - this.center = center; - this.ratio = ratio; + function Camera(center, ratio, scale) { + this.center = center || { + x: 0, + y: 0 + }; + this.ratio = ratio || 1; + this.scale = scale || 1; } + /** + * 注销Camera + */ + Camera.prototype.dispose = function() { + this.center = this.ratio = this.scale = null + } return Camera; } ); diff --git a/src/render/Layer.js b/src/render/Layer.js index 8cbba50..564926a 100644 --- a/src/render/Layer.js +++ b/src/render/Layer.js @@ -11,7 +11,7 @@ define( function(require) { var guid = require('./util/guid'); - var support = require('./shape/support'); + var ShapeConstructor = require('./shape/Shape'); var lang = require('common/lang'); /** @@ -88,16 +88,29 @@ define( var support = this.painter.support; this.context.clearRect(0, 0, this.painter.width, this.painter.height); - this.context.beginPath(); + setContextStyle(this.context, this.options); - var shapes = adjustCamera(this.shapes, this.painter.camera); + this.context.beginPath(); var context = this.context; - shapes.forEach(function(shape) { - support[shape.type].draw(context, shape); + var camera = this.painter.camera; + this.shapes.forEach(function(shape) { + + if(!shape['_shape']) { + shape['_shape'] = ShapeConstructor.clone(shape); + } + + var drawer = support[shape.type]; + + if(drawer) { + if(camera.ratio != 1) { + drawer.adjust(shape, camera); + } + drawer.draw(context, shape['_shape']); + } }); - + if(this.options.stroke) { this.context.stroke(); } @@ -193,7 +206,7 @@ define( var support = this.painter.support; var shapes = this.shapes; for(var i = 0, l = shapes.length; i < l; i++) { - if (support[shapes[i].type].isIn(shapes[i], p.x, p.y)) { + if (support[shapes[i].type].isIn(shapes[i]['_shape'], p.x, p.y)) { return shapes[i]; } } diff --git a/src/render/capture/Mouse.js b/src/render/capture/Mouse.js index 693e1b9..438d2c9 100644 --- a/src/render/capture/Mouse.js +++ b/src/render/capture/Mouse.js @@ -254,7 +254,10 @@ define( delta = e.detail / 3; } - this.fire('wheel', getEvent(e)); + var event = getEvent(e); + event.delta = delta; + + this.fire('wheel', event); } diff --git a/src/render/glyf/draw.js b/src/render/glyf/draw.js index 3ae606f..d92cab2 100644 --- a/src/render/glyf/draw.js +++ b/src/render/glyf/draw.js @@ -18,29 +18,17 @@ define( */ function draw(ctx, glyf) { - // 对轮廓进行反向,以及坐标系调整,取整 - var xOffset = -glyf.xMin; - var yOffset = -glyf.yMin; - var middleYx2 = glyf.yMax + glyf.yMin; - var scale = glyf.scale || 1; var x = glyf.x || 0; var y = glyf.y || 0; - glyf.width = scale * (glyf.xMax - glyf.xMin); - glyf.height = scale * (glyf.yMax - glyf.yMin); + glyf.width = glyf.xMax - glyf.xMin; + glyf.height = glyf.yMax - glyf.yMin; - var coordinates = []; - glyf.coordinates.forEach(function(p) { - coordinates.push({ - x: x + scale * (p.x + xOffset), - y: y + scale * (middleYx2 - p.y + yOffset), - isOnCurve: p.isOnCurve - }); - }); + ctx.translate(x, y); var startPts = 0; // 起始点 var currentPts = 0; // 结束点 - + var coordinates = glyf.coordinates; var commandQueue = []; // 命令队列 // 处理glyf轮廓 @@ -182,6 +170,8 @@ define( break; } } + + ctx.translate(-x, -y); } diff --git a/src/render/render.js b/src/render/render.js index 503fa04..64d49a7 100644 --- a/src/render/render.js +++ b/src/render/render.js @@ -28,6 +28,8 @@ define( this.options.painter ); + this.camera = this.painter.camera; + // 注册鼠标 this.capture = new MouseCapture( this.main, @@ -39,15 +41,36 @@ define( this.main, this.options.keyboard ); + } + /** + * 绑定组件事件 + * + */ + function bindEvent() { + var me = this; + this.capture.on('wheel', function(e) { + var defaultRatio = me.options.defaultRatio || 1.2; + var ratio = e.delta > 0 ? defaultRatio : 1 / defaultRatio; + + me.camera.ratio = ratio; + me.camera.center.x = e.x; + me.camera.center.y = e.y; + me.camera.scale *= ratio; + + me.painter.refresh(); + console.log(me.camera.scale); + me.camera.ratio = 1; + }); this.capture.on('dragstart', function(e) { var shape = me.painter.getShapeIn(e); if(shape) { - shape['_x'] = shape.x; - shape['_y'] = shape.y; + var _shape = shape['_shape']; + _shape._x = _shape.x; + _shape._y= _shape.y; } me.selectedShape = shape; }); @@ -55,8 +78,9 @@ define( this.capture.on('drag', function(e) { var shape = me.selectedShape; if(shape) { - shape.x = shape['_x'] + e.deltaX; - shape.y = shape['_y'] + e.deltaY; + var _shape = shape['_shape']; + _shape.x = _shape._x + e.deltaX; + _shape.y = _shape._y + e.deltaY; me.painter.getLayer(shape.layerId).refresh(); } }); @@ -68,11 +92,10 @@ define( me.selectedShape = null; } }); - - } + /** * Render 构造函数 * @@ -90,6 +113,7 @@ define( } init.call(this); + bindEvent.call(this); } /** diff --git a/src/render/shape/Font.js b/src/render/shape/Font.js index 9e9fbe9..5936fa4 100644 --- a/src/render/shape/Font.js +++ b/src/render/shape/Font.js @@ -9,13 +9,44 @@ define( function(require) { - + var ShapeConstructor = require('./Shape'); var glyfDraw = require('../glyf/draw'); var proto = { type: 'circle', + /** + * 对形状进行缩放平移调整 + * + * @param {Object} shape shape对象 + * @param {Object} camera camera对象 + * @return {Object} shape对象 + */ + adjust: function(shape, camera) { + ShapeConstructor.prototype.adjust.call(this, shape, camera); + var center = camera.center; + var ratio = camera.ratio; + var scale = camera.scale; + var _shape = shape['_shape']; + + var coordinates = []; + shape.coordinates.forEach(function(p) { + coordinates.push({ + x: p.x * scale, + y: p.y * scale, + isOnCurve: p.isOnCurve + }); + }); + + _shape.coordinates = coordinates; + _shape.xMax = shape.xMax * scale; + _shape.yMax = shape.yMax * scale; + _shape.xMin = shape.xMin * scale; + _shape.yMin = shape.yMin * scale; + + }, + /** * 获取shape的矩形区域 * @@ -59,6 +90,6 @@ define( - return require('./Shape').derive(proto); + return ShapeConstructor.derive(proto); } ); diff --git a/src/render/shape/Shape.js b/src/render/shape/Shape.js index 2569088..37f14c6 100644 --- a/src/render/shape/Shape.js +++ b/src/render/shape/Shape.js @@ -22,15 +22,39 @@ define( } lang.extend(Shape.prototype, { - /** - * 对形状进行缩放 + * 对形状进行缩放平移调整 * * @return {Object} shape对象 */ - scale: function(shape, camera) { - // TODO + adjust: function(shape, camera) { + var center = camera.center; + var ratio = camera.ratio; + var scale = camera.scale; + var _shape = shape['_shape']; + + if(typeof shape.x === 'number') { + _shape.x = ratio * (_shape.x - center.x) + center.x; + } + + if(typeof shape.y === 'number') { + _shape.y = ratio * (_shape.y - center.y) + center.y; + } + + if(typeof shape.width === 'number') { + _shape.width = scale * shape.width; + } + + if(typeof shape.width === 'number') { + _shape.height = scale * shape.height; + } + + if(typeof shape.r === 'number') { + _shape.r = scale * shape.r; + } + + return shape; }, /** @@ -88,10 +112,34 @@ define( } Constructor.constructor = Shape; - lang.extend(Constructor.prototype, prototype); + lang.extend(Constructor.prototype, Shape.prototype, prototype); return Constructor; } + /** + * 克隆一个shape对象 + * + * @param {Object} shape shape对象 + * @return {Object} shape对象 + */ + function cloneShape(shape) { + var _shape = null; + // 移出克隆的元素 + if(shape['_shape']) { + _shape = shape['_shape']; + delete shape['_shape']; + } + + var cloned = lang.clone(shape); + + if(_shape) { + shape['_shape'] = _shape; + } + return cloned; + } + + Shape.clone = cloneShape; + return Shape; } ); diff --git a/src/ttf/util/glyfAdjust.js b/src/ttf/util/glyfAdjust.js new file mode 100644 index 0000000..bdfdc00 --- /dev/null +++ b/src/ttf/util/glyfAdjust.js @@ -0,0 +1,52 @@ +/** + * @file glyfAdjust.js + * @author mengke01 + * @date + * @description + * 将glyf坐标系平移到原点 + */ + + +define( + function(require) { + + /** + * 对glyf坐标进行调整 + * + * @param {Object} glyf glyf结构 + * @param {number} scale 缩放比例 + * @param {number} offsetX x偏移 + * @param {number} offsetY y偏移 + * @return {number} glyf结构 + */ + function glyfAdjust(glyf, scale, offsetX, offsetY) { + + // 对轮廓进行反向,以及坐标系调整,取整 + var xOffset = -glyf.xMin; + var yOffset = -glyf.yMin; + var middleYx2 = glyf.yMax + glyf.yMin; + var scale = scale || 1; + var x = offsetX || 0; + var y = offsetY || 0; + var coordinates = []; + + glyf.coordinates.forEach(function(p) { + coordinates.push({ + x: x + scale * (p.x + xOffset), + y: y + scale * (middleYx2 - p.y + yOffset), + isOnCurve: p.isOnCurve + }); + }); + + glyf.xMin = x; + glyf.yMin = y; + glyf.xMax = scale * (glyf.xMax - glyf.xMin) + x; + glyf.yMax = scale * (glyf.yMax - glyf.yMin) + y; + glyf.coordinates = coordinates; + + return glyf; + } + + return glyfAdjust; + } +);