2016-11-10 3 views
3

Попытка применить поворот, перемещение и изменение размера с помощью мыши на элементе SVG. Here вы можете проверить это.svg вращение, масштабирование и перевод с помощью мыши

В настоящее время я работал над южным управлением, центральным управлением и управлением поворотом.

  1. Вращение работает отлично, я могу вращаться, останавливаться и снова вращаться. Но после того, как я перемещаю элемент, перетаскивая центральную точку, вращение сначала начинает мигать, а начальная точка вращения отличается. Я верю, что это потому, что положение центра меняется после перевода. Я попытался перераспределить позицию центра, но это не сработало.

  2. И масштабирование перемещает элемент вместо увеличения размера.

Пожалуйста, помогите мне в этом. Я не могу получить некоторые корректировки здесь.

Примечание: сначала вы нарисовали какой-то путь с помощью мыши, чтобы получить контроль над ним.

var svg = document.querySelector('.container'); 
 
var svgns = 'http://www.w3.org/2000/svg'; 
 

 
var path = document.createElementNS(svgns, 'path'); 
 
svg.appendChild(path); 
 

 
var points = []; 
 
var Resizer_Instance = null; 
 

 
var boundingBox = svg.getBoundingClientRect(); 
 

 
var toSVGPath = function(points) { 
 
    var SVGPath = ''; 
 
    for (var i = 0; i < points.length; i++) { 
 
    var prefix = (i == 0) ? 'M' : 'L'; 
 
    SVGPath += prefix + points[i].x + ' ' + points[i].y + ' '; 
 
    } 
 
    return SVGPath; 
 
}; 
 

 
var create_mousedown = false; 
 

 
var createStart = function(event) { 
 
    create_mousedown = true; 
 
}; 
 

 
var creating = function(event) { 
 
    if (create_mousedown) { 
 
    var point = svg.createSVGPoint(); 
 
    point.x = event.clientX - boundingBox.left; 
 
    point.y = event.clientY - boundingBox.top; 
 
    var t = point.matrixTransform(svg.getScreenCTM().inverse()); 
 
    points.push(t); 
 
    path.setAttributeNS(null, 'd', toSVGPath(points)); 
 
    } 
 
}; 
 

 
var createEnd = function(event) { 
 
    create_mousedown = true; 
 
    svg.removeEventListener('mousedown', createStart); 
 
    svg.removeEventListener('mousemove', creating); 
 
    svg.removeEventListener('mouseup', createEnd); 
 
    setTimeout(function functionName() { 
 
    Resizer_Instance = new Resizer(path, svg); 
 
    }, 500); 
 
}; 
 

 
svg.addEventListener('mousedown', createStart); 
 
svg.addEventListener('mousemove', creating); 
 
svg.addEventListener('mouseup', createEnd); 
 

 

 
var Resizer = (function() { 
 

 
    function Resizer(element) { 
 
    var that = this; 
 
    that.element = element; 
 
    createSelector.call(that); 
 

 
    document.addEventListener('mousemove', dragging); 
 
    document.addEventListener('mouseup', dragend); 
 

 
    } 
 

 
    var RAD2DEG = 180/Math.PI; 
 

 
    function angleBetweenPoints(p1, p2) { 
 
    var angle = null; 
 
    if (p1.x == p2.x && p1.y == p2.y) 
 
     angle = Math.PI/2; 
 
    else 
 
     angle = Math.atan2(p2.y - p1.y, p2.x - p1.x); 
 
    return (angle * RAD2DEG) + -90; 
 
    } 
 

 
    function controlPositions(el) { 
 
    var pt = svg.createSVGPoint(); 
 
    var bbox = el.getBoundingClientRect(); 
 
    var matrix = el.getScreenCTM().inverse(); 
 
    var halfWidth = bbox.width/2; 
 
    var halfHeight = bbox.height/2; 
 
    var placements = {}; 
 

 
    pt.x = bbox.left; 
 
    pt.y = bbox.top; 
 

 
    placements['nw'] = pt.matrixTransform(matrix); 
 
    pt.x += halfWidth; 
 
    placements['n'] = pt.matrixTransform(matrix); 
 
    pt.x += halfWidth; 
 
    placements['ne'] = pt.matrixTransform(matrix); 
 
    pt.y += halfHeight; 
 
    placements['e'] = pt.matrixTransform(matrix); 
 
    pt.y += halfHeight; 
 
    placements['se'] = pt.matrixTransform(svg.getScreenCTM().inverse()); 
 
    pt.x -= halfWidth; 
 
    placements['s'] = pt.matrixTransform(matrix); 
 
    pt.x -= halfWidth; 
 
    placements['sw'] = pt.matrixTransform(matrix); 
 
    pt.y -= halfHeight; 
 
    placements['w'] = pt.matrixTransform(matrix); 
 
    pt.x += halfWidth; 
 
    placements['center'] = pt.matrixTransform(matrix); 
 
    pt.y -= (halfHeight + 30); 
 
    placements['rot'] = pt.matrixTransform(matrix); 
 

 
    return placements; 
 
    } 
 

 
    var dragging_element = null; 
 

 
    var dragstart = function(event) { 
 
    var box = this; 
 
    var context = box.context; 
 
    var rootContext = context.rootContext; 
 
    rootContext.current_handle_inaction = context.direction; 
 
    dragging_element = box; 
 
    }; 
 

 
    var dragging = function(event) { 
 
    if (!dragging_element) return; 
 
    var box = dragging_element; 
 
    var context = box.context; 
 
    var rootContext = context.rootContext; 
 
    var currentHandle = rootContext.current_handle_inaction; 
 
    var control_points = rootContext.control_points; 
 

 
    if (currentHandle === context.direction) { 
 
     var point = svg.createSVGPoint(); 
 
     point.x = event.clientX; 
 
     point.y = event.clientY; 
 
     var element = rootContext.element; 
 
     var transformed = point.matrixTransform(svg.getScreenCTM().inverse()); 
 

 
     var centerPosition = context.center; 
 

 
     rootContext.angle = rootContext.angle || 0; 
 
     rootContext.hMove = rootContext.hMove || 0; 
 
     rootContext.vMove = rootContext.vMove || 0; 
 
     rootContext.scaleX = rootContext.scaleX || 1; 
 
     rootContext.scaleY = rootContext.scaleY || 1; 
 

 
     switch (currentHandle) { 
 
     case "rot": 
 
      rootContext.angle = angleBetweenPoints(transformed, centerPosition); 
 
      break; 
 
     case "center": 
 
      rootContext.hMove = transformed.x - centerPosition.x; 
 
      rootContext.vMove = transformed.y - centerPosition.y; 
 
      break; 
 
     case "s": 
 
      var startPos = control_points[currentHandle]; 
 
      var vMove = transformed.y - startPos.y; 
 
      rootContext.scaleY += (vMove > 0 ? -1 : 1) * 0.001; 
 
      break; 
 
     } 
 

 
     var move_transform = "translate(" + rootContext.hMove + " " + rootContext.vMove + ")"; 
 
     var rotate_transform = "rotate(" + rootContext.angle + ", " + centerPosition.x + ", " + centerPosition.y + ")"; 
 
     var scale_transform = "scale(" + rootContext.scaleX + ", " + rootContext.scaleY + ")"; 
 

 
     var transform = [move_transform, rotate_transform, scale_transform].join(' '); 
 

 
     rootContext.element.setAttribute('transform', transform); 
 
     rootContext.controlGroup.setAttribute('transform', transform); 
 
    } 
 
    }; 
 

 
    var dragend = function() { 
 
    if (!dragging_element) return; 
 
    var box = dragging_element; 
 
    var context = box.context; 
 
    var rootContext = context.rootContext; 
 
    delete rootContext.current_handle_inaction; 
 
    // createSelector.call(rootContext); 
 
    dragging_element = null; 
 
    }; 
 

 
    var adjustPositions = function() { 
 
    var that = this; 
 
    var control_points = that.control_points; 
 
    var controlGroup = that.controlGroup; 
 
    var point = svg.createSVGPoint(); 
 
    for (var direction in control_points) { 
 
     var dP = control_points[direction]; 
 
     point.x = dP.x; 
 
     point.y = dP.y; 
 
     debugger; 
 
     control_points[direction] = point.matrixTransform(controlGroup.getScreenCTM().inverse()); 
 
    } 
 
    return control_points; 
 
    }; 
 

 
    var Deg2Rad = 0.017453292519943295; 
 

 
    var createSelector = function() { 
 
    var that = this; 
 
    var points = that.control_points; 
 
    if (points) { 
 
     points = adjustPositions.call(that); 
 
    } else { 
 
     points = controlPositions(that.element, svg); 
 
    } 
 
    that.control_points = points; 
 
    var existingBoxes = {}; 
 
    var controlGroup = that.controlGroup; 
 

 
    if (!controlGroup) { 
 
     controlGroup = document.createElementNS(svgns, 'g'); 
 
     that.controlGroup = controlGroup; 
 
     svg.appendChild(controlGroup); 
 
    } 
 

 
    that.control_boxes = that.control_boxes || {}; 
 

 
    var line_name = "connecting-line", 
 
     line_element = that.control_boxes['connecting-line']; 
 

 
    var line_route = ["nw", "n", "rot", 'n', "ne", "e", "se", "s", "sw", "w", "nw"]; 
 

 
    if (!line_element) { 
 
     line_element = document.createElementNS(svgns, 'path'); 
 
     line_element.style.cssText = "fill: none; stroke: #f41542; opacity: 0.5"; 
 

 
     that.control_boxes[line_name] = line_element; 
 
     controlGroup.appendChild(line_element); 
 

 
     var pathString = ""; 
 

 
     line_route.forEach(function(direction) { 
 
     var point = points[direction]; 
 
     var command = pathString.length === 0 ? "M" : " L "; 
 
     pathString += (command + point.x + " " + point.y); 
 
     }); 
 

 
     line_element.setAttribute('d', pathString); 
 
    } 
 

 
    Object.keys(points).forEach(function(direction) { 
 
     var point = points[direction]; 
 
     var box = that.control_boxes[direction]; 
 
     if (!box) { 
 
     box = document.createElementNS(svgns, 'circle'); 
 
     box.style.cssText = "fill: #5AABAB"; 
 

 
     that.control_boxes[direction] = box; 
 
     box.setAttributeNS(null, 'r', 3); 
 
     box.setAttribute('handle', direction); 
 

 
     box.addEventListener('mousedown', dragstart.bind(box)); 
 

 
     controlGroup.appendChild(box); 
 
     } 
 

 
     box.setAttributeNS(null, 'cx', point.x); 
 
     box.setAttributeNS(null, 'cy', point.y); 
 

 
     box.context = { 
 
     point: point, 
 
     direction: direction, 
 
     rootContext: that, 
 
     center: points.center 
 
     }; 
 

 
    }); 
 

 

 
    }; 
 

 
    var prototype = { 
 
    constructor: Resizer 
 
    }; 
 
    Resizer.prototype = prototype; 
 
    return Resizer; 
 
})();
path { 
 
    fill: none; 
 
    stroke: #42B6DF; 
 
} 
 
body, 
 
html { 
 
    height: 100%; 
 
    width: 100%; 
 
    margin: 0; 
 
}
<svg class="container" version="1.1" baseProfile="full" style="position:absolute;left:0;top:0;height:100%;width:100%;-ms-transform:scale(1,1);transform:scale(1,1);-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);-ms-transform-origin:0, 0;-webkit-transform-origin:0, 0;-moz-transform-origin:0, 0;-o-transform-origin:0, 0;transform-origin:0, 0" 
 
viewBox="-220.38356461849224 6442.3347962008365 454.7376658611161 114.54981723871151"></svg>

+0

Вы никогда не обновляете свой 'box.context'. Вы только инициализируете его один раз на своей функции 'createSelector()'. – Elfayer

+0

@Elfayer Я пробовал обновлять, но позиции были неправильными. Так вернулось. – Exception

+0

Ну, это ваша проблема. Иначе почему бы вам не получить центральное положение элемента в DOM, когда вы начинаете вращаться? Вместо использования устаревшего объекта. – Elfayer

ответ

1

В настоящее время вы вычисляете угол относительно начального центра фигуры (тот, который вы только что нарисовали). Это неправильно - вам нужно рассчитать угол относительно центра фигуры после предыдущего хода.

Fiddle

Я раздели те части, которые я не изменял.

var dragging = function(event) { 
    ... 

    if (currentHandle === context.direction) { 
     ... 

     var initialCenterPosition = context.center, 
      // use the coordinates saved after last move or 
      // initial coordinates if there are none saved 
      previousCenterPosition = rootContext.previousCenterPosition || initialCenterPosition; 

     ... 

     switch (currentHandle) { 
      case "rot": 
       rootContext.angle = angleBetweenPoints(transformed, previousCenterPosition); 
       break; 
      case "center": 
       rootContext.hMove = transformed.x - initialCenterPosition.x; 
       rootContext.vMove = transformed.y - initialCenterPosition.y; 

       // remember the new center coordinates 
       rootContext.previousCenterPosition = { 
        x: transformed.x, 
        y: transformed.y 
       }; 
       break; 
      case "s": 
       ... 
     } 

     var move_transform = "translate(" + rootContext.hMove + " " + rootContext.vMove + ")"; 
     var rotate_transform = "rotate(" + rootContext.angle + ", " + initialCenterPosition.x + ", " + initialCenterPosition.y + ")"; 
     var scale_transform = "scale(" + rootContext.scaleX + ", " + rootContext.scaleY + ")"; 

     ... 
    } 
} 
+0

Perfect. Работает. – Exception

+0

@ Исключение Почему вы не принимаете ответ тогда? –

+0

Мой вопрос также включает в себя масштаб. Можете ли вы добавить это тоже – Exception

3

Вы не можете легко обрабатывать все три преобразования операции (перевод, масштаб и поворот) одними только те три преобразующих функций. Фактически вы должны использовать четыре функции.

Вы должны помнить исходную центральную точку элемента. Назовем это ocx и ocy. Затем выполните следующие действия:

  1. перевести оригинальную центральную точку начала координат
  2. выполняют в масштабе
  3. выполнять вращение
  4. перевести центр назад к новой (текущей) центральной позиции.

Так transform строка будет выглядеть примерно так:

transform="translate(ncx,ncy) rotate(rot) scale(sx,sy) translate(-ocx,-ocy)" 

Таким образом, вы можете сохранить все операции изолированы, и вам не нужно изменять других, когда один изменения.

+0

Я просто попробовал то, что вы сказали. Теперь вращение и перемещение являются странными и неконтролируемыми. Наверное, мне не хватает какой-то важной части. – Exception

+0

Не можете прочесть код – Exception

Смежные вопросы