马黑黑 发表于 2023-11-1 13:16

svg : pattern 标签(一)

<style>
.ma p, .ma pre, .ma svg { margin: 8px 0; }
.rred { color: red; }
.ma > pre { padding: 16px; background: #efefef; font: normal 16px monospace; white-space: pre-wrap; word-wrap: break-word; tab-size: 4; line-height:1.5em; }
.ma > svg { border: 1px solid gray; }
</style>

<div class="ma">
        <p>pattern是一种填充类型的svg标签,它包裹在 &lt;defs&gt;...&lt;/defs&gt; 标签之内,其内可以组织包括path路径在内的所有svg图形元素,并将这些图形以 fill 或 stroke 方式填充使用对象或给该对象描边。代码结构和运行效果举例如下:</p>
        <pre>&lt;svg width="200" height="200" style="border: 1px solid;"&gt;
        &lt;defs&gt;
                &lt;pattern id="tri" x="0" y="0" width="20%" height="20%"&gt;
                        &lt;polygon points="20,5 5,30 40,20 20,5" fill="steelblue" /&gt;
                &lt;/pattern&gt;
        &lt;/defs&gt;

        &lt;circle cx="100" cy="100" r="100" fill="url(#tri)" /&gt;
&lt;/svg&gt;</pre>

        <svg width="200" height="200" style="border: 1px solid;">
                <defs>
                        <pattern id="tri" x="0" y="0" width="20%" height="20%">
                                <polygon points="20,5 5,30 40,20 20,5" fill="steelblue" />
                        </pattern>
                </defs>
                <circle cx="100" cy="100" r="100" fill="url(#tri)" />
        </svg>

        <p>上面的代码,我们首先创建一个 pattern 元素,它需要放在 &lt;defs&gt;...&lt;/defs&gt; 标签的省略号处。pattern 标签拥有 id 标识符,x 和 y 属性定义 pattern 取其内图形的XY坐标位置,width 和 height 属性定义取图形的宽高,注意,<span class="rred">默认情况下 width 和 height 属性使用百分比做单位</span>,不然无效。然后我们使用 polygon 多边形标签绘制一个不规则三角形(如果愿意,我们可以绘制组合式图形)。这样,pattern 图案就准备就绪,可以拿去填充其他图形或给其他图形描边了。</p>

        <p>pattern的本意是图案,pattern 标签就是设置一个或一组图案,然后以平铺方式拿去给其他图形做图案,这和贴瓷砖、贴窗花差不多是一个道理。从上面效果看,我们应可以感受到 pattern 的宽高和贴图对象(circle)的宽高尺寸的关系:pattern 定义的图案宽高都是20%,这意味着在贴图对象的纵横两个方向都能贴 5 个pattern内定义的图案;本例我们使用的贴图对象是一个圆,有一些三角形被剪切在圆的外面了,定可以数一数横向和纵向直径的三角形个数以证实上面的说法。</p>

        <p>作为首次接触,pattern 标签先说这些,后续还有一些问题需要探讨,敬请期待。最后给出一个有趣的pattern动画,它是在上面示例的基础上略作改动完成的:</p>
</div>

<svg width="200" height="200">
        <defs>
                <pattern id="mypatt" x="0" y="0" width="10%" height="10%" viewBox="0 0 40 40">
                        <polygon points="20,5 5,25 30,20 20,5" fill="steelblue" />
                </pattern>
        </defs>
        <circle cx="100" cy="100" r="100" fill="url(#mypatt)" />
</svg>
<br><br>
<p style="margin-left: 60px;"><input type="button" id="btnplay" value="开始动画" /></p>

<script>

let step = 0.01, base = 10, playId = false, aniId = null;

let whChg = () => {
        base += step;
        if(base > 20 || base < 4) step = -step;
        mypatt.setAttribute('width', base + '%');
        mypatt.setAttribute('height', base + '%');
        aniId = requestAnimationFrame(whChg);
};

btnplay.onclick = () => {
        playId === false ? aniId = (requestAnimationFrame(whChg), playId = true) : (cancelAnimationFrame(aniId), playId = false);
        btnplay.value = playId ? '结束动画' : '开始动画';
};

</script>

红影 发表于 2023-11-1 14:14

width 和 height 属性的取值是有限制的吧,对于上面例子,我取到100%就没了,取50%和70%得到的也完全不同。
这个应该是跟polygon配套着用的吧。{:4_203:}

红影 发表于 2023-11-1 14:18

觉得这个很好看也很好玩,但触摸不到它的底线,我用polygon points="50,150 100,50 150,150 50,150"画个正三角,用宽度20%时就看不到了{:4_173:}

马黑黑 发表于 2023-11-1 19:29

红影 发表于 2023-11-1 14:14
width 和 height 属性的取值是有限制的吧,对于上面例子,我取到100%就没了,取50%和70%得到的也完全不同。 ...
我为什么花那么多的精力介绍 viewBox ?这是svg的精髓。当然,在 pattern 还没有使用 viewBox 之前,我们要弄清楚的是pattern的宽高百分比、填充目标的尺寸和pattern内部图案的关系。

pattern内部的图案,默认时,它的尺寸很重要。比方说,单个图案,设置为宽高40*40,则,pattern的宽、高百分比百分比和填充的目标图形的宽、高尺寸的比例,要能保证 40*40 的图案能正常显示,否则就会出现被剪切的区域,例如,填充的目标图形尺寸是 200*200,则 20% 是合适的,40%也是合适的。

但是这一切问题,pattern 引入 viewBox 之后,都将不复存在,因为 viewBox 能让 pattern 内的图案伸缩。

马黑黑 发表于 2023-11-1 19:31

红影 发表于 2023-11-1 14:18
觉得这个很好看也很好玩,但触摸不到它的底线,我用polygon points="50,150 100,50 150,150 50,150"画个正 ...

你可以单独画一个 polygon 看看效果,它很大的

红影 发表于 2023-11-1 22:40

马黑黑 发表于 2023-11-1 19:29
我为什么花那么多的精力介绍 viewBox ?这是svg的精髓。当然,在 pattern 还没有使用 viewBox 之前,我们 ...

哦,在没使用 viewBox 时,这些宽高比有限制,使用了,这些限制就能呗解决了吧。知道了{:4_187:}

红影 发表于 2023-11-1 22:42

马黑黑 发表于 2023-11-1 19:31
你可以单独画一个 polygon 看看效果,它很大的

是的,这个特地弄个大的,感受一下比较大的时候能否被填充。

马黑黑 发表于 2023-11-2 07:28

红影 发表于 2023-11-1 22:42
是的,这个特地弄个大的,感受一下比较大的时候能否被填充。

pattern 的 width 和 height 规定平铺的个体大小,原始设计的边界太大了就会被剪裁,所以需要引入 viewBox 属性,令其可以伸缩时保持形状不变或不变形

红影 发表于 2023-11-2 10:18

马黑黑 发表于 2023-11-2 07:28
pattern 的 width 和 height 规定平铺的个体大小,原始设计的边界太大了就会被剪裁,所以需要引入 viewBo ...

嗯,看到今天的那个介绍,知道了,引入 viewBox 属性的设置也要恰当。

马黑黑 发表于 2023-11-2 11:57

红影 发表于 2023-11-2 10:18
嗯,看到今天的那个介绍,知道了,引入 viewBox 属性的设置也要恰当。

一切属性、参数的设置,都是根据需要来

红影 发表于 2023-11-2 14:07

马黑黑 发表于 2023-11-2 11:57
一切属性、参数的设置,都是根据需要来

设置的时候必须符合实际,否则可能看不到东西。

马黑黑 发表于 2023-11-2 19:59

红影 发表于 2023-11-2 14:07
设置的时候必须符合实际,否则可能看不到东西。

设计师不会在实现自己的设计时让一切都看不到

红影 发表于 2023-11-2 21:38

马黑黑 发表于 2023-11-2 19:59
设计师不会在实现自己的设计时让一切都看不到

设计师不会,只是在自己设置不合适时会。

马黑黑 发表于 2023-11-2 21:47

红影 发表于 2023-11-2 21:38
设计师不会,只是在自己设置不合适时会。

不合适就改改

红影 发表于 2023-11-2 22:22

马黑黑 发表于 2023-11-2 21:47
不合适就改改

是的,这个是必须的。

马黑黑 发表于 2023-11-2 23:12

红影 发表于 2023-11-2 22:22
是的,这个是必须的。

红影 发表于 2023-11-3 12:53

马黑黑 发表于 2023-11-2 23:12


等遇到不合适时再说{:4_173:}

马黑黑 发表于 2023-11-3 21:36

红影 发表于 2023-11-3 12:53
等遇到不合适时再说

也好

红影 发表于 2023-11-3 23:04

马黑黑 发表于 2023-11-3 21:36
也好

还需要发现不合适才行,发现不了也改不了{:4_173:}

马黑黑 发表于 2023-11-3 23:20

红影 发表于 2023-11-3 23:04
还需要发现不合适才行,发现不了也改不了

那就别改
页: [1] 2 3 4
查看完整版本: svg : pattern 标签(一)