为了账号安全,请及时绑定邮箱和手机立即绑定

如何将鼠标移动距离转换为SVG坐标空间?

如何将鼠标移动距离转换为SVG坐标空间?

至尊宝的传说 2021-04-13 17:14:10
我在这里可以看到HSL空间中CSS4颜色关键字的分布的SVG可视化:https : //meyerweb.com/eric/css/colors/hsl-dist.html我最近添加了通过鼠标滚轮缩放和通过鼠标敲击和拖动来平移的功能。我能够从屏幕空间中的点转换为SVG使用的坐标空间matrixTransform,.getScreenCTM()以及.inverse()由于示例代码我在网上找到,但我怎么拖动转换过程中鼠标移动?现在,我只是将viewBox坐标从移X和Y值event,这意味着在放大时图像拖动比鼠标移动快。举例来说,假设我放大了图像并拖动以平移,并且鼠标向左或向下拉动了一下。 event.movementX返回-37和event.movementY返回6。如何确定SVG坐标等于多少,以便viewBox正确移动坐标?(注意:我知道有一些用于此类事情的库,但是我故意编写香草JS代码以了解有关SVG和JS的更多信息。因此,请不要发布“大声笑,请仅使用库X ”,就这样吧。谢谢!)编辑添加:我被要求张贴代码。发布整个JS似乎太长了,但这是在mousemove事件上触发的函数:function dragger(event) {    var target = document.getElementById('color-wheel');    var coords = parseViewBox(target);    coords.x -= event.movementX;    coords.y -= event.movementY;    changeViewBox(target,coords);}如果需要更多,请在链接页面上查看源代码;所有JS都在页面顶部。除了仅包含可视化的所有HSL值和颜色名称的文件之外,没有任何外部内容。
查看完整描述

3 回答

?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

我的建议:不用担心事件的movementX/Y属性。只需担心鼠标在哪里开始以及现在在哪里。


(这还有一个额外的好处,即使您错过了一些事件,您也可以获得相同的结果:可能是因为鼠标移出了窗口,或者可能是因为您想对事件进行分组,所以每个动画帧只运行一次代码。)


对于鼠标的起始位置,您可以在mousedown事件上对其进行测量。使用.getScreenCTM().inverse()和所使用的方法,将其转换为SVG坐标中的位置.matrixTransform()。进行此转换后,您无需担心此点在屏幕上的什么位置。您只关心它在图片中的位置。这就是图片中您始终要移动到鼠标下方的要点。


在mousemove事件上,您使用相同的转换方法来找出鼠标当前在当前SVG坐标系内的位置。然后,您可以算出距离鼠标下方想要的点(同样,在SVG坐标中)有多远。那就是您用来变换图形的数量。我遵循了您的示例,并通过移动x和的y一部分来进行转换viewBox:


function move(e) {

  var targetPoint = svgCoords(event, svg);

  shiftViewBox(anchorPoint.x - targetPoint.x,

               anchorPoint.y - targetPoint.y);

}

您也可以在SVG中transform的组(<g>元素)上使用来移动图形。只要确保将相同的组元素用于getScreenCTM()从clientX/Y事件坐标转换的调用即可。


拖动演示的完整演示。我已经跳过了所有绘图代码和缩放效果。但是缩放应该仍然有效,因为您要保存在全局值中的唯一位置已经转换为SVG坐标。


var svg = document.querySelector("svg");

var anchorPoint;


function shiftViewBox(deltaX, deltaY) {

  svg.viewBox.baseVal.x += deltaX;

  svg.viewBox.baseVal.y += deltaY;

}


function svgCoords(event,elem) {

  var ctm = elem.getScreenCTM();

  var pt = svg.createSVGPoint();

    // Note: rest of method could work with another element,

    // if you don't want to listen to drags on the entire svg.

    // But createSVGPoint only exists on <svg> elements.

  pt.x = event.clientX;

  pt.y = event.clientY;

  return pt.matrixTransform(ctm.inverse());

}


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

  anchorPoint = svgCoords(event, svg);

  window.addEventListener("mousemove", move);

  window.addEventListener("mouseup", cancelMove);

});


function cancelMove(e) {

  window.removeEventListener("mousemove", move);

  window.removeEventListener("mouseup", cancelMove);

  anchorPoint = undefined;

}


function move(e) {

  var targetPoint = svgCoords(event, svg);

  shiftViewBox(anchorPoint.x - targetPoint.x,

               anchorPoint.y - targetPoint.y);

}

body {

  display: grid;

  margin: 0;

  min-height: 100vh;

}


svg {

  margin: auto;

  width: 70vmin;

  height: 70vmin;

  border: thin solid gray;

  cursor: move;

}

<svg viewBox="-40 -40 80 80">

  <polygon fill="skyBlue"

           points="0 -40, 40 0, 0 40 -40 0" />

</svg>


查看完整回答
反对 回复 2021-04-22
  • 3 回答
  • 0 关注
  • 222 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信