- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在创建一个编辑器。我想要我的对象的基本功能,即旋转/调整大小 和翻译。
我已经设法做到了其中的三个,但现在唯一的问题是我的鼠标位置不跟随控制点(对于下面未显示的其他控制点,问题变得更糟)。
你会在下面找到一个右中间调整大小的例子,旋转 Angular 为 30 度,没有 mouseY 位置,请注意,当旋转 Angular 等于 0 时,鼠标完全跟随我的控制点。
有没有办法轻松解决这个问题,我是不是走错了路?
这里是jsfiddle链接,可以在代码中改变旋转 Angular 自己看JSiddle link . (只需单击并拖动黑色控制点即可调整对象大小)
//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>
最佳答案
下面的代码计算在每个 mousemove 事件中鼠标在矩形的方向上移动了多少,而不是从 mousedown 的开始到当前的 mousemove。然后更新 updatedRectWidth
并使用它来计算当前所需的比例。
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>
关于javascript - 如何在调整大小时使光标与控制点同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44709931/
有没有办法动态调整贝塞尔路径四曲线的控制点? 我正在为 children 创建一个小型拖放绘图应用程序。我希望他们在 Canvas 上添加一条线,然后通过拖动手指来调整曲线点以创建微笑或皱眉。 我目前
我正在开发一款安卓 UPnP/DLNA 应用程序。我有一个控制点,我可以在其中将文件从媒体服务器流式传输到渲染器。我可以在播放期间暂停/播放和停止文件,但我似乎无法弄清楚如何将搜索栏集成到控制点中以显
我能够使用这个问题的答案在 ggplot 中找到 geom_curve 控制点: How to find the geom_curve control points in ggplot 我现在想知道如
我正在开发一个类似提醒的应用程序,需要在特定时间发送通知。基本上,用户会创建某种提醒,我需要在指定时间发送通知。我正在使用 Firebase Cloud Messaging 发送通知。 我现在的想法是
我正在开发一个类似提醒的应用程序,需要在特定时间发送通知。基本上,用户会创建某种提醒,我需要在指定时间发送通知。我正在使用 Firebase Cloud Messaging 发送通知。 我现在的想法是
我一直在搜索 gcloud 文档和网络,但找不到为 gcloud 应用服务版本设置配置的方法。 在我的其他项目中已经完成,但我忘记了如何再次更新它。我想做的是对单个服务设置最大版本限制 - 例如: 使
我正在尝试为一些 NSView 的 alpha 过渡设置动画。它需要在另一个动画期间发生,特别是它的 super View (边界更改)。解释原因有点复杂,但我需要这些 alpha 转换具有计时功能,
以下怎么可能? ➢ gcloud compute instances list NAME ZONE
以下怎么可能? ➢ gcloud compute instances list NAME ZONE
我想将 Spanner 中现有表的主键从 Col1 修改为 Col1 和 Col2 的组合。可以在 Spanner 中实现吗? 此选项在控制台中不可用。也许可以用脚本来完成! 最佳答案 The key
我想使用 CyberGarage“CyberLink for Java”API 为 Android 编写一个 UPnP 控制点应用程序。为了测试 API,我实现了一个非常简单的应用程序。在此应
我是一名优秀的程序员,十分优秀!