Eri*_*yer 2 javascript svg matrix
我在这里可以看到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);
}
Run Code Online (Sandbox Code Playgroud)
如果需要更多,请在链接页面上查看源代码;所有JS都在页面顶部。除了仅包含可视化的所有HSL值和颜色名称的文件之外,没有任何外部内容。
我的建议:不用担心事件的movementX/ Y属性。只需担心鼠标在哪里开始以及现在在哪里。
(这还有一个额外的好处,即使您错过了一些事件,您也可以获得相同的结果:可能是因为鼠标移出了窗口,或者可能是因为您想对事件进行分组,因此每个动画帧只运行一次代码。)
对于鼠标的起始位置,您可以在mousedown事件上对其进行测量。将其转换为在SVG坐标的位置,使用您正在使用,该方法.getScreenCTM().inverse()和.matrixTransform()。进行此转换后,您无需担心此点在屏幕上的什么位置。您只关心它在图片中的位置。这就是图片中您始终要移动到鼠标下方的要点。
在mousemove事件上,您使用相同的转换方法来找出鼠标当前在当前SVG坐标系内的位置。然后,您可以算出距离鼠标下方想要的点(同样,在SVG坐标中)有多远。那就是您用来变换图形的数量。我遵循了您的示例,并通过移动x和的y部分来进行转换viewBox:
function move(e) {
var targetPoint = svgCoords(event, svg);
shiftViewBox(anchorPoint.x - targetPoint.x,
anchorPoint.y - targetPoint.y);
}
Run Code Online (Sandbox Code Playgroud)
您也可以在SVG中transform的组(<g>元素)上使用来移动图形。只要确保使用相同的组元素进行getScreenCTM()从clientX/ Y事件坐标转换的调用即可。
拖动演示的完整演示。我已经跳过了所有绘图代码和缩放效果。但是缩放应该仍然有效,因为您要保存在全局值中的唯一位置已经转换为SVG坐标。
function move(e) {
var targetPoint = svgCoords(event, svg);
shiftViewBox(anchorPoint.x - targetPoint.x,
anchorPoint.y - targetPoint.y);
}
Run Code Online (Sandbox Code Playgroud)
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);
}Run Code Online (Sandbox Code Playgroud)
body {
display: grid;
margin: 0;
min-height: 100vh;
}
svg {
margin: auto;
width: 70vmin;
height: 70vmin;
border: thin solid gray;
cursor: move;
}Run Code Online (Sandbox Code Playgroud)