#javascript #svg
Ссылка: 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; }
Ответы
Ответ 1
В случае с поворотом координата при перемещении мышью зависит от обоих смещений(по 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; }
Комментариев нет:
Отправить комментарий