SVG 背景图像中的旋转条纹
Rotating stripes in SVG background image
下面的 javascript 代码应该根据用户输入生成背景图像。用户应该能够改变条纹的角度和其他东西,比如深度、颜色……
问题是当角度改变时,我无法让图案无缝重复。我认为这是因为模式总是从同一点开始。有什么方法可以控制吗?
var atts = {
size: [30, 30],
depth: 50,
rotDegrees: 45
};
function refresh() {
var code = $('#tpl').html().replace(/{\:([^{}]+)}/g, function(match, key) {
return atts[key] || match;
});
code = '<svg xmlns="http://www.w3.org/2000/svg" width="' + atts.size[0] + '" height="' + atts.size[1] + '">' + code + '</svg>';
$('#preview').css('background-image', 'url("data:image/svg+xml;base64,' + window.btoa(code) + '")');
};
refresh();
$('input').on('input', function(e) {
atts[this.name] = this.value;
refresh();
});
#preview {
width: 600px;
height: 600px;
display: block;
background: transparent none repeat center center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input name="rotDegrees" type="range" min="0" max="360" step="1" value="0" />
<input name="depth" type="range" min="1" max="100" step="1" value="60" />
<div id="preview"></div>
<script id="tpl" type="text/template">
<defs>
<pattern id="stripe-pattern" width="100%" height="100%" patternUnits="userSpaceOnUse" patternTransform="rotate({:rotDegrees})">
<rect width="{:depth}%" height="100%" transform="translate(0,0)" fill="#fff" />
</pattern>
<mask id="stripe-mask">
<rect x="0" y="0" width="100%" height="100%" fill="url(#stripe-pattern)" />
</mask>
</defs>
<rect mask="url(#stripe-mask)" x="0" y="0" width="100%" height="100%" />
</script>
如果您希望条纹之间的距离固定 - 例如此处显示的 30 像素,那么您将无法保持固定大小的图案 "box"。它需要改变宽度,以便条纹有空间环绕并在 30 像素标记处与自身相遇。
对于 10 度的角度和 30 的条纹间距,盒子的尺寸需要为:
width = 30 / tan(10)
= 170px
对于 1 度,它需要为 1718.7 像素。
另一方面,如果您想保持固定宽度的图案(例如 30 像素),那么您需要有多个条纹 <rect>
才能完成图案正方形的额外交叉完成一个条纹周期。
对于10度的例子,我们已经确定了循环的"cycle length"(周期)为170px,所以你需要六个矩形。
170/30 = 5.666
但是,当然,如果您使用这种方法,对于某些角度和条纹宽度,您将失去条纹效果,因为您最终会在图案中看到纯色条纹块。
下面的 javascript 代码应该根据用户输入生成背景图像。用户应该能够改变条纹的角度和其他东西,比如深度、颜色……
问题是当角度改变时,我无法让图案无缝重复。我认为这是因为模式总是从同一点开始。有什么方法可以控制吗?
var atts = {
size: [30, 30],
depth: 50,
rotDegrees: 45
};
function refresh() {
var code = $('#tpl').html().replace(/{\:([^{}]+)}/g, function(match, key) {
return atts[key] || match;
});
code = '<svg xmlns="http://www.w3.org/2000/svg" width="' + atts.size[0] + '" height="' + atts.size[1] + '">' + code + '</svg>';
$('#preview').css('background-image', 'url("data:image/svg+xml;base64,' + window.btoa(code) + '")');
};
refresh();
$('input').on('input', function(e) {
atts[this.name] = this.value;
refresh();
});
#preview {
width: 600px;
height: 600px;
display: block;
background: transparent none repeat center center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input name="rotDegrees" type="range" min="0" max="360" step="1" value="0" />
<input name="depth" type="range" min="1" max="100" step="1" value="60" />
<div id="preview"></div>
<script id="tpl" type="text/template">
<defs>
<pattern id="stripe-pattern" width="100%" height="100%" patternUnits="userSpaceOnUse" patternTransform="rotate({:rotDegrees})">
<rect width="{:depth}%" height="100%" transform="translate(0,0)" fill="#fff" />
</pattern>
<mask id="stripe-mask">
<rect x="0" y="0" width="100%" height="100%" fill="url(#stripe-pattern)" />
</mask>
</defs>
<rect mask="url(#stripe-mask)" x="0" y="0" width="100%" height="100%" />
</script>
如果您希望条纹之间的距离固定 - 例如此处显示的 30 像素,那么您将无法保持固定大小的图案 "box"。它需要改变宽度,以便条纹有空间环绕并在 30 像素标记处与自身相遇。
对于 10 度的角度和 30 的条纹间距,盒子的尺寸需要为:
width = 30 / tan(10)
= 170px
对于 1 度,它需要为 1718.7 像素。
另一方面,如果您想保持固定宽度的图案(例如 30 像素),那么您需要有多个条纹 <rect>
才能完成图案正方形的额外交叉完成一个条纹周期。
对于10度的例子,我们已经确定了循环的"cycle length"(周期)为170px,所以你需要六个矩形。
170/30 = 5.666
但是,当然,如果您使用这种方法,对于某些角度和条纹宽度,您将失去条纹效果,因为您最终会在图案中看到纯色条纹块。