Ссылка: jsfiddle
Используемая библиотека Raphael.js и плагин Raphael.FreeTransform.
Используемые технологии: SVG, JavaScript.
Строки:
инициализация холста: 125;
функция для перемещения точек: 260.
Проблема: Если повернуть прямоугольник на определенный угол поворота и после попробовать передвинуть точки для изменения его размера, то точки будут неправильно себя вести при перемещении.
Помогите, пожалуйста, исправить данную проблему..
(function(win, Raphael) {
'use strict';
function Paper() {
var self = this;
self.elementId = 'paper';
self.width = win.innerWidth;
self.height = win.innerHeight;
self.paper = {};
}
Paper.prototype.Init = function(args) {
var self = this;
var elementId;
var width;
var height;
try {
args = args || {};
elementId = args.id || self.elementId;
width = args.width || self.width;
height = args.height || self.height;
self.paper = Raphael(elementId, width, height);
}
catch(error) {
console.error(error);
}
return self;
};
Paper.prototype.get = function() {
var paper = {};
try {
paper = this.paper;
}
catch(error) {
console.error(error);
}
return paper;
};
win.Paper = win.Paper || new Paper;
})(typeof window !== 'undefined' ? window : this, Raphael);
(function(win) {
'use strict';
if(typeof win.Paper !== 'object') {
return false;
}
function Shape() {
var self = this;
self.properties = {
circleOptions : {
fill : '#FFD100',
fillOpacity : 1,
stroke : '#FFD100',
strokeOpacity : 1,
strokeWidth : 3,
strokeLinecap : 'round',
strokeLinejoin : 'round',
strokeDasharray : 0
},
rectOptions : {
fill : '#FFF20F',
fillOpacity : 1,
stroke : '#FFD103',
strokeOpacity : 1,
strokeWidth : 3,
strokeLinecap : 'round',
strokeLinejoin : 'round',
strokeDasharray : 0
}
};
}
Shape.prototype.addPoint = function(x, y, r, properties) {
var self = this;
var element = {};
try {
x = x || 0;
y = y || 0;
r = r || 5;
properties = properties || {};
element = win.Paper.get().circle(x, y, r).attr({
'fill' : properties.fill || self.properties.circleOptions.fill,
'fill-opacity' : properties.fillOpacity || self.properties.circleOptions.fillOpacity,
'stroke' : properties.stroke || self.properties.circleOptions.stroke,
'stroke-opacity' : properties.strokeOpacity || self.properties.circleOptions.strokeOpacity,
'stroke-width' : properties.strokeWidth || self.properties.circleOptions.strokeWidth,
'stroke-linecap' : properties.strokeLinecap || self.properties.circleOptions.strokeLinecap,
'stroke-linejoin' : properties.strokeLinejoin || self.properties.circleOptions.strokeLinejoin,
'stroke-dasharray' : properties.strokeDasharray || self.properties.circleOptions.strokeDasharray
});
element[0].setAttributeNS(null, 'id', element.id);
}
catch(error) {
console.error(error);
}
return {
'element' : element,
'coords' : {
'x' : x,
'y' : y,
'r' : r
}
};
};
win.Paper.Shape = new Shape();
})(typeof window !== 'undefined' ? window : this);
(function(win) {
var groupElements;
var radius = 10;
var pathData;
var rectangle;
var point1;
var point2;
var point3;
var point4;
var _objects = {
'paths' : {},
'points' : {}
};
var path = {};
var pointElements = {};
var customizationOptions = {
fill : '#FFFFFF',
fillOpacity : 1,
stroke : '#000000',
strokeOpacity : 0.5,
strokeWidth : 1,
strokeLinecap : 'round',
strokeLinejoin : 'round'
};
var freeTransformOptions = {
attrs : {
'fill' : customizationOptions.fill,
'fill-opacity' : customizationOptions.fillOpacity,
'stroke' : customizationOptions.stroke,
'stroke-opacity' : customizationOptions.strokeOpacity,
'stroke-width' : customizationOptions.strokeWidth,
'stroke-linecap' : customizationOptions.strokeLinecap,
'stroke-linejoin' : customizationOptions.strokeLinejoin
},
draw : [],
distance : 0,
drag : [],
keepRatio : [],
range : {
rotate : [-180, 180],
scale : [-99999, 99999]
},
rotate : [],
scale : [],
size : 0,
snap : {
drag : 0,
rotate : 0,
scale : 0
},
snapDist : {
drag : 0,
rotate : 0,
scale : 0
}
};
var freeTransformObj;
var resizeModule;
// style options
win.Paper.Shape.properties.rectOptions.strokeOpacity = 0.5;
win.Paper.Shape.properties.rectOptions.fillOpacity = 0.2;
win.Paper.Shape.properties.circleOptions.radius = 10;
win.Paper.Shape.properties.circleOptions.strokeWidth = 0;
win.Paper.Shape.properties.circleOptions.fillOpacity = 0.7;
// rotate options
freeTransformOptions.distance = 1.3;
freeTransformOptions.size = 5;
freeTransformOptions.rotate = ['axisX', 'axisY'];
win.Paper.Init({
id : 'paper',
width : 1024,
height : 1024
});
pathData = [['M', 105, 105], ['L', 250, 105], ['L', 250, 150], ['L', 105, 150], ['Z']];
rectangle = win.Paper.get().path(pathData).attr({
'fill' : win.Paper.Shape.properties.rectOptions.fill,
'fill-opacity' : win.Paper.Shape.properties.rectOptions.fillOpacity,
'stroke' : win.Paper.Shape.properties.rectOptions.stroke,
'stroke-opacity' : win.Paper.Shape.properties.rectOptions.strokeOpacity,
'stroke-width' : win.Paper.Shape.properties.rectOptions.strokeWidth,
'stroke-linecap' : win.Paper.Shape.properties.rectOptions.strokeLinecap,
'stroke-linejoin' : win.Paper.Shape.properties.rectOptions.strokeLinejoin,
'stroke-dasharray' : win.Paper.Shape.properties.rectOptions.strokeDasharray
});
point1 = win.Paper.Shape.addPoint(pathData[0][1], pathData[0][2], radius).element;
point2 = win.Paper.Shape.addPoint(pathData[1][1], pathData[1][2], radius).element;
point3 = win.Paper.Shape.addPoint(pathData[2][1], pathData[2][2], radius).element;
point4 = win.Paper.Shape.addPoint(pathData[3][1], pathData[3][2], radius).element;
groupElements = win.Paper.get().set();
groupElements.push(rectangle);
groupElements.push(point1);
groupElements.push(point2);
groupElements.push(point3);
groupElements.push(point4);
for(var key in groupElements) {
if(groupElements.hasOwnProperty(key)) {
if(groupElements[key].type === 'path') {
path['element'] = groupElements[key];
_objects.paths[groupElements[key].id] = {
path : path,
pointElements : pointElements
};
}
else {
if(groupElements[key].type === 'circle') {
pointElements[groupElements[key].id] = {
path : path,
pointElement : groupElements[key],
index : key - 1
};
_objects.points[groupElements[key].id] = pointElements[groupElements[key].id];
}
}
}
}
freeTransformObj = win.Paper.get().freeTransform(groupElements, freeTransformOptions);
resizeModule = new resize();
groupElements.drag(function onmove(dx, dy, x, y, event) {
resizeModule.move(dx, dy);
}, function onstart(x, y, event) {
resizeModule.start(x, y, event);
}, function onend(event) {
resizeModule.end(event);
});
function resize() {
var pathElement = {};
var currentElement;
var path = [];
var index = 0;
var pointElement = {};
var posX = 0;
var posY = 0;
this.start = function(x, y, event) {
if(currentElement = event.target || event.srcElement) {
if(_objects.points[currentElement.id]) {
pointElement = _objects.points[currentElement.id].pointElement;
pathElement = _objects.points[pointElement.id].path.element;
index = _objects.points[pointElement.id].index;
posX = pointElement.attrs.cx;
posY = pointElement.attrs.cy;
path = pathElement.getPath();
}
}
};
this.move = function(dx, dy) {
var x = 0;
var y = 0;
var pointElements;
var bbox;
var middlePoint = {};
var point;
if(currentElement.nodeName === 'circle' && path.length) {
x = posX + dx;
y = posY + dy;
pointElement.attr({cx : x});
path[index][1] = x;
pointElement.attr({cy : y});
path[index][2] = y;
pathElement.attr({
path : path
});
}
};
this.end = function(event) {};
}
})(typeof window !== 'undefined' ? window : this);
#paper {
min-height : 768px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.8/raphael.js"></script>
<script src="https://alias.io/raphael/free_transform/raphael.free_transform/raphael.free_transform.js"></script>
<div id="paper"></div>
В случае с поворотом координата при перемещении мышью зависит от обоих смещений(по X и по Y), необходимо учесть угол поворота, как то так:
this.move = function(dx, dy) {
...
let angle = groupElements.freeTransform.attrs.rotate/180*Math.PI;
y = posY + dy*Math.cos(angle) - dx*Math.sin(angle);
x = posX + dy*Math.sin(angle) + dx*Math.cos(angle);
...
}
(function(win, Raphael) {
'use strict';
function Paper() {
var self = this;
self.elementId = 'paper';
self.width = win.innerWidth;
self.height = win.innerHeight;
self.paper = {};
}
Paper.prototype.Init = function(args) {
var self = this;
var elementId;
var width;
var height;
try {
args = args || {};
elementId = args.id || self.elementId;
width = args.width || self.width;
height = args.height || self.height;
self.paper = Raphael(elementId, width, height);
}
catch(error) {
console.error(error);
}
return self;
};
Paper.prototype.get = function() {
var paper = {};
try {
paper = this.paper;
}
catch(error) {
console.error(error);
}
return paper;
};
win.Paper = win.Paper || new Paper;
})(typeof window !== 'undefined' ? window : this, Raphael);
(function(win) {
'use strict';
if(typeof win.Paper !== 'object') {
return false;
}
function Shape() {
var self = this;
self.properties = {
circleOptions : {
fill : '#FFD100',
fillOpacity : 1,
stroke : '#FFD100',
strokeOpacity : 1,
strokeWidth : 3,
strokeLinecap : 'round',
strokeLinejoin : 'round',
strokeDasharray : 0
},
rectOptions : {
fill : '#FFF20F',
fillOpacity : 1,
stroke : '#FFD103',
strokeOpacity : 1,
strokeWidth : 3,
strokeLinecap : 'round',
strokeLinejoin : 'round',
strokeDasharray : 0
}
};
}
Shape.prototype.addPoint = function(x, y, r, properties) {
var self = this;
var element = {};
try {
x = x || 0;
y = y || 0;
r = r || 5;
properties = properties || {};
element = win.Paper.get().circle(x, y, r).attr({
'fill' : properties.fill || self.properties.circleOptions.fill,
'fill-opacity' : properties.fillOpacity || self.properties.circleOptions.fillOpacity,
'stroke' : properties.stroke || self.properties.circleOptions.stroke,
'stroke-opacity' : properties.strokeOpacity || self.properties.circleOptions.strokeOpacity,
'stroke-width' : properties.strokeWidth || self.properties.circleOptions.strokeWidth,
'stroke-linecap' : properties.strokeLinecap || self.properties.circleOptions.strokeLinecap,
'stroke-linejoin' : properties.strokeLinejoin || self.properties.circleOptions.strokeLinejoin,
'stroke-dasharray' : properties.strokeDasharray || self.properties.circleOptions.strokeDasharray
});
element[0].setAttributeNS(null, 'id', element.id);
}
catch(error) {
console.error(error);
}
return {
'element' : element,
'coords' : {
'x' : x,
'y' : y,
'r' : r
}
};
};
win.Paper.Shape = new Shape();
})(typeof window !== 'undefined' ? window : this);
(function(win) {
var groupElements;
var radius = 10;
var pathData;
var rectangle;
var point1;
var point2;
var point3;
var point4;
var _objects = {
'paths' : {},
'points' : {}
};
var path = {};
var pointElements = {};
var customizationOptions = {
fill : '#FFFFFF',
fillOpacity : 1,
stroke : '#000000',
strokeOpacity : 0.5,
strokeWidth : 1,
strokeLinecap : 'round',
strokeLinejoin : 'round'
};
var freeTransformOptions = {
attrs : {
'fill' : customizationOptions.fill,
'fill-opacity' : customizationOptions.fillOpacity,
'stroke' : customizationOptions.stroke,
'stroke-opacity' : customizationOptions.strokeOpacity,
'stroke-width' : customizationOptions.strokeWidth,
'stroke-linecap' : customizationOptions.strokeLinecap,
'stroke-linejoin' : customizationOptions.strokeLinejoin
},
draw : [],
distance : 0,
drag : [],
keepRatio : [],
range : {
rotate : [-180, 180],
scale : [-99999, 99999]
},
rotate : [],
scale : [],
size : 0,
snap : {
drag : 0,
rotate : 0,
scale : 0
},
snapDist : {
drag : 0,
rotate : 0,
scale : 0
}
};
var freeTransformObj;
var resizeModule;
// style options
win.Paper.Shape.properties.rectOptions.strokeOpacity = 0.5;
win.Paper.Shape.properties.rectOptions.fillOpacity = 0.2;
win.Paper.Shape.properties.circleOptions.radius = 10;
win.Paper.Shape.properties.circleOptions.strokeWidth = 0;
win.Paper.Shape.properties.circleOptions.fillOpacity = 0.7;
// rotate options
freeTransformOptions.distance = 1.3;
freeTransformOptions.size = 5;
freeTransformOptions.rotate = ['axisX', 'axisY'];
win.Paper.Init({
id : 'paper',
width : 1024,
height : 1024
});
pathData = [['M', 105, 105], ['L', 250, 105], ['L', 250, 150], ['L', 105, 150], ['Z']];
rectangle = win.Paper.get().path(pathData).attr({
'fill' : win.Paper.Shape.properties.rectOptions.fill,
'fill-opacity' : win.Paper.Shape.properties.rectOptions.fillOpacity,
'stroke' : win.Paper.Shape.properties.rectOptions.stroke,
'stroke-opacity' : win.Paper.Shape.properties.rectOptions.strokeOpacity,
'stroke-width' : win.Paper.Shape.properties.rectOptions.strokeWidth,
'stroke-linecap' : win.Paper.Shape.properties.rectOptions.strokeLinecap,
'stroke-linejoin' : win.Paper.Shape.properties.rectOptions.strokeLinejoin,
'stroke-dasharray' : win.Paper.Shape.properties.rectOptions.strokeDasharray
});
point1 = win.Paper.Shape.addPoint(pathData[0][1], pathData[0][2], radius).element;
point2 = win.Paper.Shape.addPoint(pathData[1][1], pathData[1][2], radius).element;
point3 = win.Paper.Shape.addPoint(pathData[2][1], pathData[2][2], radius).element;
point4 = win.Paper.Shape.addPoint(pathData[3][1], pathData[3][2], radius).element;
groupElements = win.Paper.get().set();
groupElements.push(rectangle);
groupElements.push(point1);
groupElements.push(point2);
groupElements.push(point3);
groupElements.push(point4);
for(var key in groupElements) {
if(groupElements.hasOwnProperty(key)) {
if(groupElements[key].type === 'path') {
path['element'] = groupElements[key];
_objects.paths[groupElements[key].id] = {
path : path,
pointElements : pointElements
};
}
else {
if(groupElements[key].type === 'circle') {
pointElements[groupElements[key].id] = {
path : path,
pointElement : groupElements[key],
index : key - 1
};
_objects.points[groupElements[key].id] = pointElements[groupElements[key].id];
}
}
}
}
freeTransformObj = win.Paper.get().freeTransform(groupElements, freeTransformOptions);
resizeModule = new resize();
groupElements.drag(function onmove(dx, dy, x, y, event) {
resizeModule.move(dx, dy);
}, function onstart(x, y, event) {
resizeModule.start(x, y, event);
}, function onend(event) {
resizeModule.end(event);
});
function resize() {
var pathElement = {};
var currentElement;
var path = [];
var index = 0;
var pointElement = {};
var posX = 0;
var posY = 0;
this.start = function(x, y, event) {
if(currentElement = event.target || event.srcElement) {
if(_objects.points[currentElement.id]) {
pointElement = _objects.points[currentElement.id].pointElement;
pathElement = _objects.points[pointElement.id].path.element;
index = _objects.points[pointElement.id].index;
posX = pointElement.attrs.cx;
posY = pointElement.attrs.cy;
path = pathElement.getPath();
}
}
};
this.move = function(dx, dy) {
var x = 0;
var y = 0;
var pointElements;
var bbox;
var middlePoint = {};
var point;
if(currentElement.nodeName === 'circle' && path.length) {
let angle = groupElements.freeTransform.attrs.rotate/180*Math.PI;
y = posY + dy*Math.cos(angle) - dx*Math.sin(angle);
x = posX + dy*Math.sin(angle) + dx*Math.cos(angle);
pointElement.attr({cx : x});
path[index][1] = x;
pointElement.attr({cy : y});
path[index][2] = y;
pathElement.attr({
path : path
});
}
};
this.end = function(event) {};
}
})(typeof window !== 'undefined' ? window : this);
#paper {
min-height : 768px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.2.8/raphael.js"></script>
<script src="https://alias.io/raphael/free_transform/raphael.free_transform/raphael.free_transform.js"></script>
<div id="paper"></div>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Во всех учебниках и уроках что я читал, всегда пишут что первым выполнится тот оператор в выражении, у которого больше приоритетИ вроде бы это...
Столкнулся со странной ситуацией, есть функция которая должна просто удалить все пробелы в строке:
Недавно начал изучать JS, для практики решил написать небольшой калькуляторВсе в нем более-менее работает, но интересует вопрос, как оптимизировать...