如何在SVG中创建带两条可控对称旋转线条的网格图案?
问题描述
我希望创建一个可控制两条线条夹角的网格图案,当用户拖动滑块时,两条线条同时对称旋转,实现如下动画效果:
目前我通过叠加两个填充不同线条pattern的矩形来模拟网格,使用两个滑块分别控制两条直线。我的问题如下:
- 如何使用一个滑块实现如动画所示的两条线条对称旋转控制?
- 是否可以仅使用一个
<pattern>,而非两个,从而只需单个矩形而非叠加两个矩形来实现该效果?
现有代码如下:
var controlRotate = document.getElementById("controlRotate"); var controlRotate1 = document.getElementById("controlRotate1") var pattern0 = document.getElementById("pattern0") var pattern1 = document.getElementById("pattern1") var path0 = document.getElementById("path0") var path1 = document.getElementById("path1") controlRotate.oninput = function(){ pattern0.setAttribute("patternTransform", "rotate("+controlRotate.value+")") } controlRotate1.oninput = function(){ pattern1.setAttribute("patternTransform", "rotate("+controlRotate1.value+")") }
<script src="https://d3js.org/d3.v4.min.js"></script> <svg> <defs> <pattern id="pattern0" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="rotate(45)" > <path id = "path0" d="m -100 10 l 200 0" strokeWidth = "1" stroke = "black"></path> </pattern> <pattern id="pattern1" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="rotate(135)" > <path id = "path1" d="m -100 10 l 200 0" strokeWidth = "1" stroke = "black"></path> </pattern> </defs> <rect x="0" y="0" width="100" height="100" style="stroke: #000000; fill: url(#pattern0);" /> <rect x="0" y="0" width="100" height="100" style="stroke: #000000; fill: url(#pattern1);" /> </svg> <!-- rotation controller--> <div style='margin-bottom:25px'> <p style=font-size:15px>Rotation</p> <input type="range" min="0" max="360" value="0" class="slider" id="controlRotate" style='margin-top: -10px;'> </div> <div style='margin-bottom:25px'> <p style=font-size:15px>Rotation1</p> <input type="range" min="0" max="360" value="0" class="slider" id="controlRotate1" style='margin-top: -10px;'> </div>
解决方案
1. 单个滑块实现对称旋转控制
核心是让两条线保持固定90°夹角,同步跟随滑块值旋转。修改后的代码如下:
var controlRotate = document.getElementById("controlRotate"); var pattern0 = document.getElementById("pattern0") var pattern1 = document.getElementById("pattern1") controlRotate.oninput = function(){ var rotateVal = parseInt(this.value); // 两条线始终保持90°夹角,同步旋转 pattern0.setAttribute("patternTransform", `rotate(${rotateVal})`); pattern1.setAttribute("patternTransform", `rotate(${rotateVal + 90})`); }
<!-- 仅保留一个控制滑块 --> <div style='margin-bottom:25px'> <p style=font-size:15px>旋转控制</p> <input type="range" min="0" max="360" value="45" class="slider" id="controlRotate" style='margin-top: -10px;'> </div>
拖动滑块时,两个pattern会以固定90°夹角同步旋转,完全匹配动画中的对称效果。
2. 使用单个<pattern>实现网格
可以通过在单个pattern中绘制两条垂直线条,直接实现网格效果,无需叠加多个矩形。完整代码如下:
<script src="https://d3js.org/d3.v4.min.js"></script> <svg> <defs> <pattern id="gridPattern" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"> <!-- 在同一个pattern内绘制两条垂直的线条 --> <path d="m -100 10 l 200 0" strokeWidth="1" stroke="black"></path> <path d="m 10 -100 l 0 200" strokeWidth="1" stroke="black"></path> </pattern> </defs> <!-- 仅需一个矩形填充该pattern --> <rect x="0" y="0" width="100" height="100" style="stroke: #000000; fill: url(#gridPattern);" /> </svg> <div style='margin-bottom:25px'> <p style=font-size:15px>旋转控制</p> <input type="range" min="0" max="360" value="45" class="slider" id="controlRotate" style='margin-top: -10px;'> </div> <script> var controlRotate = document.getElementById("controlRotate"); var gridPattern = document.getElementById("gridPattern") controlRotate.oninput = function(){ gridPattern.setAttribute("patternTransform", `rotate(${this.value})`); } </script>
代码说明
- 在单个
<pattern>中同时绘制水平和垂直线条,天然形成垂直网格结构; - 控制整个pattern的旋转角度,拖动滑块时整个网格同步旋转,效果与动画一致;
- 仅需一个矩形和一个滑块,代码更简洁高效。
内容的提问来源于stack exchange,提问作者Hesper
相关产品推荐
相关产品推荐

