add rotate mode
This commit is contained in:
@@ -64,16 +64,26 @@ define(
|
||||
height: 42
|
||||
});
|
||||
|
||||
var shape3 = cover.addShape('polygon', {
|
||||
points: [
|
||||
{x:300, y: 344},
|
||||
{x:350, y: 344},
|
||||
{x:450, y: 400},
|
||||
{x:400, y: 400}
|
||||
],
|
||||
dashed: true
|
||||
});
|
||||
|
||||
var font = currentRender.addLayer('font', {
|
||||
level: 10
|
||||
});
|
||||
|
||||
var contourAdjust = require('ttf/util/contourAdjust');
|
||||
var pathAdjust = require('graphics/pathAdjust');
|
||||
|
||||
shape_baidu.contours.forEach(function(contour) {
|
||||
var shape = {};
|
||||
shape.points = contour;
|
||||
shape.points = contourAdjust(contour, 1, 1, 100, 400);
|
||||
shape.points = pathAdjust(contour, 1, 1, 100, 400);
|
||||
font.addShape('path', shape);
|
||||
});
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ define(
|
||||
function(require) {
|
||||
var lang = require('common/lang');
|
||||
var computeBoundingBox = require('graphics/computeBoundingBox');
|
||||
var pathAdjust = require('render/util/pathAdjust');
|
||||
var pathAdjust = require('graphics/pathAdjust');
|
||||
var editorMode = require('./mode/editorMode');
|
||||
var ContextMenu = require('./menu/ContextMenu');
|
||||
|
||||
@@ -56,8 +56,8 @@ define(
|
||||
return;
|
||||
}
|
||||
|
||||
render.camera.startx = e.x;
|
||||
render.camera.starty = e.y;
|
||||
render.camera.startX = e.x;
|
||||
render.camera.startY = e.y;
|
||||
setCamera(e);
|
||||
|
||||
me.mode.down && me.mode.down.call(me, e);
|
||||
@@ -106,6 +106,17 @@ define(
|
||||
me.mode.up && me.mode.up.call(me, e);
|
||||
});
|
||||
|
||||
render.capture.on('click', function(e) {
|
||||
|
||||
if (me.contextMenu.visible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setCamera(e);
|
||||
|
||||
me.mode.click && me.mode.click.call(me, e);
|
||||
});
|
||||
|
||||
render.capture.on('dblclick', function(e) {
|
||||
|
||||
if (me.contextMenu.visible()) {
|
||||
|
||||
@@ -9,13 +9,11 @@
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var pathAdjust = require('render/util/pathAdjust');
|
||||
var boundAdjust = require('render/util/boundAdjust');
|
||||
var pathAdjust = require('graphics/pathAdjust');
|
||||
var lang = require('common/lang');
|
||||
var computeBoundingBox = require('../../graphics/computeBoundingBox');
|
||||
var getTransformMatrix = require('../util/getTransformMatrix');
|
||||
|
||||
var computeBoundingBox = require('graphics/computeBoundingBox');
|
||||
var scaleTransform = require('./scaleTransform');
|
||||
var rotateTransform = require('./rotateTransform');
|
||||
var updateControls = require('./updateControls');
|
||||
|
||||
|
||||
@@ -58,57 +56,12 @@ define(
|
||||
* 根据控制点做图形变换
|
||||
*/
|
||||
ShapesGroup.prototype.transform = function(point, camera) {
|
||||
|
||||
|
||||
var matrix = getTransformMatrix(point.pos, this.bound, camera);
|
||||
|
||||
// 等比缩放
|
||||
if (camera.event.shiftKey && [1, 2, 3, 4].indexOf(point.pos) >= 0) {
|
||||
var scale = Math.max(Math.abs(matrix[2]), Math.abs(matrix[3]));
|
||||
matrix[2] = matrix[2] >= 0 ? scale : -scale;
|
||||
matrix[3] = matrix[3] >= 0 ? scale : -scale;
|
||||
if (this.mode === 'scale') {
|
||||
scaleTransform.call(this, point, camera);
|
||||
}
|
||||
|
||||
|
||||
// 更新shape
|
||||
var shapes = this.shapes;
|
||||
|
||||
this.originShapes.forEach(function(originShape, index) {
|
||||
|
||||
var shape = lang.clone(originShape);
|
||||
pathAdjust(shape.points, matrix[2], matrix[3], -matrix[0], -matrix[1]);
|
||||
pathAdjust(shape.points, 1, 1, matrix[0], matrix[1]);
|
||||
|
||||
if (matrix[2] < 0 && !matrix[3] < 0) {
|
||||
shape.points = shape.points.reverse();
|
||||
}
|
||||
|
||||
if (matrix[3] < 0 && !matrix[2] < 0) {
|
||||
shape.points = shape.points.reverse();
|
||||
}
|
||||
|
||||
lang.extend(shapes[index], shape);
|
||||
|
||||
});
|
||||
|
||||
this.render.getLayer('font').refresh();
|
||||
|
||||
// 更新边界
|
||||
var coverLayer = this.render.getLayer('cover');
|
||||
var boundShape = coverLayer.getShape('bound');
|
||||
if(!boundShape) {
|
||||
boundShape = {
|
||||
type: 'rect',
|
||||
dashed: true,
|
||||
id: 'bound'
|
||||
};
|
||||
coverLayer.addShape(boundShape);
|
||||
else {
|
||||
rotateTransform.call(this, point, camera);
|
||||
}
|
||||
|
||||
var bound = boundAdjust(lang.clone(this.bound), matrix[2], matrix[3], -matrix[0], -matrix[1]);
|
||||
boundAdjust(bound, 1, 1, matrix[0], matrix[1]);
|
||||
lang.extend(boundShape, bound);
|
||||
coverLayer.refresh();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
84
src/editor/group/getRotateMatrix.js
Normal file
84
src/editor/group/getRotateMatrix.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @file getRotateMatrix.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 获得变换的矩阵
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var getAngle = require('math/getAngle');
|
||||
|
||||
|
||||
/**
|
||||
* 获得变换矩阵
|
||||
*
|
||||
* @param {number} pos 变换位置
|
||||
* @param {Object} bound 边界
|
||||
* @param {Object} camera 镜头对象
|
||||
* @return {Array} 变换矩阵,x,y,xScale,yScale
|
||||
*/
|
||||
function getRotateMatrix(pos, bound, camera) {
|
||||
|
||||
// x, y, xscale 相对符号, yscale 相对符号
|
||||
var matrix = [
|
||||
bound.x + bound.width / 2,
|
||||
bound.y + bound.height / 2,
|
||||
0
|
||||
];
|
||||
|
||||
switch (pos) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
matrix[2] = getAngle(
|
||||
camera.startX - matrix[0], camera.startY - matrix[1],
|
||||
camera.x - matrix[0], camera.y - matrix[1]
|
||||
);
|
||||
return matrix;
|
||||
|
||||
case 5:
|
||||
matrix[0] = 0;
|
||||
matrix[1] = bound.y + bound.height;
|
||||
matrix[2] = getAngle(
|
||||
0, bound.height,
|
||||
camera.x - camera.startX, bound.height
|
||||
);
|
||||
return matrix;
|
||||
case 7:
|
||||
matrix[0] = 0;
|
||||
matrix[1] = bound.y;
|
||||
matrix[2] = getAngle(
|
||||
0, -bound.height,
|
||||
camera.x - camera.startX, -bound.height
|
||||
);
|
||||
return matrix;
|
||||
case 6:
|
||||
matrix[0] = bound.x;
|
||||
matrix[1] = 0;
|
||||
matrix[2] = getAngle(
|
||||
bound.width, 0,
|
||||
bound.width, camera.y - camera.startY
|
||||
);
|
||||
return matrix;
|
||||
case 8:
|
||||
matrix[0] = bound.x + bound.width;
|
||||
matrix[1] = 0;
|
||||
matrix[2] = getAngle(
|
||||
-bound.width, 0,
|
||||
-bound.width, camera.y - camera.startY
|
||||
);
|
||||
return matrix;
|
||||
};
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
||||
return getRotateMatrix;
|
||||
}
|
||||
);
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file getTransformMatrix.js
|
||||
* @file getScaleMatrix.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
@@ -19,7 +19,7 @@ define(
|
||||
* @param {Object} camera 镜头对象
|
||||
* @return {Array} 变换矩阵,x,y,xScale,yScale
|
||||
*/
|
||||
function getTransformMatrix(pos, bound, camera) {
|
||||
function getScaleMatrix(pos, bound, camera) {
|
||||
|
||||
// x, y, xscale 相对符号, yscale 相对符号
|
||||
var matrix = [
|
||||
@@ -83,6 +83,6 @@ define(
|
||||
}
|
||||
|
||||
|
||||
return getTransformMatrix;
|
||||
return getScaleMatrix;
|
||||
}
|
||||
);
|
||||
87
src/editor/group/rotateTransform.js
Normal file
87
src/editor/group/rotateTransform.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @file rotateTransform.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 旋转变换
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var getRotateMatrix = require('./getRotateMatrix');
|
||||
var pathRotate = require('graphics/pathRotate');
|
||||
var pathLean = require('graphics/pathLean');
|
||||
var lang = require('common/lang');
|
||||
|
||||
/**
|
||||
* 旋转变换
|
||||
*
|
||||
* @param {Object} point 参考点
|
||||
* @param {Object} camera 镜头对象
|
||||
*/
|
||||
function rotateTransform(point, camera) {
|
||||
|
||||
var matrix = getRotateMatrix(point.pos, this.bound, camera);
|
||||
|
||||
var transformer = point.pos <= 4 ? pathRotate : pathLean;
|
||||
|
||||
// 更新shape
|
||||
var shapes = this.shapes;
|
||||
|
||||
this.originShapes.forEach(function(originShape, index) {
|
||||
var shape = lang.clone(originShape);
|
||||
transformer(shape.points, matrix[2], matrix[0], matrix[1]);
|
||||
lang.extend(shapes[index], shape);
|
||||
|
||||
});
|
||||
|
||||
this.render.getLayer('font').refresh();
|
||||
|
||||
// 更新边界
|
||||
var coverLayer = this.render.getLayer('cover');
|
||||
var boundShape = coverLayer.getShape('bound');
|
||||
|
||||
if(!boundShape) {
|
||||
boundShape = {
|
||||
type: 'polygon',
|
||||
dashed: true,
|
||||
id: 'bound'
|
||||
};
|
||||
coverLayer.addShape(boundShape);
|
||||
}
|
||||
|
||||
|
||||
var bound = this.bound;
|
||||
boundShape.points = transformer(
|
||||
[
|
||||
{x: bound.x,y:bound.y},
|
||||
{x: bound.x + bound.width, y:bound.y},
|
||||
{x: bound.x + bound.width, y:bound.y + bound.height},
|
||||
{x: bound.x, y:bound.y + bound.height},
|
||||
],
|
||||
matrix[2], matrix[0], matrix[1]
|
||||
);
|
||||
|
||||
// 更新中心点
|
||||
var boundCenter = coverLayer.getShape('boundcenter');
|
||||
if(!boundCenter) {
|
||||
boundCenter = {
|
||||
type: 'cpoint',
|
||||
id: 'boundcenter',
|
||||
x: bound.x + bound.width / 2,
|
||||
y: bound.y + bound.height / 2
|
||||
};
|
||||
coverLayer.addShape(boundCenter);
|
||||
}
|
||||
boundCenter.x = (boundShape.points[0].x + boundShape.points[2].x) / 2;
|
||||
boundCenter.y = (boundShape.points[0].y + boundShape.points[2].y) / 2;
|
||||
|
||||
|
||||
coverLayer.refresh();
|
||||
}
|
||||
|
||||
return rotateTransform;
|
||||
}
|
||||
);
|
||||
88
src/editor/group/scaleTransform.js
Normal file
88
src/editor/group/scaleTransform.js
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* @file scaleTransform.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 缩放变换
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var getScaleMatrix = require('./getScaleMatrix');
|
||||
var pathAdjust = require('graphics/pathAdjust');
|
||||
var lang = require('common/lang');
|
||||
|
||||
/**
|
||||
* 缩放变换
|
||||
*
|
||||
* @param {Object} point 参考点
|
||||
* @param {Object} camera 镜头对象
|
||||
*/
|
||||
function scaleTransform(point, camera) {
|
||||
|
||||
var matrix = getScaleMatrix(point.pos, this.bound, camera);
|
||||
// 等比缩放
|
||||
if (camera.event.shiftKey && [1, 2, 3, 4].indexOf(point.pos) >= 0) {
|
||||
var scale = Math.max(Math.abs(matrix[2]), Math.abs(matrix[3]));
|
||||
matrix[2] = matrix[2] >= 0 ? scale : -scale;
|
||||
matrix[3] = matrix[3] >= 0 ? scale : -scale;
|
||||
}
|
||||
|
||||
|
||||
// 更新shape
|
||||
var shapes = this.shapes;
|
||||
|
||||
this.originShapes.forEach(function(originShape, index) {
|
||||
|
||||
var shape = lang.clone(originShape);
|
||||
pathAdjust(shape.points, matrix[2], matrix[3], -matrix[0], -matrix[1]);
|
||||
pathAdjust(shape.points, 1, 1, matrix[0], matrix[1]);
|
||||
|
||||
if (matrix[2] < 0 && !matrix[3] < 0) {
|
||||
shape.points = shape.points.reverse();
|
||||
}
|
||||
|
||||
if (matrix[3] < 0 && !matrix[2] < 0) {
|
||||
shape.points = shape.points.reverse();
|
||||
}
|
||||
|
||||
lang.extend(shapes[index], shape);
|
||||
|
||||
});
|
||||
|
||||
this.render.getLayer('font').refresh();
|
||||
|
||||
// 更新边界
|
||||
var coverLayer = this.render.getLayer('cover');
|
||||
var boundShape = coverLayer.getShape('bound');
|
||||
|
||||
if(!boundShape) {
|
||||
boundShape = {
|
||||
type: 'polygon',
|
||||
dashed: true,
|
||||
id: 'bound'
|
||||
};
|
||||
coverLayer.addShape(boundShape);
|
||||
}
|
||||
|
||||
var bound = this.bound;
|
||||
var points = pathAdjust(
|
||||
[
|
||||
{x: bound.x,y:bound.y},
|
||||
{x: bound.x + bound.width, y:bound.y},
|
||||
{x: bound.x + bound.width, y:bound.y + bound.height},
|
||||
{x: bound.x, y:bound.y + bound.height},
|
||||
],
|
||||
matrix[2], matrix[3], -matrix[0], -matrix[1]
|
||||
);
|
||||
pathAdjust(points, 1, 1, matrix[0], matrix[1]);
|
||||
boundShape.points = points;
|
||||
coverLayer.refresh();
|
||||
|
||||
}
|
||||
|
||||
return scaleTransform;
|
||||
}
|
||||
);
|
||||
@@ -18,25 +18,26 @@ define(
|
||||
function updateControls(bound) {
|
||||
|
||||
if (!this.controls) {
|
||||
this.controls = [{
|
||||
type: 'rect',
|
||||
dashed: true,
|
||||
selectable: false
|
||||
}];
|
||||
for (var i = 0; i < 8; i++) {
|
||||
this.controls.push({
|
||||
type: 'point'
|
||||
});
|
||||
}
|
||||
// 虚线框
|
||||
this.controls = [
|
||||
{
|
||||
type: 'polygon',
|
||||
dashed: true,
|
||||
selectable: false
|
||||
},
|
||||
{}, {}, {}, {}, {}, {}, {}, {}
|
||||
];
|
||||
}
|
||||
|
||||
var points = [
|
||||
// 虚线框
|
||||
|
||||
{
|
||||
x: bound.x,
|
||||
y: bound.y,
|
||||
width: bound.width,
|
||||
height: bound.height
|
||||
points: [
|
||||
{x: bound.x,y:bound.y},
|
||||
{x: bound.x + bound.width, y:bound.y},
|
||||
{x: bound.x + bound.width, y:bound.y + bound.height},
|
||||
{x: bound.x, y:bound.y + bound.height},
|
||||
]
|
||||
},
|
||||
|
||||
// 控制点
|
||||
@@ -55,9 +56,13 @@ define(
|
||||
{x: bound.x, y: bound.y + bound.height / 2, pos: 8},
|
||||
];
|
||||
|
||||
var mode = this.mode;
|
||||
var controls = this.controls;
|
||||
points.forEach(function(p, index) {
|
||||
lang.extend(controls[index], p);
|
||||
points.forEach(function(p, i) {
|
||||
lang.extend(controls[i], p);
|
||||
if (i > 0) {
|
||||
controls[i].type = mode == 'rotate' && i <= 4 ? 'cpoint' : 'point';
|
||||
}
|
||||
});
|
||||
|
||||
var coverLayer = this.render.getLayer('cover');
|
||||
|
||||
@@ -11,14 +11,26 @@ define(
|
||||
function(require) {
|
||||
// 不同位置的光标集合
|
||||
return {
|
||||
1: 'nw-resize',
|
||||
2: 'ne-resize',
|
||||
3: 'se-resize',
|
||||
4: 'sw-resize',
|
||||
5: 's-resize',
|
||||
6: 'e-resize',
|
||||
7: 'n-resize',
|
||||
8: 'w-resize'
|
||||
};;
|
||||
scale: {
|
||||
1: 'nw-resize',
|
||||
2: 'ne-resize',
|
||||
3: 'se-resize',
|
||||
4: 'sw-resize',
|
||||
5: 's-resize',
|
||||
6: 'e-resize',
|
||||
7: 'n-resize',
|
||||
8: 'w-resize'
|
||||
},
|
||||
rotate: {
|
||||
1: 'pointer',
|
||||
2: 'pointer',
|
||||
3: 'pointer',
|
||||
4: 'pointer',
|
||||
5: 'e-resize',
|
||||
6: 's-resize',
|
||||
7: 'w-resize',
|
||||
8: 'n-resize'
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ define(
|
||||
function(require) {
|
||||
|
||||
var computeBoundingBox = require('graphics/computeBoundingBox');
|
||||
var pathAdjust = require('render/util/pathAdjust');
|
||||
var pathAdjust = require('graphics/pathAdjust');
|
||||
var lang = require('common/lang');
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ define(
|
||||
}
|
||||
else {
|
||||
this.currentGroup.setShapes([shape]);
|
||||
this.currentGroup.setMode('scale');
|
||||
this.currentGroup.refresh();
|
||||
return;
|
||||
}
|
||||
@@ -96,6 +97,20 @@ define(
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击
|
||||
*/
|
||||
click: function(e) {
|
||||
// 变换编辑模式
|
||||
if (e.time > 400 && this.currentGroup && !this.currentPoint) {
|
||||
this.currentGroup.setMode(this.currentGroup.mode == 'scale' ? 'rotate' : 'scale');
|
||||
this.currentGroup.refresh();
|
||||
}
|
||||
else {
|
||||
this.currentPoint = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 开始模式
|
||||
*/
|
||||
@@ -105,12 +120,12 @@ define(
|
||||
|
||||
this.currentGroup = new ShapesGroup(shapes, this.render);
|
||||
this.currentGroup.refresh();
|
||||
|
||||
|
||||
// 注册鼠标样式
|
||||
me.render.capture.on('move', me.__moveEvent = function (e) {
|
||||
var shapes = coverLayer.getShapeIn(e);
|
||||
if(shapes) {
|
||||
me.render.setCursor(POS_CUSOR[shapes[0].pos] || 'default');
|
||||
me.render.setCursor(POS_CUSOR[me.currentGroup.mode][shapes[0].pos] || 'default');
|
||||
}
|
||||
else {
|
||||
me.render.setCursor('default');
|
||||
|
||||
@@ -5,81 +5,39 @@
|
||||
* @description
|
||||
* 判断点是否在polygon内部
|
||||
*
|
||||
* copy from zrender:
|
||||
* https://github.com/ecomfe/zrender
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var isSegmentRayCross = require('./isSegmentRayCross');
|
||||
|
||||
/**
|
||||
* 多边形包含判断
|
||||
* 警告:下面这段代码会很难看,建议跳过~
|
||||
* 多边形包含判断, 射线法
|
||||
*/
|
||||
function isInsidePolygon(pointList, x, y) {
|
||||
/**
|
||||
* 射线判别法
|
||||
* 如果一个点在多边形内部,任意角度做射线肯定会与多边形要么有一个交点,要么有与多边形边界线重叠
|
||||
* 如果一个点在多边形外部,任意角度做射线要么与多边形有一个交点,
|
||||
* 要么有两个交点,要么没有交点,要么有与多边形边界线重叠。
|
||||
*/
|
||||
var i;
|
||||
var j;
|
||||
var polygon = pointList;
|
||||
var N = polygon.length;
|
||||
var inside = false;
|
||||
var redo = true;
|
||||
var v;
|
||||
function isInsidePolygon(points, p) {
|
||||
|
||||
for (i = 0; i < N; ++i) {
|
||||
// 是否在顶点上
|
||||
if (polygon[i].x == x && polygon[i].y == y ) {
|
||||
redo = false;
|
||||
inside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var zCount = 0, p0, p1, result;
|
||||
for (var i = 0, l = points.length; i < l ; i++) {
|
||||
p0 = points[i];
|
||||
p1 = points[i === l - 1 ? 0 : i + 1];
|
||||
|
||||
if (redo) {
|
||||
redo = false;
|
||||
inside = false;
|
||||
for (i = 0,j = N - 1; i < N; j = i++) {
|
||||
if ((polygon[i].y < y && y < polygon[j].y)
|
||||
|| (polygon[j].y < y && y < polygon[i].y)
|
||||
) {
|
||||
if (x <= polygon[i].x || x <= polygon[j].x) {
|
||||
v = (y - polygon[i].y)
|
||||
* (polygon[j].x - polygon[i].x)
|
||||
/ (polygon[j].y - polygon[i].y)
|
||||
+ polygon[i].x;
|
||||
if (x < v) { // 在线的左侧
|
||||
inside = !inside;
|
||||
}
|
||||
else if (x == v) { // 在线上
|
||||
inside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result = isSegmentRayCross(p0, p1, p)) {
|
||||
// 在线段上
|
||||
if (result.y == p.y) {
|
||||
return true;
|
||||
}
|
||||
else if (y == polygon[i].y) {
|
||||
if (x < polygon[i].x) { // 交点在顶点上
|
||||
polygon[i].y > polygon[j].y ? --y : ++y;
|
||||
//redo = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p1.y > p0.y) {
|
||||
zCount++;
|
||||
}
|
||||
else if (polygon[i].y == polygon[j].y // 在水平的边界线上
|
||||
&& y == polygon[i].y
|
||||
&& ((polygon[i].x < x && x < polygon[j].x)
|
||||
|| (polygon[j].x < x && x < polygon[i].x))
|
||||
) {
|
||||
inside = true;
|
||||
break;
|
||||
else {
|
||||
zCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return inside;
|
||||
return !!zCount;
|
||||
}
|
||||
|
||||
return isInsidePolygon;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file contourAdjust.js
|
||||
* @file pathAdjust.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
@@ -20,7 +20,7 @@ define(
|
||||
* @param {number} offsetY y偏移
|
||||
* @return {number} contour 坐标点
|
||||
*/
|
||||
function contourAdjust(contour, scaleX, scaleY, offsetX, offsetY) {
|
||||
function pathAdjust(contour, scaleX, scaleY, offsetX, offsetY) {
|
||||
var scaleX = scaleX == undefined ? 1 : scaleX;
|
||||
var scaleY = scaleY == undefined ? 1 : scaleY;
|
||||
var x = offsetX || 0;
|
||||
@@ -34,6 +34,6 @@ define(
|
||||
return contour;
|
||||
}
|
||||
|
||||
return contourAdjust;
|
||||
return pathAdjust;
|
||||
}
|
||||
);
|
||||
@@ -14,6 +14,8 @@ define(
|
||||
* 遍历路径的路径集合
|
||||
*
|
||||
* @param {Array} contour 坐标点集
|
||||
* @param {Function} callBack 回调函数,参数集合:command, p0, p1, p2
|
||||
* 其中command = L 或者 Q,表示直线或者贝塞尔曲线
|
||||
*/
|
||||
function pathIterator(contour, callBack) {
|
||||
|
||||
|
||||
47
src/graphics/pathLean.js
Normal file
47
src/graphics/pathLean.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file pathLean.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* path倾斜变换
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
/**
|
||||
* path倾斜变换
|
||||
*
|
||||
* @param {Object} contour 坐标点
|
||||
* @param {number} angle 角度
|
||||
* @param {number} offsetX x偏移
|
||||
* @param {number} offsetY y偏移
|
||||
* @return {number} contour 坐标点
|
||||
*/
|
||||
function pathLean(contour, angle, offsetX, offsetY) {
|
||||
var angle = angle == undefined ? 0 : angle;
|
||||
var x = offsetX || 0;
|
||||
var y = offsetY || 0;
|
||||
var tan = Math.tan(angle);
|
||||
var px, py;
|
||||
|
||||
// x 平移
|
||||
if (x == 0) {
|
||||
contour.forEach(function(p) {
|
||||
p.x += tan * (p.y - offsetY);
|
||||
});
|
||||
}
|
||||
// y平移
|
||||
else {
|
||||
contour.forEach(function(p) {
|
||||
p.y += tan * (p.x - offsetX);
|
||||
});
|
||||
}
|
||||
|
||||
return contour;
|
||||
}
|
||||
|
||||
return pathLean;
|
||||
}
|
||||
);
|
||||
44
src/graphics/pathRotate.js
Normal file
44
src/graphics/pathRotate.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @file pathRotate.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 路径旋转
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
/**
|
||||
* 对path坐标进行调整
|
||||
*
|
||||
* @param {Object} contour 坐标点
|
||||
* @param {number} angle 角度
|
||||
* @param {number} centerX x偏移
|
||||
* @param {number} centerY y偏移
|
||||
* @return {number} contour 坐标点
|
||||
*/
|
||||
function pathRotate(contour, angle, centerX, centerY) {
|
||||
var angle = angle == undefined ? 0 : angle;
|
||||
var x = centerX || 0;
|
||||
var y = centerY || 0;
|
||||
var cos = Math.cos(angle);
|
||||
var sin = Math.sin(angle);
|
||||
var px, py;
|
||||
|
||||
//x1=cos(angle)*x-sin(angle)*y;
|
||||
//y1=cos(angle)*y+sin(angle)*x;
|
||||
contour.forEach(function(p) {
|
||||
px = cos * (p.x - x) - sin * (p.y - y);
|
||||
py = cos * (p.y - y) + sin * (p.x - x);
|
||||
p.x = px + x;
|
||||
p.y = py + y;
|
||||
});
|
||||
|
||||
return contour;
|
||||
}
|
||||
|
||||
return pathRotate;
|
||||
}
|
||||
);
|
||||
37
src/math/getAngle.js
Normal file
37
src/math/getAngle.js
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file getAngle.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 获取向量夹角,带方向
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
/**
|
||||
* 获取向量夹角, 相对于坐标原点
|
||||
*
|
||||
* @param {number} x1 起始x
|
||||
* @param {number} y1 起始y
|
||||
* @param {number} x2 结束x
|
||||
* @param {number} y2 结束y
|
||||
* @return {number} 弧度
|
||||
*/
|
||||
function getAngle(x1, y1, x2, y2) {
|
||||
// cos(θ) = (x1x2+y1y2)/[√(x1²+y1²)*√(x2²+y2²)]
|
||||
var angle = Math.acos( (x1 * x2 + y1 * y2) / Math.sqrt(x1*x1 + y1*y1) / Math.sqrt(x2*x2 + y2*y2));
|
||||
|
||||
// 有向线段内积,判断左右
|
||||
//(xb - xa) * (yc - ya) - (xc - xa) * (yb - ya);
|
||||
if (x1 * y2 - x2 * y1 < 0) {
|
||||
angle = 2 * Math.PI - angle;
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
return getAngle;
|
||||
}
|
||||
);
|
||||
@@ -32,9 +32,13 @@ define(
|
||||
});
|
||||
|
||||
render.capture.on('down', function(e) {
|
||||
var result = render.getShapeIn(e);
|
||||
var result = render.getLayer('cover').getShapeIn(e);
|
||||
|
||||
if(result) {
|
||||
render.selectedShape = result[0];
|
||||
}
|
||||
else {
|
||||
result = render.getLayer('font').getShapeIn(e);
|
||||
if (result.length > 1) {
|
||||
render.selectedShape = selectShape(result);
|
||||
}
|
||||
@@ -42,6 +46,8 @@ define(
|
||||
render.selectedShape = result[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render.camera.x = e.x;
|
||||
render.camera.y = e.y;
|
||||
});
|
||||
|
||||
@@ -35,7 +35,6 @@ define(
|
||||
function setContextStyle(context, options) {
|
||||
context.fillStyle = options.fillColor || 'black';
|
||||
context.strokeStyle = options.strokeColor || 'black';
|
||||
context.strokeWidth = options.strokeWidth || 1;
|
||||
context.lineWidth = options.lineWidth || 1;
|
||||
context.font = options.font || "normal 10px arial";
|
||||
}
|
||||
|
||||
@@ -93,7 +93,6 @@ define(
|
||||
mousemove: lang.bind(mousemove, this),
|
||||
mousedown: lang.bind(mousedown, this),
|
||||
dblclick: lang.bind(dblclick, this),
|
||||
click: lang.bind(click, this),
|
||||
mouseover: lang.bind(mouseover, this),
|
||||
mouseout: lang.bind(mouseout, this),
|
||||
mouseup: lang.bind(mouseup, this)
|
||||
@@ -104,7 +103,6 @@ define(
|
||||
target.addEventListener('mousemove', this.handlers.mousemove, false);
|
||||
target.addEventListener('mousedown', this.handlers.mousedown, false);
|
||||
target.addEventListener('dblclick', this.handlers.dblclick, false);
|
||||
target.addEventListener('click', this.handlers.click, false);
|
||||
target.addEventListener('mouseover', this.handlers.mouseover, false);
|
||||
target.addEventListener('mouseout', this.handlers.mouseout, false);
|
||||
document.addEventListener('mouseup', this.handlers.mouseup, false);
|
||||
@@ -127,6 +125,7 @@ define(
|
||||
|
||||
this.startX = event.x;
|
||||
this.startY = event.y;
|
||||
this.startTime = Date.now();
|
||||
this.isDown = true;
|
||||
|
||||
// 左键
|
||||
@@ -138,22 +137,6 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击事件
|
||||
*
|
||||
* @param {Object} e 事件参数
|
||||
*/
|
||||
function click(e) {
|
||||
|
||||
prevent(e);
|
||||
|
||||
if(false === this.events.click) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.fire('click', getEvent(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* 双击事件
|
||||
*
|
||||
@@ -221,6 +204,7 @@ define(
|
||||
}
|
||||
|
||||
var event = getEvent(e);
|
||||
event.time = Date.now() - this.startTime;
|
||||
|
||||
// 左键
|
||||
|
||||
@@ -236,6 +220,10 @@ define(
|
||||
this.isDragging = false;
|
||||
this.fire('dragend', event);
|
||||
}
|
||||
else if(this.isDown && !this.isDragging && false !== this.events.click) {
|
||||
this.isDragging = false;
|
||||
this.fire('click', event);
|
||||
}
|
||||
|
||||
this.isDown = false;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ define(
|
||||
function(require) {
|
||||
var ShapeConstructor = require('./Shape');
|
||||
var isInsidePath = require('../../graphics/isInsidePath');
|
||||
var pathAdjust = require('../util/pathAdjust');
|
||||
var pathAdjust = require('graphics/pathAdjust');
|
||||
var drawContour = require('ttf/util/drawContour');
|
||||
var computeBoundingBox = require('graphics/computeBoundingBox');
|
||||
var proto = {
|
||||
|
||||
@@ -1,8 +1,124 @@
|
||||
/**
|
||||
* @file Polygon.js
|
||||
* @file Rect.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 多边形绘制
|
||||
* 绘制多边形
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
|
||||
var dashedLineTo = require('../util/dashedLineTo');
|
||||
var pathAdjust = require('graphics/pathAdjust');
|
||||
var computeBoundingBox = require('graphics/computeBoundingBox');
|
||||
var isInsidePolygon = require('graphics/isInsidePolygon');
|
||||
|
||||
var proto = {
|
||||
|
||||
type: 'polygon',
|
||||
|
||||
/**
|
||||
* 对形状进行缩放平移调整
|
||||
*
|
||||
* @param {Object} shape shape对象
|
||||
* @param {Object} camera camera对象
|
||||
* @return {Object} shape对象
|
||||
*/
|
||||
adjust: function(shape, camera) {
|
||||
pathAdjust(shape.points, camera.ratio, camera.ratio, -camera.center.x, -camera.center.y);
|
||||
pathAdjust(shape.points, 1, 1, camera.center.x, camera.center.y);
|
||||
},
|
||||
|
||||
/**
|
||||
* 移动指定位置
|
||||
*
|
||||
* @return {Object} shape对象
|
||||
*/
|
||||
move: function(shape, mx, my) {
|
||||
pathAdjust(shape.points, 1, 1, mx, my);
|
||||
return shape;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 获取shape的矩形区域
|
||||
*
|
||||
* @param {Object} shape shape数据
|
||||
* @param {Object} 矩形区域
|
||||
*/
|
||||
getRect: function(shape) {
|
||||
return computeBoundingBox.computeBounding(shape.points);
|
||||
},
|
||||
|
||||
/**
|
||||
* 判断点是否在shape内部
|
||||
*
|
||||
* @param {Object} shape shape数据
|
||||
* @param {number} x x偏移
|
||||
* @param {number} y y偏移
|
||||
* @param {boolean} 是否
|
||||
*/
|
||||
isIn: function(shape, x, y) {
|
||||
var bound = computeBoundingBox.computeBounding(shape.points);
|
||||
if(
|
||||
x <= bound.x + bound.width
|
||||
&& x >= bound.x
|
||||
&& y <= bound.y + bound.height
|
||||
&& y >= bound.y
|
||||
) {
|
||||
|
||||
return isInsidePolygon(shape.points, {
|
||||
x: x,
|
||||
y: y
|
||||
});
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* 绘制一个shape对象
|
||||
*
|
||||
* @param {CanvasContext} ctx canvas的context
|
||||
* @param {Object} shape shape数据
|
||||
*/
|
||||
draw: function(ctx, shape) {
|
||||
|
||||
ctx.translate(0.5, 0.5);
|
||||
|
||||
var points = shape.points;
|
||||
var i = 0, l = points.length;
|
||||
if(shape.dashed) {
|
||||
for (; i < l - 1; i++) {
|
||||
dashedLineTo(ctx,
|
||||
Math.round(points[i].x), Math.round(points[i].y),
|
||||
Math.round(points[i+1].x), Math.round(points[i+1].y)
|
||||
);
|
||||
};
|
||||
dashedLineTo(ctx,
|
||||
Math.round(points[l-1].x), Math.round(points[l-1].y),
|
||||
Math.round(points[0].x), Math.round(points[0].y)
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
ctx.moveTo(Math.round(points[0].x), Math.round(points[0].y));
|
||||
for (i = 1; i < l; i++) {
|
||||
ctx.lineTo(
|
||||
Math.round(points[i].x), Math.round(points[i].y)
|
||||
);
|
||||
};
|
||||
ctx.lineTo(
|
||||
Math.round(points[0].x), Math.round(points[0].y)
|
||||
);
|
||||
}
|
||||
ctx.translate(-0.5, -0.5);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
return require('./Shape').derive(proto);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file DashedRect.js
|
||||
* @file Rect.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
@@ -62,13 +62,13 @@ define(
|
||||
dashedLineTo(ctx, x + w, y, x + w, y + h);
|
||||
dashedLineTo(ctx, x + w, y + h, x, y + h);
|
||||
dashedLineTo(ctx, x, y + h, x, y);
|
||||
|
||||
}
|
||||
else {
|
||||
ctx.lineTo(x, y, x + w, y);
|
||||
ctx.lineTo(x + w, y, x + w, y + h);
|
||||
ctx.lineTo(x + w, y + h, x, y + h);
|
||||
ctx.lineTo(x, y + h, x, y);
|
||||
ctx.moveTo(x, y);
|
||||
ctx.lineTo(x + w, y);
|
||||
ctx.lineTo(x + w, y + h);
|
||||
ctx.lineTo(x, y + h);
|
||||
ctx.lineTo(x, y);
|
||||
}
|
||||
ctx.translate(-0.5, -0.5);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ define(
|
||||
var support = {
|
||||
circle: require('./Circle'),
|
||||
cpoint: require('./CirclePoint'),
|
||||
rect: require('./Rect'),
|
||||
point: require('./Point'),
|
||||
rect: require('./Rect'),
|
||||
polygon: require('./Polygon'),
|
||||
font: require('./Font'),
|
||||
path: require('./Path'),
|
||||
axis: require('./Axis')
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* @file pathAdjust.js
|
||||
* @author mengke01
|
||||
* @date
|
||||
* @description
|
||||
* 路径调整
|
||||
*/
|
||||
|
||||
|
||||
define(
|
||||
function(require) {
|
||||
return require('ttf/util/contourAdjust');
|
||||
}
|
||||
);
|
||||
@@ -13,7 +13,7 @@ define(
|
||||
var lang = require('common/lang');
|
||||
var computeBoundingBox = require('../../graphics/computeBoundingBox');
|
||||
var isPathCross = require('../../graphics/isPathCross');
|
||||
var pathAdjust = require('./pathAdjust');
|
||||
var pathAdjust = require('graphics/pathAdjust');
|
||||
|
||||
/**
|
||||
* 从待选的shape中选择一个,作为选中的shape
|
||||
|
||||
Reference in New Issue
Block a user