jquery使用鼠标调整旋转图像的大小(mousemove事件)

时间:2017-07-16 10:25:18

标签: javascript jquery html svg resize

我正在尝试创建控件,允许我使用(nw,n,ne,e,se,s,sw,w)控件调整当前对象(在本例中为图像)的大小,当没有旋转调整大小时工作完善否则它不起作用,我试图解决它,我也搜索它,但我最后在这里寻求帮助。

顺便说一句,我不想​​使用svgjs等插件

这是我的代码: https://jsfiddle.net/z0fd9fqe/13/

HTML:

   <svg width="400" height="400" transform="scale(1)">
  <rect id="_svg_editor_background_" fill="#fafafa" width="100%" height="100%"></rect>
  <g id="active_group" transform="">
    <rect x="100" y="138" width="200" height="125" stroke-width="2" stroke="red" fill="transparent" class="active-control-border" pointer-events="none"></rect>
    <image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://eskipaper.com/images/berries-nature-winter-1.jpg" preserveAspectRatio="none" x="100" y="138.5" width="200px" class=""></image>
    <circle cx="200" cy="200.5" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-center" style="null"></circle>
    <circle cx="200" cy="118" r="6" fill="rgba(150, 243, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-rotator" style="cursor: crosshair;"></circle>
    <circle cx="100" cy="138" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-nw" style="cursor: nw-resize;"></circle>
    <circle cx="200" cy="138" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-n" style="cursor: n-resize;"></circle>
    <circle cx="300" cy="138" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-ne" style="cursor: ne-resize;"></circle>
    <circle cx="300" cy="200.5" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-e" style="cursor: e-resize;"></circle>
    <circle cx="300" cy="263" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-se" style="cursor: se-resize;"></circle>
    <circle cx="200" cy="263" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-s" style="cursor: s-resize;"></circle>
    <circle cx="100" cy="263" r="6" fill="rgba(33, 150, 243, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-sw" style="cursor: sw-resize;"></circle>
    <circle cx="100" cy="200.5" r="6" fill="rgba(243, 150, 33, 0.6)" strokeWidth="1" stroke="slateblue" class="active-control-w" style="cursor: w-resize;"></circle>
  </g>
</svg>
<div id="console">
X: <span id="x">0px</span><br>
Y: <span id="y">0px</span><br>
Width: <span id="width">0px</span><br>
Height: <span id="height">0px</span><br>
Center: <span id="center">0px</span><br>
Rotation: <span id="rot">0deg</span><br>
Rotation Center: <span id="rotcenter">{x:0px,y:0px}</span><br>

</div>

CSS:

    #console{
  position:absolute;
  bottom:10px;
  left:10px;
}

JS:

//DRAGGING 
$('image').mousedown(function(e){

if (!$(this).is('[class^=active-control-]') && !$(e.target).is('[class^=active-control-]')) {
    var elem = this;
    if ($(this).is('g#active_group')) {
        elem = $(this).find(':not([class^=active-control-])').get(0);
    }

    var pageX0 = e.pageX;
    var pageY0 = e.pageY;

    var init_scale = {width: elem.getBBox().width, height: elem.getBBox().height};
    var init_offset = {x: parseInt($(elem).attr('x')), y: parseInt($(elem).attr('y'))};

    function handle_dragging(e) {

        var x = init_offset.x + (e.pageX - pageX0);
        var y = init_offset.y + (e.pageY - pageY0);


        //change center of rotation to match new element center when dragging
        var trans = transform2Array(elem);
        if (!Object.values(trans).length) {
            trans = transform2Array($(elem).parent());
        }
        var transform = "";
        if (trans.rotate != undefined) {
            var rot_cx = x + init_scale.width / 2;
            var rot_cy = y + init_scale.height / 2;
            transform += "rotate(" + trans.rotate[0] + "," + rot_cx + "," + rot_cy + ")";
        }
        $(elem).attr({x: x, y: y});
        //fix bug rotate +90 drag rotate clear  select& drag => rotate svg element !
        if ($(elem).parent().is('g#active_group'))
            $(elem).parent().attr({transform: transform});
        updateControls($(elem));//update controls to match the new position
    }

    function handle_mouseup(e) {

        $('body')
            .off('mousemove', handle_dragging)
            .off('mouseup', handle_mouseup);
    }

    $('body')
        .on('mouseup', handle_mouseup)
        .on('mousemove', handle_dragging);
}

});
//END OF DRAGGING

$('circle[class^=active-control-]').mousedown(function(md_e) {
  var $control = $(this);
  var $element = $('image:first');
  var control_name = $(this).attr('class').replace('active-control-', '').trim();
  var pageX0 = md_e.pageX;
  var pageY0 = md_e.pageY;
  var init_offset = {
    x: $element.get(0).getBBox().x,
    y: $element.get(0).getBBox().y
  };
  var init_scale = {
    width: $element.get(0).getBBox().width,
    height: $element.get(0).getBBox().height
  };

  console.log('im dragging from ' + control_name);

  function handle_dragging(d_e) {
    if (control_name == 'rotator') {
      //rotate fix source: https://stackoverflow.com/questions/32640642/svg-angle-rotation-by-mousemove-touchmove-bug
      var rx = parseFloat($element.get(0).getBBox().width);
      var ry = parseFloat($element.get(0).getBBox().height);
      var ctm = $element.get(0).getScreenCTM()
      var p = $('svg').get(0).createSVGPoint()

      p.x = d_e.clientX
      p.y = d_e.clientY
      p = p.matrixTransform(ctm.inverse())

      var elem_center_x = init_offset.x + rx / 2;
      var elem_center_y = init_offset.y + ry / 2;
      var radians = Math.atan2(elem_center_x - p.x, elem_center_y - p.y);
      var degree = (radians * (180 / Math.PI) * -1) + 0;

      var new_angle = (getAngle($element) + degree);
      if (new_angle > 360) {
        new_angle -= 360;
      }
      if (new_angle < -360) {
        new_angle += 360;
      }
      $('#console #rot').text(new_angle+"deg");
      $('#console #rotcenter').text(JSON.stringify({x:elem_center_x+"px",y:elem_center_y+"px"}));
      if ($element.parent().is('g#active_group') || $element.is('g#active_group')) {
        $element.parent()
          .attr("transform", "rotate(" + new_angle + "," + elem_center_x + "," + elem_center_y + ")");
      }
    } else {
      makeResize(control_name[0]);
      if (control_name.length == 2) {
        makeResize(control_name[1]);
      }
    }
    updateControls($element);

    function makeResize(direction) {
      var dx = d_e.pageX - pageX0;
      var dy = d_e.pageY - pageY0;
      //do resizing here for each control while image is rotated at any angle
      //change width, height, and coords(x,y)
      switch (direction) {
        case "e":
          $element.attr('width', Math.max(init_scale.width + dx, 10));
          break;
        case "w":
          if ($element.attr('width') != 10)
        $element.attr('x', init_offset.x + dx);
            $element.attr('width', Math.max(init_scale.width - dx, 10));
            break;
        case "s":
          $element.attr('height', Math.max(init_scale.height + dy, 10));
          break;
        case "n": //
          if ($element.attr('height') != 10)
            $element.attr('y', init_offset.y + dy);
          $element.attr('height', Math.max(init_scale.height - dy, 10));
          break;
      }
    }



  }

  function handle_mouseup() {
    $('body').css('cursor', 'default');
    $('body')
      .off('mousemove', handle_dragging)
      .off('mouseup', handle_mouseup);
  }

  $('body')
    .on('mouseup', handle_mouseup)
    .on('mousemove', handle_dragging);
});

function updateControls($element) {
  $element = $($element); //ensure its jquery object 
  var width = parseInt($element.get(0).getBBox().width),
    height = parseInt($element.get(0).getBBox().height),
    data = {
      x: parseInt($element.attr('x')),
      y: parseInt($element.attr('y')),
      rx: width,
      ry: height,
      angle: 0
    };

  var controls = [{
      x: data.x + data.rx / 2,
      y: data.y - 20,
      name: "rotator"
    }, {
      x: data.x + data.rx / 2,
      y: data.y + data.ry / 2,
      name: "center"
    },

    {
      x: data.x,
      y: data.y,
      name: "nw"
    }, {
      x: data.x + data.rx / 2,
      y: data.y,
      name: "n"
    }, {
      x: data.x + data.rx,
      y: data.y,
      name: "ne"
    }, {
      x: data.x + data.rx,
      y: data.y + data.ry / 2,
      name: "e"
    },

    {
      x: data.x + data.rx,
      y: data.y + data.ry,
      name: "se"
    }, {
      x: data.x + data.rx / 2,
      y: data.y + data.ry,
      name: "s"
    }, {
      x: data.x,
      y: data.y + data.ry,
      name: "sw"
    }, {
      x: data.x,
      y: data.y + data.ry / 2,
      name: "w"
    }
  ];
  var bounderAttrs = {
    x: $element.attr('x'),
    y: $element.attr('y'),
    width: $element.attr('width'),
    height: $element.attr('height'),
  };
  $('#console #x').text($element.attr('x')+"px");
  $('#console #y').text($element.attr('y')+"px");
  $('#console #width').text(bounderAttrs.width);
  $('#console #height').text(bounderAttrs.height?bounderAttrs.height+"px":'AUTO SCALED');

  if ($element.parent().is('g#active_group')) {
    $element.parent().find('.active-control-border').attr(bounderAttrs);
    $.each(controls, function(i, o) {
    if(o.name=='center'){
     $('#console #center').text(JSON.stringify({x:o.x+"px",y:o.y+"px"}));
    }
      $element.parent().find('circle.active-control-' + o.name).attr({
        cx: o.x,
        cy: o.y
      });
    });
    return;
  }

}
//get elem angle from transform attribute
function getAngle(elem) {
  var angle = 0;
  var trans = transform2Array(elem);
  if (!Object.values(trans).length) {
    trans = transform2Array(elem.parent());
  }
  if (trans.rotate != undefined) {
    angle = parseFloat(trans.rotate[0]);
  }
  return angle;
}
/**
 * get tranform attribute values as array transform="rotate(x,y,z) scale(x,y)"
 *  return {
 *      rotate:[x,y,z]
 *      scale:[x,y]
 *        }
 */
function transform2Array(elem) {
  var transform = $(elem).attr('transform');
  var transforms = {};
  if (typeof transform !== 'undefined') {
    $.each(transform.split(' '), function(i, o) {
      if (o.length) {
        var trans = o.replace(')', '').split('(');
        transforms[trans[0]] = [];
        var params = trans[1].split(',');
        $.each(params, function(i, o_param) {
          transforms[trans[0]].push(parseFloat(o_param));
        });
      }
    });
  }
  return transforms;
}
updateControls($('image'))

0 个答案:

没有答案