如何在调整大小的同时使光标与控制点同步? [英] How can I make my cursor synced with the control point during a resize?

查看:116
本文介绍了如何在调整大小的同时使光标与控制点同步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个编辑器。
我希望我的对象的基本功能是旋转/调整大小翻译

我设法做了他们三个,但唯一的问题是现在我的鼠标位置不遵循控制点(问题变得更糟,其他控制点没有显示在下面)..

您将在下面找到右侧中间尺寸的示例,旋转角度为30度且没有mouseY位置,请注意,当旋转角度等于0时,鼠标完全符合我的控制点。 p>

有没有一种方法可以轻松解决这个问题,我错了吗?

这里是jsfiddle链接,可以更改代码中的旋转角度,以便自己查看 JSiddle链接。 (只需点击并拖动黑色控制点来调整对象大小)

/ /将范围amin至amax的值转换为范围bmin至bmax;函数imap(值,amin,amax,bmin,bmax){if((amax - amin))return(value - amin)*(bmax - bmin)/ (amax - amin)+ bmin; return(0);}; //从SVG元素函数获取鼠标坐标getMouse(el,e){var pt = el.createSVGPoint(); pt.x = e.clientX; pt.y = e.clientY; var cursorpt = pt.matrixTransform(el.getScreenCTM()。inverse()); return({x:cursorpt.x,y:cursorpt.y})}; var controlPoint = document.getElementById(c); //我的控制点elementvar mouseX; var mouseXClicked = 0; var scaleX = 1; var scaleY = 1; var scaleXClicked = 1; var control = false; //设置是否resizeRightMiddle()应该被执行var rectWidth = 100; //通常用getBBox()函数调用scalevar = document.getElementById(scale); function resizeRightMiddle(){//将原始鼠标X位置与实际X鼠标位置之间的差异转换为比例因子plus X = imap (mouseX - mouseXClicked,0,rectWidth,0,1); //将转换的比例因子添加到原始x比例值resX = scaleXClicked + plusX; scale.setAttribute('transform','scale('+ resX +','+ scaleY +')'); scaleX = resX;} var svg = document.getElementById(main); //在clicksvg.addEventListener(mousedown,function(e){var coord = getMouse(svg,e))上保存Scale和X鼠标坐标; mouseXClicked (); coXe; scaleXClicked = scaleX;}); svg.addEventListener(mousemove,function(e){//获取鼠标坐标var coord = getMouse(svg,e); mouseX = coord.x; // resize if如果(控制)resizeRightMiddle();}); / / desactivate resizesvg.addEventListener(mouseup,function(e){control = false;}); // activate resizecontrolPoint.addEventListener(mousedown, function(){control = true;});

svg {-webkit-touch-callout:none; -webkit-user-select:none; -khtml-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none;}

< div>< ; svg id =mainwidth =1000height =300> < g transform =translate(66,56)> < g id =rotatetransform-origin =centertransform =rotate(30)> < g id =scale> < path fill =redstroke =redd =M 0 0 L 0 100 L 100 100 L 100 0Z/> < rect id =cfill =blackstroke =blackx = 95 y = 45 width = 10 height = 10 /> < / g取代; < / g取代; < / svg>< / div>

下面的代码计算鼠标在每个mousemove事件的矩形方向上的移动量,而不是从mousedown开始移动到当前鼠标移动量。然后它会更新 updatedRectWidth ,并使用它来计算当前所需的比例。
$ b

  var controlPoint = document.getElementById(c); var control = false; var origRectWidth = 100; var scale = document.getElementById(scale); var relevantMouseMoveDist = 0 ; var updatedRectWidth = origRectWidth; var mouseDownPt = {}; var rotateDiv = document.getElementById(rotate); var rotateString = rotateDiv.getAttribute('transform'); var rectangleAngle = parseInt(rotateString.slice(rotateString.indexOf( ())* Math.PI / 180; //从DOMvar中检索角度relatedMouseMoveDist; var newMousePosn; var oldMousePosn; function resizeRightMiddle(){updatedRectWidth + = relatedMouseMoveDist; xScale = updatedRectWidth / origRectWidth; scale.setAttribute( 'transform','scale('+ xScal ());} var svg = document.getElementById(main); svg.addEventListener(mousemove,function(e){if(newMousePosn){//前鼠标pos'n oldMousePosn = {x:newMousePosn.x,y:newMousePosn.y}; //新鼠标pos'n newMousePosn = {x:e.clientX,y:e.clientY}; //自上次移动事件后鼠标位置坐标的变化var deltaMouseMove = {x:newMousePosn.x  -  oldMousePosn.x,y:newMousePosn.y  -  oldMousePosn.y}; //此运动的dir'n var angleOfMouseMovement = Math.atan2(deltaMouseMove.y,deltaMouseMove.x); //鼠标移动的绝对距离var mouseMoveDist = Math.sqrt(deltaMouseMove.x * deltaMouseMove.x + deltaMouseMove.y * deltaMouseMove.y); //鼠标移动和矩形方向之间的差异var angleDifference = angleOfMouseMovement  -  rectangleAngle; //鼠标移动的方向上矩形的方向部分relatedMouseMoveDist = mouseMoveDist * Math.cos(angleDifference);如果(控制)resizeRightMiddle(); //调整矩形的大小} else {//在第一个mousemove事件期间建立鼠标pos'n newMousePosn = {x:e.clientX,y:e.clientY}; }}); svg .addEventListener(mouseup,function(e){control = false;}); controlPoint.addEventListener(mousedown,function(e){control = true;});  

< div>< svg id =mainwidth =1000height = 300 > < g transform =translate(66,56)> < g id =rotatetransform-origin =centertransform =rotate(40)> < g id =scale> < path fill =redstroke =redd =M 0 0 L 0 100 L 100 100 L 100 0Z/> < rect id =cfill =blackstroke =blackx = 95 y = 45 width = 10 height = 10 /> < / g取代; < / g取代; < / g>< / svg>< / div>

I am creating an editor. I would like the basic functions on my objects which are rotate/resize and translate.

I've managed to do the three of them but the only problem is now my mouse position doesn't follow the control points (the problem gets even worst for the other control points not shown below)..

You'll find below an example for the right middle resize with a rotation angle of 30 degrees with no mouseY position, note that the mouse follows perfectly my control point when the rotation angle equals 0.

Is there a way easily solve this problem, am I going the wrong way?

Here's the jsfiddle link where you can change the rotate angle in the code to see by yourself JSiddle link. (Just click and drag the black control point to resize the object)

//convert value of range amin to amax to the range bmin to bmax;
function imap(value, amin, amax, bmin, bmax)
{
	if ((amax - amin))
		return (value - amin) * (bmax - bmin) / (amax - amin) + bmin;
	return (0);
};

//get mouse coordinates from the SVG element
function getMouse(el, e)
{
  var pt = el.createSVGPoint();
	pt.x = e.clientX;
	pt.y = e.clientY;
	var cursorpt =  pt.matrixTransform(el.getScreenCTM().inverse());
	return({x: cursorpt.x, y: cursorpt.y})
};

var controlPoint = document.getElementById("c"); //My control point element

var mouseX;
var mouseXClicked = 0;
var scaleX = 1;
var scaleY = 1;
var scaleXClicked = 1;
var control = false; // sets if resizeRightMiddle() should be executed
var rectWidth = 100; //is normally tooken with a getBBox() function
var scale = document.getElementById("scale");

function resizeRightMiddle()
{
  //convert difference between original mouse X postion on click and actual X mouse position into a scale factor
	plusX = imap(mouseX - mouseXClicked, 0, rectWidth, 0, 1);
  //add converted scale factor to the original x scale value
	resX = scaleXClicked + plusX;
	scale.setAttribute('transform', 'scale(' + resX + ',' + scaleY + ')');
	scaleX = resX;
}

var svg = document.getElementById("main");
// save Scale and X mouse coordinate on click
svg.addEventListener("mousedown", function(e){
	var coord = getMouse(svg, e);
	mouseXClicked = coord.x;
	scaleXClicked = scaleX;
});

svg.addEventListener("mousemove", function(e){
//get mouse coordinates
	var coord = getMouse(svg, e);
	mouseX = coord.x;
// resize if control element has been clicked
	if (control)
		resizeRightMiddle();
});

// desactivate resize
svg.addEventListener("mouseup", function(e){
	control = false;
});

//activate resize
controlPoint.addEventListener("mousedown", function(){
	control = true;
});

svg {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

<div>
<svg id="main" width="1000" height="300">
	<g transform="translate(66, 56)">
		<g id="rotate" transform-origin="center" transform="rotate(30)">
			<g id="scale">
  			<path fill="red" stroke="red" d="M 0 0 L 0 100 L 100 100 L 100 0Z" />
				<rect id="c" fill="black" stroke="black" x=95 y=45 width=10 height=10 />
			</g>
		</g>
	</g>
</svg>
</div>

解决方案

The code below calculates how much the mouse moves in the direction of the rectangle's orientation on each mousemove event, instead of from the beginning of the mousedown to the current mousemove. It then updates updatedRectWidth and uses that to calculate the current desired scale.

var controlPoint = document.getElementById("c");
var control = false;
var origRectWidth = 100;
var scale = document.getElementById("scale");
var relevantMouseMoveDist = 0;
var updatedRectWidth = origRectWidth;
var mouseDownPt = {};
var rotateDiv = document.getElementById("rotate");
var rotateString = rotateDiv.getAttribute('transform');
var rectangleAngle = parseInt(rotateString.slice(rotateString.indexOf("(") + 1)) * Math.PI / 180; // retrieve the angle from the DOM
var relevantMouseMoveDist;
var newMousePosn;
var oldMousePosn;

function resizeRightMiddle()
{
  updatedRectWidth += relevantMouseMoveDist;
  xScale = updatedRectWidth/origRectWidth;
  scale.setAttribute('transform', 'scale(' + xScale + ',1)');
}

var svg = document.getElementById("main");

svg.addEventListener("mousemove", function(e){

  if (newMousePosn) {
  
    // the former mouse pos'n
    oldMousePosn = {x: newMousePosn.x, y: newMousePosn.y};
    
    // the new mouse pos'n
    newMousePosn = {x: e.clientX, y: e.clientY};
    
    // the change in the mouse pos'n coordinates since the last move event
    var deltaMouseMove = {
      x: newMousePosn.x - oldMousePosn.x,
      y: newMousePosn.y - oldMousePosn.y
    };
    
    // the dir'n of this movement
    var angleOfMouseMovement = Math.atan2(deltaMouseMove.y, deltaMouseMove.x);
    
    // the absolute distance the mouse has moved
    var mouseMoveDist = Math.sqrt(
      deltaMouseMove.x * deltaMouseMove.x +
      deltaMouseMove.y * deltaMouseMove.y
    );
     
    // the difference in direction between the mouse movement and orientation of the rectangle
    var angleDifference = angleOfMouseMovement - rectangleAngle;
    
    // the portion of the mouse movement that is in the direction of the rectangle's orientation
    relevantMouseMoveDist = mouseMoveDist * Math.cos(angleDifference);
    
    // resize the rectangle if necessary
    if (control) resizeRightMiddle();
    
  } else {
  
    // establish the mouse pos'n during the first mousemove event
    newMousePosn = {x: e.clientX, y: e.clientY};
  }
  
});

svg         .addEventListener("mouseup"  , function(e){control = false;});
controlPoint.addEventListener("mousedown", function(e){control = true ;});

<div>
<svg id="main" width="1000" height="300">
	<g transform="translate(66, 56)">
		<g id="rotate" transform-origin="center" transform="rotate(40)">
			<g id="scale">
  			<path fill="red" stroke="red" d="M 0 0 L 0 100 L 100 100 L 100 0Z" />
				<rect id="c" fill="black" stroke="black" x=95 y=45 width=10 height=10 />
			</g>
		</g>
	</g>
</svg>
</div>

这篇关于如何在调整大小的同时使光标与控制点同步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆