Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/473.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 通过拖动角点来调整d3 svg形状的大小时,如何保持纵横比?_Javascript_Svg_D3.js - Fatal编程技术网

Javascript 通过拖动角点来调整d3 svg形状的大小时,如何保持纵横比?

Javascript 通过拖动角点来调整d3 svg形状的大小时,如何保持纵横比?,javascript,svg,d3.js,Javascript,Svg,D3.js,我正在开发一个svg形状工作区,您可以在其中拖动、旋转和调整不同形状的大小。我附加了一个最小的复制品 我希望在拖动调整大小时保持形状的纵横比。到目前为止,我的实现在侧面正确地实现了这一点,但在拐角处却没有。我已经尝试了一些错误的开始,所以我想我最好问问你们: 如何在通过拖动角点调整大小手柄调整形状大小时保持形状的纵横比 我这样做的目的是,当你调整大小时,相反的调整手柄固定在适当的位置,因为我发现这是最自然、最不令人惊讶的。因此,拖动W时,E调整大小控制柄固定在位,拖动SE时,NW固定在位。即使形

我正在开发一个svg形状工作区,您可以在其中拖动、旋转和调整不同形状的大小。我附加了一个最小的复制品

我希望在拖动调整大小时保持形状的纵横比。到目前为止,我的实现在侧面正确地实现了这一点,但在拐角处却没有。我已经尝试了一些错误的开始,所以我想我最好问问你们:

如何在通过拖动角点调整大小手柄调整形状大小时保持形状的纵横比

我这样做的目的是,当你调整大小时,相反的调整手柄固定在适当的位置,因为我发现这是最自然、最不令人惊讶的。因此,拖动W时,E调整大小控制柄固定在位,拖动SE时,NW固定在位。即使形状本身的纵横比在调整大小时被锁定,也需要这样做

如果您在figma.com上调整大小时按住shift键,则其工作正常:

设x=300; 设y=100; 宽度=180; 设高度=120; 设旋转角度=0; 常量旋转\手柄\半径=10; 常量旋转\u手柄\u边距=12; 常量svg=d3。选择“正文”。追加“svg” .attr'width',600 .attr'height',400 .样式“背景色”、“浅灰色”; const shapeGroup=svg.append'g' 呼叫 d3.阻力 .on'drag',=>onDrag ; const rectangle=shapeGroup.append'rect' .attr'fill'、'rebeccapulve'; 常量旋转组=形状组 .附加“g” .attr'transform','translate0,-2' 呼叫 d3.阻力 .在“拖动”时,=>在旋转时 ; 常量设备旋转线=旋转组 .附加“行” .样式“轮廓”,“1px实心深蓝色”; 常量设备旋转圆=旋转组 .附加“圆圈” .style'fill','darkblue' .style'cursor','grab'; 常量设备旋转角度标签=形状组 .append'text' .attr'text-anchor','middle' .style'fill','darkblue' .attr'alignment-baseline'、'central'; const resizeGroup=shapeGroup.append'g'; 常量大小句柄=[ [NW',N',NE'], ['W',未定义,'E'], ['SW','S','SE'] ].mapresizeHandleRow=>{ return resizeHandleRow.maphandle=>{ 如果!处理{ 返回未定义; } 常量大小游标={ “NW”:“nwse调整大小”, 'N':'ns resize', 'NE':'nesw resize', “W”:“ew resize”, “E”:“ew resize”, 'SW':'nesw resize', 'S':'ns resize', “SE”:“nwse调整大小” } const resizeHandle=resizeGroup .append'rect' .attr'width',8*2 .attr'height',8*2 .attr'x',-8 .attr'y',-8 .attr'cursor',resizeCursors[句柄] .attr'填充','紫红色' 呼叫 d3.阻力 .on'drag',=>onResizehandle ; 返回resizeHandle; }; }; 旋转函数{ 两点之间的函数角度半径点1,点2{ 如果点1[0]==2[0]&&1[1]==2[1]{ 返回Math.PI/2; } 返回Math.atan2point2[1]-point1[1],point2[0]-point1[0]; } 函数辐射度{ 返回弧度/Math.PI/180; } 函数规格化{ 返回Math.roundangle+360%360; } 常量rotateHandleVerticalPos=高度/2+旋转\u手柄\u边距; 设deltaAngleRadians=两点之间的角度半径[0,0],[d3.event.x,d3.event.y]; deltaAngleRadians=deltaAngleRadians-两个点之间的角度半径[0,0],[0,-旋转和杠杆半径]; 常数三角角度数=弧度度数三角角弧度; rotationAngle=规格化AngleRotationAngle+三角洲角度度; 渲染形状; } 函数onResizehandle{ 常量事件=d3.0事件; const height overwidth=高度/宽度; const widthOverHeight=宽度/高度; 常数x=x; 常数=y; 常数宽度=宽度; 常数高度=高度; 开关手柄{ 案例“N”: 高度+=事件y*-1; y+=事件y/2; 宽度+=事件y*宽度超高*-1; 打破 案例“NE”: 宽度+=event.dx; 高度+=事件y*-1; x+=event.dx/2; y+=事件y/2; 打破 案例“E”: 宽度+=event.dx; x+=event.dx/2; 高度+=event.dx*高度过宽; 打破 案例“SE”: 宽度+=event.dx; 高度+=event.dy; x+=event.dx/2; y+=event.dy/2; 打破 案例S: 高度+=event.dy; 宽度+=event.dy*宽度超高; y+=event.dy/2; 打破 案例“SW”: 宽度+=事件x*-1; 高度+=event.dy ; x+=事件x/2; y+=event.dy/2; 打破 案例“W”: 宽度+=事件x*-1; x+=事件x/2; 高度+=事件x*高度超过宽度*-1; 打破 案例“NW”: 宽度+=事件x*-1; 高度+=事件y*-1; x+=事件x/2; y+=事件y/2; 打破 } //强制最小宽度和高度 如果宽度只需夹紧dx/dy对以适应原始纵横比。以SE句柄为例:

案例SE:{ const shiftKey=event.sourceEvent.shiftKey; 设{dx,dy}=event; 如果移位键{ 如果dx/dy>宽度超高{ //dx超出原始比率 dx=宽度超高*dy; }否则,如果dy/dx>高度超过宽度{ //dy超出原始比率 dy=dx*高过宽; } } 宽度+=dx; 高度+=dy; x+=dx/2; y+=dy/2; 打破 }
从@hackape的答案扩展而来。按下shift键时,无需检查任何状况。相反,根据控制柄值直接更改必要的宽度、高度、x、y值。SE的句柄在示例中

设x=300; 设y=100; 宽度=180; 设高度=120; 设旋转角度=0; 常量旋转\手柄\半径=10; 常量旋转\u手柄\u边距=12; 常量svg=d3。选择“正文”。追加“svg” .attr'width',600 .attr'height',400 .样式“背景色”、“浅灰色”; const shapeGroup=svg.append'g' 呼叫 d3.阻力 .on'drag',=>onDrag ; const rectangle=shapeGroup.append'rect' .attr'fill'、'rebeccapulve'; 常量旋转组=形状组 .附加“g” .attr'transform','translate0,-2' 呼叫 d3.阻力 .在“拖动”时,=>在旋转时 ; 常量设备旋转线=旋转组 .附加“行” .样式“轮廓”,“1px实心深蓝色”; 常量设备旋转圆=旋转组 .附加“圆圈” .style'fill','darkblue' .style'cursor','grab'; 常量设备旋转角度标签=形状组 .append'text' .attr'text-anchor','middle' .style'fill','darkblue' .attr'alignment-baseline'、'central'; const resizeGroup=shapeGroup.append'g'; 常量大小句柄=[ [NW',N',NE'], ['W',未定义,'E'], ['SW','S','SE'] ].mapresizeHandleRow=>{ return resizeHandleRow.maphandle=>{ 如果!处理{ 返回未定义; } 常量大小游标={ “NW”:“nwse调整大小”, 'N':'ns resize', 'NE':'nesw resize', “W”:“ew resize”, “E”:“ew resize”, 'SW':'nesw resize', 'S':'ns resize', “SE”:“nwse调整大小” } const resizeHandle=resizeGroup .append'rect' .attr'width',8*2 .attr'height',8*2 .attr'x',-8 .attr'y',-8 .attr'cursor',resizeCursors[句柄] .attr'填充','紫红色' 呼叫 d3.阻力 .on'drag',=>onResizehandle ; 返回resizeHandle; }; }; 旋转函数{ 两点之间的函数角度半径点1,点2{ 如果点1[0]==2[0]&&1[1]==2[1]{ 返回Math.PI/2; } 返回Math.atan2point2[1]-point1[1],point2[0]-point1[0]; } 函数辐射度{ 返回弧度/Math.PI/180; } 函数规格化{ 返回Math.roundangle+360%360; } 常量rotateHandleVerticalPos=高度/2+旋转\u手柄\u边距; 设deltaAngleRadians=两点之间的角度半径[0,0],[d3.event.x,d3.event.y]; deltaAngleRadians=deltaAngleRadians-两个点之间的角度半径[0,0],[0,-旋转和杠杆半径]; 常数三角角度数=弧度度数三角角弧度; rotationAngle=规格化AngleRotationAngle+三角洲角度度; 渲染形状; } 函数onResizehandle{ 常量事件=d3.0事件; const height overwidth=高度/宽度; const widthOverHeight=宽度/高度; 常数x=x; 常数=y; 常数宽度=宽度; 常数高度=高度; const shiftKey=event.sourceEvent.shiftKey; 设{dx,dy}=event; 开关手柄{ 案例“N”: 高度+=事件y*-1; y+=事件y/2; 宽度+=事件y*宽度超高*-1; 打破 案例“NE”: 宽度+=event.dx; 高度+=事件y*-1; x+=event.dx/2; y+=事件y/2; 打破 案例“E”: 宽度+=event.dx; x+=event.dx/2; 高度+=event.dx*高度过宽; 打破 案例“SE”: 如果移位键{ dx=宽度超高*dy; dy=dx*高过宽; } 宽度+=dx; 高度+=dy; x+=dx/2; y+=dy/2; 打破 案例S: 高度+=event.dy; 宽度+=event.dy*宽度超高; y+=event.dy/2; 打破 案例“SW”: 宽度+=事件x*-1; 高度+=event.dy; x+=事件x/2; y+=event.dy/2; 打破 案例“W”: 宽度+=事件x*-1; x+=事件x/2; 高度+=事件x*高度超过宽度*-1; 打破 案例“NW”: 宽度+=事件x*-1; 高度+=事件y*-1; x+=事件x/2; y+=事件y/2; 打破 } //强制最小宽度和高度
如果宽度,您是否尝试过使用viewBox属性设置宽度和高度?viewBox仅用于svg dom元素本身,对吗?也许我的问题不清楚:我想在svg元素工作区内保持形状的纵横比。我以前见过它的实现。例如diagrams.net和Libreoffice Draw。在这两种情况下,在调整大小时按住shift按钮以锁定纵横比。但是我看到diagrams.net在拖动一个角时只缩放一个轴,这有点作弊。不过,这是一个非常简单的解决方法。我很想看到一个像Libreoffice Draw那样的解决方案。很遗憾,我在figma.com上添加了一个gif,它可以正常工作。我尝试将其粘贴到示例中,并在按住shift键的同时单击并拖动SE控制柄,但它没有为我锁定纵横比。很抱歉,这不会像问题描述中的示例那样在x和y方向上拖动。