w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com zh-hans w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/css/aspect-ratios-for-grid-items.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>之前,我们讲了<a href="//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/css/aspect-ratio-boxes.html">宽高比盒子</a>,谈到一个技巧,就是运用填充来随心所欲地调整一个元素的长宽比例。<strong>这个技巧并不是经常能用到的,因为修整一个元素的高度是自找麻烦</strong>,但也不是没有这种情况出现。</p> <p>要降低这一风险,有一种方法,那就是<a href="//css-tricks.com/aspect-ratio-boxes/#article-header-id-6">伪元素(Psuedo Element)策略</a>,让伪元素顶住其上一层元素,撑起纵横比。但是如果元素里的内容将元素顶得更高,那元素也会变得更高,纵横比就完蛋了。</p> <p>这一技巧可以在CSS网格布局中,应用到网格项目上去!当然,应用的方法有几种,都值得我们思考。</p> <h2>记住,网格区域和占据区域的元素并不一定大小一致</h2> <p><a href="//css-tricks.com/grid-areas-element-occupies-arent-necessarily-size/">这一点我们刚讲过</a>。 那篇文章一开始是想写成这篇文章的一部分的,不过后来感觉这个概念还是挺重要的,应该分开写。</p> <p>知道了这一点,就引申出两个问题:是需要网格区域本身有个纵横比,然后里面的元素跟着拉伸?还是不管元素所在的网格区域如何,仅元素需要纵横比?</p> <h2>只是内部的元素需要设纵横比。</h2> <p>好,这个可能比较容易一些。 只要保证元素的宽度和网格区域的宽度<code>100%</code>相同,然后加上伪元素来处理拉伸高度的纵横比。</p> <pre><code>&lt;div class="grid"&gt; &lt;div style="--aspect-ratio: 2/1;"&gt;2/1&lt;/div&gt; &lt;div style="--aspect-ratio: 3/1;"&gt;3/1&lt;/div&gt; &lt;div style="--aspect-ratio: 1/1;"&gt;1/1&lt;/div&gt; &lt;/div&gt; .grid { display: grid; grid-template-columns: 1fr 1fr 1fr; place-items: start; } .grid &gt; * { background: orange; width: 100%; } .grid &gt; [style^='--aspect-ratio']::before { content: ""; display: inline-block; width: 1px; height: 0; padding-bottom: calc(100% / (var(--aspect-ratio))); } </code></pre> <p>结果就是<a href="http://www.xysjxj.com/quot;//codepen.io/chriscoyier/pen/POjJQG">这样</a>:</p>" <div style="margin-bottom: 20px;"><iframe id="ZvPxXj" src="//codepen.io/airen/embed/ZvPxXj?height=400&amp;theme-id=0&amp;slug-hash=ZvPxXj&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <blockquote> <p><strong>注意</strong>,应用纵横比并不一定要通过自定义属性。可以看到,这里的脏活累活都是由底部填充(<code>padding-bottom</code>)这条规则完成的,它的值也可以直接用固定值或别的什么。</p> </blockquote> <h2>跨列求宽</h2> <p>我觉得,其实大家想要的更可能是这样的效果,就是设一个<code>2:1</code>的宽高比,然后元素就能确确实实地跨两列,而不是局限在一列里。做法和上面的差不多,但要加规则来实现跨列。</p> <pre><code>[style="--aspect-ratio: 1/1;"] { grid-column: span 1; } [style="--aspect-ratio: 2/1;"] { grid-column: span 2; } [style="--aspect-ratio: 3/1;"] { grid-column: span 3; } </code></pre> <p>如果再加进一条<code>grid-auto-flow: dense;</code>规则,我们还可以让不同网格项目有不同的宽高比,它们可以整齐地<a href="http://www.xysjxj.com/quot;//codepen.io/chriscoyier/pen/xPGzWo">相互包围</a>,显得很协调。</p>" <div style="margin-bottom: 20px;"><iframe id="xPGzWo" src="//codepen.io/airen/embed/xPGzWo?height=400&amp;theme-id=0&amp;slug-hash=xPGzWo&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>到了这里,就该讲讲哪些做法会把准确的纵横比搞砸。有些文字的行高<code>line-height</code>属性可能会把方框顶得过高;要用网格间距<code>grid-gap</code>这个属性也可能会弄乱纵横比。如果纵横比例要求一定超准,可能就要多试几个固定值,碰运气了。</p> <p>如果网格本身没有固定数量的行,做跨列也会变得比较麻烦。大家做的可能是重复函数<code>repeat</code>加自动填充<code>auto-fill</code>的效果,这样最后遇到的情况可能是有几个列不相等,那它们的纵横比也好不到哪里去。这个问题也许下次我们再来深入研究一下。</p> <h2>硬来</h2> <p>网格有能力进行二维布局。真想做的话,只要强迫网格区域高和宽符合纵横比就可以了。比如,给列和行直接设定固定的值,这种做法也不是不行:</p> <pre><code>.grid { display: grid; grid-template-columns: 200px 100px 100px; grid-template-rows: 100px 200px 300px; } </code></pre> <p>我们一般不会考虑这种方法,因为都希望元素大小灵活易变,正是由于这个原因,上面的纵横比例子里用的技术都是基于百分比的。但是固定值仍然不失为另一种选择。</p> <p>看看Pen网站CodePen上<a href="http://www.xysjxj.com/quot;//codepen.io/chriscoyier/pen/NwgaVX/">宽高比盒子填充</a>这个例子,作者@Chri" Coyier。</p> <div style="margin-bottom: 20px;"><iframe id="baZvMr" src="//codepen.io/airen/embed/baZvMr?height=400&amp;theme-id=0&amp;slug-hash=baZvMr&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>这个例子强迫网格区域大小固定,然后让其中的元素拉伸填充这个区域,不过我们大可把元素的大小也固定下来。</p> <h2>实际应用的例子</h2> <p>@Ben Goshow留言说要完成这个例子,于是促成了现在这个效果:</p> <p><img src="/sites/default/files/blogs/2018/1801/aspect-ratios-for-grid-items-1.png" alt="" /></p> <p>这个问题一部分在于不但要给方框加上纵横比,还要在方框内实现对齐功能。有几种方法可以实现,但我认为最简单的方法是网格套网格。给网格元素加上<code>display: grid;</code>规则,然后利用那个内部网格的对齐功能来实现。</p> <p>看看Pen网站CodePen上<a href="http://www.xysjxj.com/quot;//codepen.io/chriscoyier/pen/gGNLJY/">CSS网格项目的宽高比和内部元素对齐</a>这个例子,作者@Chri" Coyier。</p> <div style="margin-bottom: 20px;"><iframe id="RxdMYR" src="//codepen.io/airen/embed/RxdMYR?height=400&amp;theme-id=0&amp;slug-hash=RxdMYR&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>注意这个演示网页中所有元素都明确定位,没有跨行。这种做法不是必须的,只是作为另一种布局方法的例子而已。</p> <blockquote> <p><strong>特别声明</strong>:本文转载@chaussen发布于众成翻译的《<a href="http://zcfy.cc/article/aspect-ratios-for-grid-items-css-tricks">网格项目的纵横比</a>》一文,如需转载,烦请注明原文出处:<a href="//zcfy.cc/article/aspect-ratios-for-grid-items-css-tricks">http://zcfy.cc/article/aspect-ratios-for-grid-items-css-tricks</a></p> </blockquote> </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/624.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">转载</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/68.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">CSS</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/356.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">CSS3 Grid Layout</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/355.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Grid</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/180.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Layout</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/130.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">布局</a></div></div></div> Mon, 22 Jan 2018 15:56:53 +0000 Airen 2354 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/css/display-contents-is-coming.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>没错,<code>display: contents</code>要在<a href="http://www.xysjxj.com/quot;//chromium.googlesource.com/chromium/src/+/27c0ee55811678e4896cf0a07f8c4728bd7a58f2">Blink引擎</a>和<" href="http://www.xysjxj.com/quot;//trac.webkit.org/changeset/224822/webkit">WebKit引擎</a>里成为默认样式了,可能会随着Chrome浏览器65版与Safari浏览器11.1版一起发布。<" href="http://www.xysjxj.com/quot;//developer.mozilla.org/en-US/%E7%81%AB%E7%8B%90/Releases/37">火狐浏览器从37版开始就有了这一功能</a>,现在要轮到这两个浏览器了。这样,唯一没有这个功能的就剩下Edge浏览器了,<" href="//wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/10938981-implement-the-box-generation-keywords-from-css-dis">大家一起投票提要求吧</a>!</p> <p>关于这一点,我想着重说明一下,Chromium浏览器对这一功能的支持是由<a href="http://www.xysjxj.com/quot;//twitter.com/ecbos_">Emili" Cobos</a>开的头,他2016年秋天到2017年夏天参加<a href="http://www.xysjxj.com/quot;//www.igalia.com/about-us/coding-experience">Igalia公司代码之旅(Codin" Experience)</a>实习项目时,开始着手进行这项工作。</p> <p><a href="http://www.xysjxj.com/quot;//blogs.igalia.com/mrego/2016/02/25/igalia-coding-experience-on-web-engines/">2016年初的一篇博客贴子</a>里,我谈到了Igalia公司的代码之旅(Codin" Experience)实习项目,还有我对其网站平台开发团队部分未完成工作的想法,有些人可能还记得,有些人可能已经忘了。其中一项任务就是<code>display: contents</code>样式,现在终于快完成了。</p> <h2><code>display: contents</code>样式规则是什么?</h2> <p><code>display</code>这一规则属性有了这个新的值,就能把一个元素从边界框树型结构(box tree)中移去,但内容保留。<a href="//drafts.csswg.org/css-display/#valdef-display-contents">详细要求</a>里有准确定义:</p> <blockquote> <p>元素本身不产生任何边界框,而元素的子元素与伪元素仍然生成边界框,元素文字照常显示。为了同时照顾边界框与布局,处理这个元素时,要想象这个元素不在元素树型结构里,而只有内容留下。这包括元素在元文档中的子元素与伪元素,比如<code>::before</code>和<code>::after</code>这两个伪元素,如平常一样,前者仍然在元素子元素之前生成,后者在之后生成。</p> </blockquote> <p>给一个简单的例子帮助正确理解:</p> <pre><code>&lt;div style="display: contents; background: magenta; border: solid thick black; ng: 20px; color: cyan; font: 30px/1 Monospace;"&gt; &lt;span style="background: black;"&gt;foobar&lt;/span&gt; &lt;/div&gt; </code></pre> <p><code>display: contents</code>样式规则使<code>div</code>元素不产生任何边界框,因此元素的背景、边框和填充部分都不会渲染。然而,继承的属性如颜色(<code>color</code>)和字体(<code>font</code>)却能照常影响到<code>span</code>这个子元素。</p> <p>就这个例子而言,最终结果应该看上去是这个样子的:</p> <pre><code>&lt;span style="background: black; color: cyan; font: 30px/1 Monospace;"&gt;foobar&lt;/span&gt; </code></pre> <p><img src="/sites/default/files/blogs/2018/1801/display-content-1.png" alt="" /></p> <p>上一个例子在浏览器不支持时的效果,对比实际效果与支持时的效果。</p> <p>想了解更多细节,<a href="http://www.xysjxj.com/quot;//rachelandrew.co.uk/archives/2016/01/29/vanishing-boxes-with-display-contents/">Rache" Andrew写了一篇关于这个话题的博客贴子,很不错</a>。</p> <h2>CSS网格布局与<code>display: contents</code></h2> <p>从我自己写的贴子里大家可能已经能猜到,这个规则多少与CSS网格布局(Grid Layout)有关。这个<code>display: contents</code>样式能取代<strong><a href="//drafts.csswg.org/css-grid-2/#valdef-display-subgrid">子网格(<code>subgrids</code>)</a></strong>功能,目前还没有任何浏览器支持次网格。不过,<strong><a href="http://www.xysjxj.com/quot;//blogs.igalia.com/mrego/2016/02/12/subgrids-thinking-out-loud/#use-cases">子网格(<code>subgrids</code>)有些情况还是需要用到的</a></strong>。</p>" <p>典型的例子是<a href="http://www.xysjxj.com/quot;//blogs.igalia.com/mrego/2015/02/25/grid-auto-placement-is-ready/">网格布局(Gri" Layout)的自动就位(<code>auto-placement</code>)效果</a>,下面是一个简单的表格元素,看起来是这样的:</p> <pre><code>&lt;style&gt; form { display:grid; } label { grid-column: 1; } input { grid-column: 2; } button { grid-column: span 2; } &lt;/style&gt; &lt;form&gt; &lt;label&gt;Name&lt;/label&gt;&lt;input /&gt; &lt;label&gt;Mail&lt;/label&gt;&lt;input /&gt; &lt;button&gt;Send&lt;/button&gt; &lt;/form&gt; </code></pre> <p><img src="/sites/default/files/blogs/2018/1801/grid-form-list-display-contents.svg" alt="" /></p> <p>然而这不是一个典型的HTML网页表格,因为通常我们会在表格内部使用列表,这样使用读屏软件的用户就能预先知道有多少空要填。所以HTML网页看起来更可能会是这样的:</p> <pre><code>&lt;form&gt; &lt;ul&gt; &lt;li&gt;&lt;label&gt;Name&lt;/label&gt;&lt;input /&gt;&lt;/li&gt; &lt;li&gt;&lt;label&gt;Mail&lt;/label&gt;&lt;input /&gt;&lt;/li&gt; &lt;li&gt;&lt;button&gt;Send&lt;/button&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/form&gt; </code></pre> <p>有了<code>display: contents</code>样式,就可以做出和第一个例子相同的布局,用的CSS也差不多:</p> <pre><code>ul{ display: grid; } li{ display: contents; } label{ grid-column: 1; } input{ grid-column: 2; } button { grid-column: span 2; } </code></pre> <p>现在这样,网站转用CSS网格布局(Grid Layout)时,HTML代码不用大改,也不需要舍去一些确实有用的HTML元素,如上面例子里的列表元素,真的很不错。</p> <h2>在Chromium浏览器上实这个功能</h2> <p>之前介绍部分说过,<a href="http://www.xysjxj.com/quot;//bugzilla.mozilla.org/show_bug.cgi?id=1105369">火狐三年前就已经支持<code>display" contents</code>功能了</a>,但Chromium浏览器对此却没有任何实现。CSS网格布局(Grid Layout)是由Igalia公司实现的,所以公司非常希望这个功能得到支持,因为在好几个网格布局(Grid Layout)用例中,这个功能都可以方便解决问题。</p> <p>Igalia公司代码之旅(Coding Experience)提出的计划是<a href="http://www.xysjxj.com/quot;//groups.google.com/a/chromium.org/d/msg/blink-dev/nAUxrvJeNLQ/-e1zF6YkBAAJ">在Blink引擎上实现<code>display" contents</code>样式规则</a>,并将其作为主要任务。Emilio做得很棒,大部分工作都成功完成了,发现的问题应需报告给了CSS工作组和其它浏览器团队,并为网站平台测试(web-platform-tests)仓库编写了测试,以保证不同实现方法之间的互用性。</p> <p>还有一些工作要在代码之旅(Coding Experience)结束后做好,然后才能默认开启<code>display: contents</code>规则。前Opera公司、现Google公司的<a href="http://www.xysjxj.com/quot;//twitter.com/runeLi">@Run" Lillesveen</a>在整个开发过程中都给予了帮助,并将剩下的工作做完,一星期前发布。</p> <h2>在WebKit引擎上实现这个功能</h2> <p>WebKit引擎已经对<a href="http://www.xysjxj.com/quot;//bugs.webkit.org/show_bug.cgi?id=157477"><code>display" contents</code>规则</a>有了初步支持 ,但只是在实现Shadow DOM技术时内部应用,终端用户无法接触,代码其它部分也不支持。</p> <p>我们把那部分也重新激活了,虽然没时间做完,但之后苹果公司的<a href="http://www.xysjxj.com/quot;//twitter.com/anttikoivisto">Antt" Koivisto</a>完成了。到2017年11月,这个功能已在主干开发版本上设为默认启动。</p> <h2>总结</h2> <p><a href="http://www.xysjxj.com/quot;//www.igalia.com/">Igalia公司</a>作为外部力量,致力于开放式网站平台项目,是这一领域顶尖的公司之一,所以我们有机会能在不同的开源项目中实现新的功能。这要感谢我们成员的集体参与,以及在此领域内通过几年经验积累起来的外部知识。关于<code>display" contents</code>的实现,如果没有Igalia公司的支持,特别是代码之旅(Coding Experience)的经历,这个功能是不可能在今天的Chromium浏览器和WebKit引擎上实现的。</p> <p>代码之旅(Coding Experience)取得了好的结果,我们非常高兴,我们也期望在将来能再次大获成功。</p> <p>当然,所有的功劳都应该归Emilio,他是一个了不起的工程师,在代码之旅(Coding Experience)期间做得非常出色。在这一过程中,他拥有了在Chromium项目和WebKit项目里提交的特权。赞!</p> <p>最后,感谢Antti和Rune把剩下的任务完成了,才让WebKit和Chromium用户能用到<code>display: contents</code>样式规则。</p> <blockquote> <p><strong>特别声明</strong>:本文转载@chaussen发布于众成翻译的《<a href="http://www.xysjxj.com/quot;//zcfy.cc/article/quote-display-contents-quote-is-coming-regos-everyday-life">CSS的<code>display" contents</code>样式规则即将来临</a>》一文,如需转载,烦请注明原文出处:<a href="//zcfy.cc/article/quote-display-contents-quote-is-coming-regos-everyday-life">http://zcfy.cc/article/quote-display-contents-quote-is-coming-regos-everyday-life</a></p> rel="nofollow" </blockquote> </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/624.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">转载</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/68.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">CSS</a></div></div></div> Mon, 22 Jan 2018 15:29:12 +0000 Airen 2353 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/blog/2352.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>深入挖掘 CSS Grid 布局规范,发掘一些你可能不知道的特性,并探索即将到来的特性。</p> <p>CSS Grid 布局于 2017 年 3 月 开始被浏览器所支持,在撰写本文时,大多数网站有超过百分之70的访问者有 <a href="http://www.xysjxj.com/quot;//caniuse.com/#search=CSS%20grid%20layout">CS" Grid 特性支持</a>。 这个数据还在快速增长中, 并且在 Edge 浏览器发布更新支持后继续改善。</p> <p>我希望你之前已经有时间去探索过 CSS Grid 布局的一些特性了。 这篇文章将带你探索一些你可能不知道的特性。 并且了解一下未来阶段中可能实现的规范。</p> <h2><code>minmax()</code> 函数</h2> <p>不像其他的布局方式,设置元素大小均要在该元素本身,而在 Grid 布局中,我们在元素的容器级别去设置元素的大小。 我们通过定义网格轨道(Track),创建出网格单元格(Cells),并将内容至于单元格之中。</p> <p>为了使得内容能都在超出或者小于设计预期时能够灵活的展现, Gird 给 CSS 带来了一些新的特性。 其中一个就是 <code>minmax()</code> 函数。 这个函数意味着你能够指定一个网格轨道的最小值和最大值。</p> <p>在下面的例子中,我有一个左上角放置标题右边放置图片的小板块。 我想顶行的最小值为 <code>150px</code> 高, 无论标题有多少行或其他内容所需的空间大小。</p> <p>然而, 如果内容需要占用多行或者字体更大, 我想这个容器能够增大到 <code>150px</code> 以上。 此时在这里使用 <code>minmax()</code>, 设置最小值为 <code>150px</code> 以及一个最大值为 <code>auto</code>。</p> <pre><code>.grid { display: grid; grid-template-columns: 1.2fr 1fr; grid-template-rows: minmax(150px, auto) minmax(300px,auto); } </code></pre> <p><img src="/sites/default/files/blogs/2018/1801/css-grid-layout-secrets-1.jpg" alt="minmax()函数" /></p> <p>通过设置行的最小高度, 我们在设计中创建了一个大小刚好的行,即使内容比预想更短一些。</p> <p><img src="/sites/default/files/blogs/2018/1801/css-grid-layout-secrets-2.jpg" alt="minmax()函数" /></p> <p><code>minmax()</code> 函数中设置最大值为 <code>auto</code> 意味着如果内容比预想的要多,则不会导致内容溢出。</p> <p>通过使用 <code>minmax()</code>,如果我们只是有一个标题在这个容器中,容器大小比内容所需要的空间更大。 如果我们放入了更长的标题或者附加的文字,它能自动展开空间。</p> <h2><code>auto-fill</code> 和 <code>auto-fit</code></h2> <p>Flexbox 开启了许多不需要学习媒体查询而实现响应式设计的模式。 Grid 则更进一步,允许元素在两个维度上排列的灵活设计模式: 通过设置行与列。 这种模式实用的地方就在于能够在一个容器中尽可能放入多的列, 为了达到这种效果,我们需要使用两个关键词: <code>auto-fill</code> 和 <code>auto-fit</code>。</p> <p>为了能够在容器中放下尽可能多的 <code>200px</code> 大小的列轨道,我们可以这样:</p> <pre><code>.grid1 { display: grid; grid-template-columns: repeat(auto-fill, 200px); } </code></pre> <p>为了能够使所有列都能保持灵活性但始终保持一个 <code>200px</code> 的最小值, 将上文提到的 <code>minmax()</code> 函数带入即可。 我们即可创建至少有<code>200px</code>最大 <code>1fr</code> 的列。 在放入尽可能多的 <code>200px</code> 大小的列之后, 浏览器会将所有剩余的空间均分分配给每一列。</p> <pre><code>.grid1 { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, auto)); } </code></pre> <p><img src="/sites/default/files/blogs/2018/1801/css-grid-layout-secrets-3.jpg" alt="minmax()函数" /></p> <p>上图展示了 <code>auto-fill</code> 与固定大小列组合以及 <code>auto-fill</code> 与 <code>minmax()</code> 组合创建的灵活大小列之间的区别。</p> <p>我在这里使用的 <code>auto-fill</code> 关键词; 会使得即使列中没有内容,其所需要占用的空间仍然得到保留。如果使用 <code>auto-fit</code>, 任何空的轨道都会自动收缩起来,并将剩余的空间分配给其他的轨道。</p> <h2>密集填充模式</h2> <p>当你在元素上声明 <code>display: grid</code> 时, 所有的直接子级元素都会成为网格项, 所有的网格项都会自动将其排布在网格之中。 这是由于规范中所定义的自动排列规则。</p> <p>如果你的网格项包含了其他的轨道, 这意味着将会有其他的网格项将无法填入剩余的轨道之中, 这些网格项将会在网格中新开一行。 默认的, Grid 布局将会按照源内容出现的顺序向前进行内容显示。</p> <p>然而, 如果你将 <code>grid-auto-flow</code> 的值设置为 dense, 如果网格中出现空隙,Grid 将会开始回溯源内容,并将源内容中能够填入空隙的一项抽出并填入空隙中。</p> <pre><code>.grid { display: grid; grid-auto-flow: dense; grid-template-columns: repeat(auto-fill,minmax(200px, 1fr)); } </code></pre> <p><img src="/sites/default/files/blogs/2018/1801/css-grid-layout-secrets-4.jpg" alt="minmax()函数" /></p> <p><code>auto-placement</code> 规则会使内容保持默认顺序;这可能会导致布局中出现空隙。</p> <p><img src="/sites/default/files/blogs/2018/1801/css-grid-layout-secrets-5.jpg" alt="minmax()函数" /></p> <p>使用 <code>grid-auto-flow</code> 并设置属性值为 <code>dense</code>,将会开启密集填充模式,将会回填布局中出现的空隙。</p> <p>这种行为在你的网格项中没有逻辑顺序时使用最佳,然而, 使用这个关键词会对使用 <code>tab</code> 导航的人用起来更佳困难。 所以在使用这个特性时一定要充分考虑和测试!</p> <h2>神奇的网格线和网格区域</h2> <p>当你使用网格区域模板布局时, 你只要在网格中创建一个命名的区域。 这会使用区域名结尾加上 <code>-start</code> 和 <code>-end</code> 依次地创建一组列网格线和行网格线。 在接下来的例子中, 我使用了由命名区域所创建的命名网格线去创建一个遮罩层。</p> <pre><code>.grid { display: grid; grid-template-columns: 1fr 2fr 1fr; grid-auto-rows: minmax(100px, auto); grid-template-areas: "sd1 content sd2" "sd1 footer sd2"; } .side1 { grid-area: sd1; } .side2 { grid-area: sd2; } .content { grid-area: content; } .footer { grid-area: footer; } .grid .overlay { grid-column: sd1-start / sd2-end; grid-row: content-start / footer-end; } </code></pre> <p>当你使用命名网格线时也可以犯规来用。 如果你将行和列网格线的命名以 <code>-start</code> 和 <code>-end</code> 结尾, 实际上你会创建了一个以网格线主名称所命名的命名区域。</p> <p>一个以 <code>content-start</code> 和 <code>content-end</code> 定义的行和列的区域, 将会赋予名字 <code>content</code>。 你只需使用 <code>grid-area: content</code> 即可把内容存放在该区域中。</p> <p><img src="/sites/default/files/blogs/2018/1801/css-grid-layout-secrets-6.jpg" alt="minmax()函数" /></p> <p>遮罩层使用命名区域中创建的命名网格线,置于网格区域的的顶端</p> <h2>默认对齐方式</h2> <p>当一个元素变成网格项时, 默认的行为则是将此元素拉开布满所在的网格区域中; 除非元素本身是具有一定纵横比例的。 如果元素具有纵横比例, 元素将会被对齐到行列方向的起始网格线上。 这就意味着 Grid 将不会将你的图像拉伸而丢失原有比例, 当然你也可以通过调整对齐行为去改变这个默认的行为。</p> <h2>预设机制</h2> <p>在 CSS Grid 规范中有详细的介绍了 CSS Grid 布局是如何覆盖其他布局方法的。 如果你的网格元素中有浮动的,使用 <code>display: table</code> 或 <code>display: inline-block</code> 的,规范中有介绍到会发生的行为。</p> <p>简单地来说,如果元素成为了网格元素,你会发现:</p> <ul> <li>如果元素浮动了, 或者使用了清除属性,这些属性对元素产生的影响会被限制</li> <li>如果使用了 <code>display: inline-block</code> 或其他表格属性如 <code>display: table-cell</code>, 这些属性将不再生效</li> <li>以表格属性的例子, 在没有父表格容器的情况下使用 <code>display: table-cell</code>也将不会生成匿名元素</li> <li><code>vertical-align</code> 属性将不再生效</li> </ul> <p>你可以在 <a href="//rachelandrew.co.uk/css/cheatsheets/grid-fallbacks">我的网站</a> 中找到这些覆盖行为的例子</p> <p>大多数情况下这些覆盖行为都不会有问题,你还需要去关注一下后面会变成网格项的元素的宽度。 在之前的布局方式中,我们是在元素本身控制其宽度的。</p> <p>而在 Grid 中,我们将元素置于网格项中并被其制约。这就意味着如果你使用百分比设置元素的长度,这个百分比在 Grid 布局中会转换成网格区域的的长度百分比。</p> <p>这个问题的解决办法就是通过另一个 CSS 规范:特性查询。 我们可以使用特性查询去测试是否支持 Grid 布局。 如果浏览器支持 Grid, 则将长度设置为 <code>auto</code>。</p> <pre><code>.grid &gt; div { float: left; width: 33.333%; } @supports (display: grid) { .grid &gt; div { width: auto; } } </code></pre> <h2>使用 <code>min-content</code> 和 <code>max-content</code> 控制大小</h2> <p>在 CSS Intrinsic &amp; Extrinsic Sizing Module Level 3 规范中为大小控制定义了附加的关键字。 这些关键字包括 <code>min-content</code> 和 <code>max-content</code>, 都可被用于定义网格轨道的大小。</p> <p>以一个非常简单的例子, 我创建了一个两列轨道的网格。 一列使用 <code>min-content</code> 定义大小, 第二列使用 <code>max-content</code>。 第一列的大小仅为刚好能够放下一个单词的大小 -- 这也是这条轨道大小的最小值。 第二条轨道则扩增到能够装下正行文字的大小, 你会发现这可能会触发溢出问题同时需要去解决。</p> <pre><code>.grid { display: grid; grid-template-columns: min-content max-content; } </code></pre> <p><img src="/sites/default/files/blogs/2018/1801/css-grid-layout-secrets-7.jpg" alt="minmax()函数" /></p> <p>设置了 <code>min-content</code> 的一列仅为能够放下单个单词的宽度;设置了 <code>max-content</code> 的一列则扩张到能够显示整句的长度</p> <h3>Level 2 特性</h3> <p>Grid 规范现在已经在候选推荐状态了, 这意味着将不会再对规范进行大的改动;相反的,目前正处于寻求至少两个对每个特性的实现的阶段。 这保证了规范合理并且能被浏览器所实现。</p> <p>Grid 仍然在有一些变化,然而,在本篇文章剩余的篇幅中,我们将会去探讨 Level 1 规范近期的一些变化,以及在 Level 2 中值得期待的东西。</p> <h2>改变中的间距设置</h2> <p><code>grid-gap</code> 简写,以及其全写 <code>grid-column-gap</code> 和 <code>grid-row-gap</code> 属性在 2017 年 8 月的工作组会议中修改为 <code>gap</code>, <code>column-gap</code> 和 <code>row-gap</code>。对它们的定义也已经相应的移到 Box Alignment 规范中。</p> <p>这篇规范中将 Flexbox 里已有的很好的对齐特性取出并进行扩展,使得这些特性能够在 Grid 中使用 -- 还可能应用于其他布局方法中。</p> <p>将间距特性放入 Box Alignment 规范并将其重新命名至更通用的形式中,意味着这些功能在其他布局类型中使用会更加合理。 很显然在 Flexbox 中使用是合理的。</p> <p>这次重命名意味着我们最终也会在 Flexbox 中获得更好的间距支持;再也不用纠结使用 <code>margin</code> 了。浏览器会将旧的命名别名至新的命名上, 所以如果你的代码中使用了旧的命名也不会出现问题。 然而, 你最好还是将两个属性都添加上去;浏览器会忽略不支持的那一个。</p> <h2>Gird 并不是瀑布流布局</h2> <p>当人们看到本文前面所演示的密集填充模式时, 会经常想 Grid 能做到瀑布流布局的模式。 然而,瀑布流属于完全不同的一类布局。 一个标准的瀑布流布局并不是一个严格的网格, 这种布局是介于 Flexbox 善于做的和 Grid 能做的之间。</p> <p>然而在 CSS 工作组中我们也有想过这个问题。 我们知道这是开发者们非常想实现的特性。 你可以在 <a href="//github.com/w3c/csswg-drafts/issues/945">CSS 规范设计草案 的 Github 仓库中</a> 找到讨论, 同时你也可以发表你的想法。</p> <h2>网格区域的伪元素</h2> <p>另一个 Grid 布局的常见特性需求就是能够在不通过内置元素的情况下对网格单元格设置样式。 当前,如果你要在一个区域中添加边框需要通过添加一个空元素去实现, 或者通过已生成的内容去创建一个能够添加样式的网格项。</p> <p>这里有一个关于考虑为网格区域添加伪元素的 <a href="//github.com/w3c/csswg-drafts/issues/499">issue</a> 。 如果你想对指定的区域添加背景或者边框,这将会给你带来选择这些区域的能力,而不需要添加而外的标记代码或使用已生成的内容去达到效果。</p> <p>本篇文章源于 <a href="http://www.xysjxj.com/quot;//www.myfavouritemagazines.co.uk/design/net-magazine-subscription/">ne" magazine</a> 中的 issue 298, 这个杂志为专业的 Web 设计师和开发者 —— 提供最新最潮的 web 技术和技巧 <em><a href="http://www.xysjxj.com/quot;//www.myfavouritemagazines.co.uk/design/net-magazine-back-issues/net-october-2017-issue-298/">在此购" issue 298</a></em> 或 <em><a href="http://www.xysjxj.com/quot;//www.myfavouritemagazines.co.uk/design/net-magazine-subscription/">在此订阅此杂志</a></em>。</p>" <p>喜欢这篇文章?还可以读读这些:</p> <ul> <li><a href="//www.creativebloq.com/how-to/create-a-responsive-layout-with-css-grid">Create a responsive layout with CSS Grid</a></li> <li><a href="//www.creativebloq.com/features/get-up-to-speed-with-css-grid">Get up to speed with CSS Grid</a></li> <li><a href="//www.creativebloq.com/advice/a-guide-to-writing-better-css">A guide to writing better CSS</a></li> </ul> <blockquote> <p><strong>特别声明</strong>:本文转载@NimitzDEV发布于众成翻译的《<a href="//zcfy.cc/article/css-grid-layout-secrets-revealed-creative-bloq">CSS Grid 布局揭秘</a>》一文,如需转载,烦请注明原文出处:<a href="//zcfy.cc/article/css-grid-layout-secrets-revealed-creative-bloq">http://zcfy.cc/article/css-grid-layout-secrets-revealed-creative-bloq</a></p> </blockquote> </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/624.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">转载</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/69.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">CSS3</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/356.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">CSS3 Grid Layout</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/355.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Grid</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/180.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Layout</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/130.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">布局</a></div></div></div> Mon, 22 Jan 2018 15:04:17 +0000 Airen 2352 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/html5/html5-details-summary.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><h2>了解HTML5 details, summary默认交互行为</h2> <p><code>&lt;details&gt;</code>标签在Chrome,Firefox等浏览器下默认是有展开收起行为的,例如下面HTML:</p> <pre><code>&lt;details&gt; &lt;summary&gt;这是摘要1&lt;/summary&gt; &lt;p&gt;这里具体描述,标签相对随意,例如这里使用的&amp;lt;p&amp;gt;标签。&lt;/p&gt; &lt;/details&gt; </code></pre> <p>结果UI表现为:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-1.png" alt="" /></p> <p>具体描述为:</p> <ul> <li>只显示了<code>&lt;summary&gt;</code>标签内容,而<code>&lt;p&gt;</code>默认隐藏了;</li> <li><code>&lt;summary&gt;</code>标签前面出现了一个小三角;</li> </ul> <p>小三角图形的隐喻是:我是可点击的,点击我可能会出现宝箱。</p> <p>OK,我们不妨就点击一下,结果如下图:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-2.png" alt="" /></p> <p>具体描述为:</p> <ul> <li>原本隐藏的<code>&lt;p&gt;</code>标签显示出来了;</li> <li><code>&lt;summary&gt;</code>标签前面的小三角方向朝下了;</li> </ul> <p>此时我们再一次点击,<code>&lt;p&gt;</code>标签内容又会隐藏收起,箭头方向还原,如下图:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-3.png" alt="" /></p> <p>活脱脱一个天然的展开收起效果。</p> <h3>展开与收起是通过<code>open</code>属性控制的</h3> <p>通过在<code>&lt;details&gt;</code>标签上添加布尔类型的<code>open</code>属性,可以让我们的详情信息默认就是展开状态,如下HTML示意:</p> <pre><code>&lt;details open&gt; &lt;summary&gt;这是摘要2&lt;/summary&gt; &lt;content&gt;这里&amp;lt;details&amp;gt;标签设置了HTML布尔属性open,因此,默认是展开状态。&lt;/content&gt; &lt;/details&gt; </code></pre> <p>结果如下截图:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-4.png" alt="" /></p> <p>如果我们使用JS脚本手动移除这个open属性,即使没有点击行为的发生,我们内容也会收起。</p> <h3><code>&lt;summary&gt;</code>如果缺省</h3> <p><code>&lt;summary&gt;</code>标签如果缺省,则<code>&lt;details&gt;</code>元素会在内部自动创建一个<code>&lt;summary&gt;</code>内容,默认的文案是“详细信息”。如下HTML代码:</p> <pre><code>&lt;details open&gt; &lt;p&gt;如果&amp;lt;summary&amp;gt;缺省,则会自动补上,文案是“详细信息”。&lt;/p&gt; &lt;/details&gt; </code></pre> <p>结果如下截图所示:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-5.png" alt="" /></p> <p>您可以狠狠地点击这里:<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/study/201801/html-details-summary.html">HTM" details,summary基本效果Demo</a>。</p> <div style="margin-bottom: 20px;"><iframe id="XVOMdm" src="//codepen.io/airen/embed/XVOMdm?height=400&amp;theme-id=0&amp;slug-hash=XVOMdm&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <h2>details浏览器内置UI可以自定义</h2> <p><code>&lt;details&gt;</code>标签默认的小三角样式有些简陋,在实际应用的时候,往往不是我们希望的样子,不要担心,我们是可以对其进行自定义的。在Chrome等浏览器下使用<code>::-webkit-details-marker</code>,在Firefox浏览器下使用<code>::-moz-list-bullet</code>可以对小三角进行UI控制,例如改变颜色,改变大小,使用自定义的图形代替,或者直接隐藏等,我们来看几个简单的案例。</p> <h3>小三角右侧显示同时颜色变淡</h3> <p>HTML代码如下:</p> <pre><code>&lt;details class="details-1" open&gt; &lt;summary&gt;这是示例1&lt;/summary&gt; &lt;content&gt;本案例展示对小三角UI重定义:包括显示在右侧,颜色减淡等。&lt;/content&gt; &lt;/details&gt; </code></pre> <p>CSS如下:</p> <pre><code>.details-1 summary { width: -moz-fit-content; width: fit-content; direction: rtl; } .details-1 ::-webkit-details-marker { direction: ltr; color: gray; margin-left: .5ch; } .details-1 ::-moz-list-bullet { direction: ltr; color: gray; margin-left: .5ch; } </code></pre> <p>结果如下图所示:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-6.png" alt="" /></p> <p>当我们点击摘要标题升起的时候,表现为下图(截自Firefox):</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-7.png" alt="" /></p> <p>眼见为实,您可以狠狠地点击这里:<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/study/201801/html-details-ui-custom.html">HTM" details小三角位置颜色改变Demo</a></p> <div style="margin-bottom: 20px;"><iframe id="YYBZNE" src="//codepen.io/airen/embed/YYBZNE?height=400&amp;theme-id=0&amp;slug-hash=YYBZNE&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>而实际上实际开发的时候,对小三角UI更便捷的定制方法是:隐藏浏览器原生的小三角,然后借助<code>::before</code>或<code>::after</code>伪元素重新生成我们想要的UI效果,下面这个案例就将展示相关的处理。</p> <h3>隐藏浏览器原生的小三角并使用自定义三角替换</h3> <p>HTML结构还是类似的:</p> <pre><code>&lt;details class="details-2" open&gt; &lt;summary&gt;这是示例2&lt;/summary&gt; &lt;content&gt;本案例隐藏原生小三角,使用自定义小三角。&lt;/content&gt; &lt;/details&gt; </code></pre> <p>CSS主要分为2部分,一部分是隐藏浏览器原生的小三角,另外一部分是使用伪元素生成自定义的三角效果。</p> <p>首先看一下隐藏<code>&lt;details&gt;</code>标签默认的小三角的CSS:</p> <pre><code>/* 隐藏默认三角 */ .details-2 ::-webkit-details-marker { display: none; } .details-2 ::-moz-list-bullet { font-size: 0; } </code></pre> <p>可以看到Chrome浏览器和Firefox浏览器的小三角隐藏采用的是不同的策略。在Chrome浏览器下,我们可以直接设置<code>display:none</code>进行隐藏,但是这一招在Firefox浏览器下确实没有效果的,即使设置<code>display:none!important</code>也是如此,根据我的测试,只有<code>font-size:0</code>能够比较完美的隐藏。类似<code>position:absolute;visibility:hidden</code>这种常见的隐藏也是不行的,因为<code>position:absolute</code>无法生效。</p> <p>然后是自定义小三角显示的CSS,这里采用的是<code>::after</code>伪元素模拟的:</p> <pre><code>/* 自定义的三角 */ .details-2 summary::after { content: ''; position: absolute; width: 1em; height: 1em; margin: .2em 0 0 .5ch; background: url(./arrow-on.svg) no-repeat; background-size: 100% 100%; transition: transform .2s; } .details-2:not([open]) summary::after { margin-top: .25em; transform: rotate(90deg); } </code></pre> <p>最终效果如下图所示:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-8.png" alt="" /></p> <p>收起时候:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-9.png" alt="" /></p> <p>眼见为实,您可以狠狠地点击这里:<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/study/201801/html-details-ui-custom.html">HTM" details小三角自定义Demo</a>。</p> <p>最后有一点需要注意一下,就是如果<code>&lt;details&gt;</code>标签内并没有<code>&lt;summary&gt;</code>元素,则我们的对三角的自定义代码都是无效的,可以使用一个空的<code>&lt;summary&gt;</code>元素占位,类似这样:</p> <pre><code>&lt;details&gt; &lt;summary&gt;&lt;/summary&gt; &lt;content&gt;内容。&lt;/content&gt; &lt;/details&gt; </code></pre> <h2>Chrome浏览器下点击时候outline轮廓等体验处理</h2> <p>UI可以定制了,但是还有个不容忽视的体验问题,那就是在Chrome浏览器下点击时候会出现<code>outline</code>轮廓,如下图所示:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-10.png" alt="" /></p> <p>在实际项目开发的时候,产品和设计一定会让你把这个效果去掉的。以及,当我们<code>&lt;summary&gt;</code>元素点击较快的时候,文本会被选中,也不是我们想看到的。</p> <p>阻止文本选中,我们可以:</p> <pre><code>summary { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } </code></pre> <p>对于<code>outline</code>轮廓,比较直接的做法是:</p> <pre><code>summary { outline: 0; } </code></pre> <p>但是这样处理对无障碍访问而是非常不友好的,那有没有什么办法兼顾视觉体验和无障碍访问体验呢?</p> <p>我的做法是这样子的:</p> <h3>利用<code>&lt;a&gt;</code>标签的<code>outline</code>交互体验</h3> <p>浏览器对<code>&lt;a&gt;</code>标签元素的<code>outline</code>轮廓进行了专门的体验优化处理,鼠标点击的时候不显示轮廓,键盘访问时候显示轮廓。于是我们可采用李代桃僵策略,让<code>&lt;summary&gt;</code>元素的<code>outline</code>交给<code>&lt;a&gt;</code>元素,方法就是在<code>&lt;summary&gt;</code>中再内嵌一个<code>&lt;a&gt;</code>,同时通过<code>tabindex</code>属性<code>remove</code>掉<code>&lt;summary&gt;</code>原本的可访问性。HTML代码示意如下:</p> <pre><code>&lt;details open&gt; &lt;summary tabindex="-1"&gt;&lt;a href="javascript:"&gt;这是示例&lt;/a&gt;&lt;/summary&gt; &lt;content&gt;点击无外框,键盘focus有。&lt;/content&gt; &lt;/details&gt; </code></pre> <p>CSS如下:</p> <pre><code>summary { user-select: none; outline: 0; } summary a { color: inherit; } </code></pre> <p>此时,在Chrome浏览器下,我们点击摘要信息,没有任何<code>outline</code>轮廓出现;但是当我们使用<code>Tab</code>键索引时候,可以看到下图所示的轮廓效果:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-11.png" alt="" /></p> <p>轮廓区域比原生的<code>&lt;summary&gt;</code>要小,但这无伤大雅,而且实际项目开发的时候,我们会去掉小箭头,此时只要设置<code>&lt;a&gt;</code>标签<code>display:block</code>,则轮廓就可以和<code>&lt;summary&gt;</code>保持一致了。</p> <p>接下来,我们按下<code>Space</code>空格键,就会发现<code>&lt;details&gt;</code>元素内的内容信息不断的展开与收起:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-12.png" alt="" /></p> <p>您可以狠狠地点击这里:HTML5 summary outline轮廓<code>a</code>标签处理Demo。</p> <p>然后上面实现并不完美,相比原生的<code>&lt;summary&gt;</code>元素,<code>Enter</code>回车键展开收起效果丢失了。这是因为HTML元素中如果多个<code>focusable</code>同时带<code>click</code>浏览器行为元素嵌套的时候,点击里面的元素,外部元素的浏览器行为是不会触发的。类似的有<code>&lt;label&gt;</code>内嵌<code>&lt;a&gt;</code>标签。</p> <p>对于<code>&lt;a&gt;</code>标签,其浏览器行为只能通过回车键触发,空格键是无效的;但是对于<code>&lt;summary&gt;</code>,回车键和空格键都能触发展开收起行为,这就是为什么上面代码空格键有效,回车键无效的原因。</p> <p>如果想要同时支持回车键展开与收起,可以对HTML如下处理:</p> <pre><code>&lt;details open&gt; &lt;summary tabindex="-1"&gt;&lt;a href="javascript:" onClick="this.parentNode.click();"&gt;这是示例&lt;/a&gt;&lt;/summary&gt; &lt;content&gt;点击无外框,键盘focus有。&lt;/content&gt; &lt;/details&gt; </code></pre> <p>需要注意的是上面处理在<code>&lt;summary&gt;</code>自己额外绑定<code>click</code>事件时候可能会有<code>double</code>触发的问题,此时,阻止<code>&lt;a&gt;</code>元素的冒泡即可。</p> <div style="margin-bottom: 20px;"><iframe id="XVOMVj" src="//codepen.io/airen/embed/XVOMVj?height=400&amp;theme-id=0&amp;slug-hash=XVOMVj&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <h3>JS捕获键盘行为手动设置outline</h3> <p>这个方法不需要对HTML进行任何的改动,是通过CSS和JS配合对全局的<code>&lt;summary&gt;</code>元素进行<code>outline</code>优化。</p> <p>CSS如下:</p> <pre><code>summary { user-select: none; outline: 0; } summary[focus] { outline: 1px dotted; outline: 5px auto -webkit-focus-ring-color; } </code></pre> <p>JS如下:</p> <pre><code>window.addEventListener('keydown', function () { window.isKeyEvent = true; setTimeout(function () { window.isKeyEvent = false; }, 100); }); document.addEventListener('focusin', function (event) { var target = event.target; if (target &amp;&amp; target.tagName.toLowerCase() == 'summary' &amp;&amp; window.isKeyEvent == true) { target.setAttribute('focus', ''); } }); document.addEventListener('focusout', function (event) { var eleFocusAll = document.querySelectorAll('summary[focus]'); [].slice.call(eleFocusAll).forEach(function (summary) { summary.removeAttribute('focus'); }); }); </code></pre> <p>只要把上面的CSS和JS复制到页面中,视觉体验和交互体验完美支持的<code>&lt;summary&gt;</code>元素<code>outline</code>效果就有了。</p> <p>表现为,点击<code>&lt;summary&gt;</code>没有任何<code>outline</code>,键盘<code>focus</code>时候出现,且和浏览器原生<code>outline</code>效果一模一样,<code>Space</code>键和<code>Enter</code>键展开与收起访问完全保留。</p> <p>眼见为实,您可以狠狠的点击这里:<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/study/201801/html-summary-chrome-outline-js.html">HTML" summary outline轮廓JS优化Demo</a>。</p> <p>例如下图就是键盘Tab键focus后回车后的效果:</p> <p><img src="/sites/default/files/blogs/2018/1801/html5-details-13.png" alt="" /></p> <p>每每看到如此极致的用户体验处理,心情都大好。</p> <blockquote> <p><strong>原理:</strong>关键是全局监听<code>keydown</code>事件,如果有发生,则认为此<code>100ms</code>内的页面<code>focus</code>行为均是键盘产生,从而有效区分是点击触发的<code>focus</code>行为还是键盘触发的<code>focus</code>行为,如果是键盘触发,给<code>&lt;summary&gt;</code>元素手动增加<code>outline</code>效果。</p> </blockquote> <h2>基于<code>details</code>元素行为的各种交互效果案例</h2> <p>了解了<code>&lt;details&gt;</code>元素的点击交互行为;解决了UI定制难题;解决了<code>outline</code>的体验问题,下面我们就可以付诸实践,不借助任何JS来实现各种我们平常见到的交互效果。</p> <h3>“更多”展开与收起效果</h3> <p>实现最终效果如下gif:</p> <p><img src="/sites/default/files/blogs/2018/1801/more-toggle.gif" alt="" /></p> <p>因为“更多”元素是在底部,因此效果实现的要点的所有的内容信息都放在<code>&lt;summary&gt;</code>元素内部,然后通过<code>&lt;details&gt;</code>元素的<code>open</code>属性控制UI的变化。</p> <p>HTML和CSS代码如下,其中,最核心部分已经红色高亮:</p> <pre><code>&lt;details&gt; &lt;summary&gt; &lt;p&gt;据台媒报道,大...青睐。&lt;/p&gt; &lt;div class="more"&gt; &lt;p&gt;其他几首歌曲...&lt;/p&gt; &lt;/div&gt; &lt;a&gt;更多&lt;/a&gt; &lt;/summary&gt; &lt;/details&gt; ::-webkit-details-marker { display: none; } ::-moz-list-bullet { font-size: 0; float: left; } .more { display: none; } [open] .more { display: block; } [open] summary a { font-size: 0; } [open] summary a::before { content: '收起'; font-size: 14px; } </code></pre> <p>把“更多”对应的信息放在<code>.more</code>元素内,然后通过<code>[open]</code>属性选择器控制器显示,效果即达成。</p> <p>您可以狠狠的点击这里:<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/study/201801/html-details-summary-example-toggle-more.html">HTML" details/summary更多展开收起Demo</a>。</p> <div style="margin-bottom: 20px;"><iframe id="KZJWBw" src="//codepen.io/airen/embed/KZJWBw?height=400&amp;theme-id=0&amp;slug-hash=KZJWBw&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <h3>无JS实现点击显示悬浮菜单,自定义下拉框等效果</h3> <p>效果如下gif:</p> <p><img src="/sites/default/files/blogs/2018/1801/drop-menu.gif" alt="" /></p> <p>没有任何JS参与。HTML结构如下:</p> <pre><code>&lt;details&gt; &lt;summary&gt;我的消息&lt;/summary&gt; &lt;div class="box"&gt; &lt;a href&gt;我的回答&lt;sup&gt;12&lt;/sup&gt;&lt;/a&gt; &lt;a href&gt;我的私信&lt;/a&gt; &lt;a href&gt;未评价订单&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href&gt;我的关注&lt;/a&gt; &lt;/div&gt; &lt;/details&gt; </code></pre> <p>然后CSS让<code>.box</code>元素绝对定位即可,显示和隐藏<code>&lt;details&gt;</code>元素内置行为就搞定了。</p> <p>您可以狠狠地点击这里:<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/study/201801/html-details-summary-example-menu.html">HTML" details/summary悬浮菜单Demo</a>。</p> <div style="margin-bottom: 20px;"><iframe id="eyxvPd" src="//codepen.io/airen/embed/eyxvPd?height=400&amp;theme-id=0&amp;slug-hash=eyxvPd&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <h3>Accordion多项折叠效果</h3> <p>此效果常见于条目比较多的垂直导航栏,新闻条目等。</p> <p>例如下面实现的效果:</p> <p><img src="/sites/default/files/blogs/2018/1801/accordion-toggle.gif" alt="" /></p> <p>这个更加简单了,就是一堆<code>&lt;details&gt;</code>元素并排放置就可以了,如下HTML:</p> <pre><code>&lt;details open&gt; &lt;summary&gt;&lt;dt&gt;订单中心&lt;/dt&gt;&lt;/summary&gt; &lt;dd&gt;&lt;a href&gt;我的订单&lt;/a&gt;&lt;/dd&gt; &lt;dd&gt;&lt;a href&gt;我的活动&lt;/a&gt;&lt;/dd&gt; &lt;dd&gt;&lt;a href&gt;评价晒单&lt;/a&gt;&lt;/dd&gt; &lt;dd&gt;&lt;a href&gt;购物助手&lt;/a&gt;&lt;/dd&gt; &lt;/details&gt; &lt;details open&gt; &lt;summary&gt;&lt;dt&gt;关注中心&lt;/dt&gt;&lt;/summary&gt; &lt;dd&gt;&lt;a href&gt;关注的商品&lt;/a&gt;&lt;/dd&gt; ... &lt;/details&gt; &lt;details open&gt; ... &lt;/details&gt; </code></pre> <p>计算CSS没有任何设置,效果也天然达成。</p> <p>您可以狠狠地的点击这里:<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/study/201801/html-details-summary-example-accordion.html">HTML" details/summary多列菜单折叠Demo</a>。</p> <div style="margin-bottom: 20px;"><iframe id="vpbxbz" src="//codepen.io/airen/embed/vpbxbz?height=400&amp;theme-id=0&amp;slug-hash=vpbxbz&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <h3>带slideUp/slideDown效果的多项折叠菜单</h3> <p>案例3中的展开项显示的时候是非常生硬的突然显示,实际上我们可以借助一些选择器技巧以及CSS3 <code>transition</code>属性让菜单展开收起的时候是有动画效果的,效果如下gif截图:</p> <p><img src="/sites/default/files/blogs/2018/1801/slide-toggle.gif" alt="" /></p> <p>此效果实现原理核心是<code>[open]</code>属性选择器,和加号<code>+</code>相邻兄弟选择器。</p> <p>首先看下HTML,展开列表结构发生了变化,不是作为<code>&lt;details&gt;</code>的子元素,而是作为其相邻兄弟元素存在,HTML示意:</p> <pre><code>&lt;details open&gt;&lt;summary&gt;订单中心&lt;/summary&gt;&lt;/details&gt; &lt;dl&gt; &lt;dd&gt;&lt;a href&gt;我的订单&lt;/a&gt;&lt;/dd&gt; &lt;dd&gt;&lt;a href&gt;我的活动&lt;/a&gt;&lt;/dd&gt; &lt;dd&gt;&lt;a href&gt;评价晒单&lt;/a&gt;&lt;/dd&gt; &lt;dd&gt;&lt;a href&gt;购物助手&lt;/a&gt;&lt;/dd&gt; &lt;/dl&gt; ... </code></pre> <p>上面<code>&lt;dl&gt;</code>定义列表就是展开收起的内容,其作为兄弟元素和<code>&lt;details&gt;</code>元素平起平坐,于是,我们就可以利用点击<code>&lt;summary&gt;</code>元素<code>&lt;details&gt;</code>元素的<code>open</code>属性会变化的特性实现我们想要的动画效果,CSS如下:</p> <pre><code>details + dl { max-height: 0; transition: max-height .25s; overflow: hidden; } [open] + dl { max-height: 100px; } </code></pre> <p>借助相邻兄弟选择器以及<code>max-height</code>任意元素slideUp/slideDown技术就可以效果达成。</p> <p>您可以狠狠地点击这里:<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/study/201801/html-details-summary-example-slideup-slidedown.html">HTML" details/summary多列菜单滑入滑出Demo</a>。</p> <h3>多级嵌套的树形菜单交互效果</h3> <p>这里的树形菜单效果实现也很简单,多个<code>&lt;details&gt;</code>元素相互嵌套就可以,效果Gif如下:</p> <p><img src="/sites/default/files/blogs/2018/1801/tree-menu.gif" alt="" /></p> <p>HTML结构大致如下:</p> <pre><code>&lt;details&gt; &lt;summary&gt;我的视频&lt;/summary&gt; &lt;details&gt; &lt;summary&gt;爆肝工程师的异世界狂想曲&lt;/summary&gt; &lt;div&gt;tv1-720p.mp4&lt;/div&gt; &lt;div&gt;tv2-720p.mp4&lt;/div&gt; ... &lt;div&gt;tv10-720p.mp4&lt;/div&gt; &lt;/details&gt; &lt;details&gt; &lt;summary&gt;七大罪&lt;/summary&gt; &lt;div&gt;七大罪B站00合集.mp4&lt;/div&gt; &lt;/details&gt; &lt;div&gt;珍藏动漫网盘地址.txt&lt;/div&gt; &lt;div&gt;我们的小美好.mp4&lt;/div&gt; &lt;/details&gt; </code></pre> <p>CSS的主要工作就是绘制菜单前面的加号和减号图形,例如我们可以借助<code>background</code>线性渐变,具体可参见文章<a href="//www.zhangxinxu.com/wordpress/2017/10/css3-linear-gradient-dashed-triangle-graph/">“CSS3 linear-gradient线性渐变实现虚线等简单实用图形”</a>,相关CSS如下:</p> <pre><code>details { padding-left: 20px; } summary::before { content: ''; display: inline-block; width: 12px; height: 12px; border: 1px solid #999; background: linear-gradient(to right, #999, #999) no-repeat center, linear-gradient(to top, #999, #999) no-repeat center; background-size: 2px 10px, 10px 2px; vertical-align: -2px; margin-right: 6px; margin-left: -20px; } [open] &gt; summary::before { background: linear-gradient(to right, #999, #999) no-repeat center; background-size: 10px 2px; } </code></pre> <p>效果即达成!</p> <p>您可以狠狠地点击这里:<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/study/201801/html-details-summary-example-tree-menu.html">HTML" details/summary树形菜单Demo</a>。</p> <h2>如果只想要details/summary的语义不要行为</h2> <p>如果只想要<code>&lt;details&gt;</code>元素,<code>&lt;summary&gt;</code>元素的语义,但是并不需要点击展开收起的行为,该怎么处理呢?</p> <p>例如,某评论,或者某帖子有标题和正文,非常符合详情-概要-内容的语义,但是希望是纯展示的,点击时候不收起,可以这么处理:</p> <p><code>&lt;summary&gt;</code>标签设置<code>tabindex="-1"</code>让键盘无法访问;设置CSS:</p> <pre><code>summary { outline: 0; pointer-events: none; } </code></pre> <p>这样就不能点,也不会有<code>outline</code>轮廓。</p> <h2>兼容性以及Polyfill</h2> <div style="margin-bottom: 20px;"><iframe src="//caniuse.com/details/embed" scrolling="no" frameborder="0" height="300" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>除了IE和Edge浏览器,大好河山一片绿,至少移动端可以用得比较开心。</p> <p>如果想要在桌面Web网页使用<code>&lt;details&gt;</code>元素的棒棒哒特性,我们可以对其进行<a href="http://www.xysjxj.com/quot;//github.com/javan/details-element-polyfill">Polyfill,可以参见此项目</a>。</p>" <p>对键盘访问,事件<code>toggle</code>都做了兼容。</p> <p>如果开发策略是对不支持的IE进行特异处理,则下面的JS判断是否支持<code>&lt;details&gt;</code>元素的脚本可能对你有用:</p> <pre><code>var isSupportDetails = 'open' in document.createElement('details'); </code></pre> <h2>结束语么么哒</h2> <p>无JS实现的好处有:</p> <ul> <li>省了代码,加载快了;</li> <li>实现更简单了,开发快了;</li> <li>JS还没加载交互也能进行,体验好了;</li> <li>键盘无障碍和<code>aria</code>阅读设备无障碍天然支持,体验档次高了。</li> <li>可以跟同事炫,逼格上去了。</li> <li>好,感谢阅读,行为仓促,欢迎纠错。</li> </ul> <blockquote> <p><strong>特别声明</strong>:本文转载@张鑫旭老师的《<a href="http://www.xysjxj.com/quot;//www.zhangxinxu.com/wordpress/2018/01/html5-details-summary-no-js-ux/">借助HTML" details,summary无JS实现各种交互效果</a>》一文,如需转载,烦请注明原文出处:<a href="//www.zhangxinxu.com/wordpress/2018/01/html5-details-summary-no-js-ux/">http://www.zhangxinxu.com/wordpress/2018/01/html5-details-summary-no-js-ux/</a></p> rel="nofollow" </blockquote> </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/624.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">转载</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/415.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">HTML5</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/651.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">details</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/652.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">summary</a></div></div></div> Sat, 20 Jan 2018 16:55:20 +0000 Airen 2351 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/mobile/h5-share.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>圣诞节和元旦团队策划了两个活动,都涉及到了在多个平台下的分享,如何按照产品要求实现多平台下一致的分享效果,包括分享文案的动态生成,在没有Native的帮助下是比较困难的。我们研究了很多分享方案,得到了一套较为完整的分享方案。</p> <h2>微信的分享</h2> <p>微信下的分享通过调用微信提供的<code>JS-SDK</code>和引导用户点击右上角完成。使用微信的<code>JS-SDK</code>需要引入如下<code>.js</code>文件:</p> <pre><code>&lt;script src="//res.wx.qq.com/open/js/jweixin-1.3.1.js"&gt;&lt;/script&gt; </code></pre> <p>设置分享内容的代码如下:</p> <pre><code>wx.config({ debug: false, appId: '公众号的appid', timestamp: '时间戳', nonceStr: '随机字符串', signature: '签名', jsApiList: [ 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'showOptionMenu', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem' ] }); wx.ready(function() { const share = { title: '分享标题(朋友圈只显示标题)', desc: '分享内容', imgUrl: '图片URL', link: '分享链接(最好是后台JS安全域名)', success: function() { hideMaskLayer(); // 分享成功,隐藏引导用户分享的浮层 }, cancel: function() { } }; wx.onMenuShareAppMessage(share); // 微信好友 wx.onMenuShareTimeline(share); // 朋友圈 wx.onMenuShareQQ(share); // QQ wx.onMenuShareQZone(share); // QQ空间 wx.onMenuShareWeibo(share); // 腾讯微博 }); </code></pre> <p>其中<code>wx.config</code>中的参数由服务端得到,具体可<a href="http://www.xysjxj.com/quot;//mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1421141115">参见微信的开发文档</a>。<strong>注意在公众号后台设置JS安全域名</strong>。效果如下:</p>" <p><img src="/sites/default/files/blogs/2018/1801/h5-share-1.png" alt="微信的分享" /></p> <p><img src="/sites/default/files/blogs/2018/1801/h5-share-2.png" alt="微信的分享" /></p> <h2>QQ/TIM的分享</h2> <h3>通过JavaScript API分享</h3> <p>QQ(以下无特殊说明TIM下同样有效)下也有设置分享内容的API,同样需要先引用JSBridge相关的文件:</p> <pre><code>&lt;script src="//open.mobile.qq.com/sdk/qqapi.js"&gt;&lt;/script&gt; </code></pre> <p>设置分享内容的代码如下:</p> <pre><code>const share = { title: '分享标题,最大45字节', desc: '分享内容,最大60字节', image_url: '图片URL', share_url: '分享链接' }; mqq.data.setShareInfo(share, callback); </code></pre> <blockquote> <p><strong>需要注意的是</strong>:分享链接长度不能超过<code>120</code>字节,并且必须跟页面<code>URL</code>同一个域名,否则设置不生效;分享的图片最小需要<code>200 * 200</code>,否则分享到QQ空间时会被过滤掉。设置完分享内容后,可通过API调用唤起QQ的分享面板,免去引导的过程。</p> </blockquote> <pre><code>mqq.ui.showShareMenu(); </code></pre> <p>还有一种方法,QQ提供了监听点击分享平台的事件,当点击Native分享面板中的分享平台时,会触发此事件,QQ默认的分享行为将不再执行。代码如下:</p> <pre><code>mqq.ui.setOnShareHandler(function (platform) { mqq.ui.shareMessage({ title: '分享标题', desc: '分享内容', share_type: platform, share_url: '分享链接', image_url: '图片URL', sourceName: '掌上理工大', back: true }, function() { }); }); </code></pre> <p>其中<code>platform</code>是分享平台类型,取值如下:</p> <table> <thead> <tr> <th>编号</th> <th>分享平台</th> <th>编号</th> <th>分享平台</th> </tr> </thead> <tbody> <tr> <td>0</td> <td>QQ好友</td> <td>1</td> <td>QQ空间</td> </tr> <tr> <td>2</td> <td>微信好友</td> <td>3</td> <td>微信朋友圈</td> </tr> </tbody> </table> <h3>通过<code>meta</code>标签分享</h3> <p>QQ也支持通过设置<code>meta</code>标签定义分享内容。通过定义<code>itemprop</code>可设置分享内容,同时为了更好的兼容其它平台,我们也引入了Open Graph标准。代码如下:</p> <pre><code>&lt;meta itemprop="name" property="og:title" content="分享标题"&gt; &lt;meta property="og:url" content="分享链接"&gt; &lt;meta itemprop="image" property="og:image" content="图片URL"&gt; &lt;meta name="description" itemprop="description" property="og:description" content="分享描述"&gt; </code></pre> <p>需要注意的是,<code>meta</code>标签需要是服务端渲染输出,通过JavaScript生成或修改无效。</p> <h3>通过URL Scheme唤起QQ分享</h3> <p>还可以通过URL Scheme唤起QQ进行分享,该方法的好处在于可以在非QQ环境下唤起QQ实现分享,缺点在于不能设置分享图片。代码如下:</p> <pre><code>const share = { title: '分享标题', desc: '分享内容', share_url: '分享链接' }; const url_scheme = '//share/to_fri?src_type=web&amp;version=1&amp;file_type=news&amp;share_id=1103437993&amp;title=' + Base64.encode(share.title) + '&amp;thirdAppDisplayName=5o6M5LiK55CG5bel5aSn&amp;url=' + Base64.encode(share.share_url) + '&amp;description=' + Base64.encode(share.desc); location.assign('mqqapi:' + url_scheme); setTimeout(function() { location.assign('timapi:' + url_scheme); }, 2000); </code></pre> <p>其中分享的参数在拼入<code>URL</code>中时需要<code>Base64</code>编码。为了支持TIM下的分享,我们引入了延时函数,如果唤起QQ失败该定时器将会执行唤起TIM,唤起成功离开了此页面将不会执行。QQ和TIM均安装时优先唤起QQ。 效果如下:</p> <p><img src="/sites/default/files/blogs/2018/1801/h5-share-3.png" alt="通过URL Scheme唤起QQ分享" /></p> <h3>通过分享韦德娱乐平台的URL实现</h3> <p>QQ空间提供了<a href="http://www.xysjxj.com/quot;//connect.qq.com/intro/share">分享韦德娱乐平台</a>,通过分析该韦德娱乐平台可得到分享URL的参数。代码如下:</p>" <pre><code>const share = { title: '分享标题', desc: '分享内容', image_url: ['图片URL'], share_url: '分享链接' }; let image_urls = share.image_url.map(function(image) { return encodeURIComponent(image); }); location.replace('https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=' + encodeURIComponent(share.share_url) + '&amp;site=掌上理工大&amp;title=' + share.title + '&amp;pics=' + image_urls.join('|') + '&amp;summary=' + share.desc); </code></pre> <p>其中可支持多图片的分享,图片URL用竖线分隔。该方法优点在于同样支持非QQ环境下的分享。非QQ下用户登录后即可分享,QQ下可免登直接分享。效果如下:</p> <p><img src="/sites/default/files/blogs/2018/1801/h5-share-4.png" alt="通过分享韦德娱乐平台的URL实现" /></p> <h2>微博的分享</h2> <h3>通过分享韦德娱乐平台的URL实现</h3> <p>微博同样提供了分享韦德娱乐平台,通过分析URL可得到分享参数。代码如下:</p> <pre><code>const share = { title: '分享标题', image_url: '图片URL', share_url: '分享链接' }; location.replace('https://service.weibo.com/share/share.php?url=' + encodeURIComponent(share.share_url) + '&amp;title=' + share.title + '&amp;appkey=277159429&amp;&amp;ralateUid=1855112015&amp;pic=' + share.image_url + '&amp;searchPic=true'); </code></pre> <p>其中<code>appKey</code>参数可选,如果设置微博将会显示分享来源为<code>key</code>对应的应用名称(应用可在<a href="http://www.xysjxj.com/quot;//open.weibo.com/">这里注册</a>);<code>ralateUid</code>参数可选,指定微博用户<code>id</code>,会在微博尾部<code>@</code>此用户;<code>searchPic</code>用于控制是否自动爬取页面的图片,和<code>pic</code>不共存。效果如下:</p>" <p><img src="/sites/default/files/blogs/2018/1801/h5-share-5.png" alt="通过分享韦德娱乐平台的URL实现" /></p> <h3>通过微博API自动发送微博</h3> <p>微博提供了API可通过服务端调用接口直接发送一条微博。</p> <pre><code>POST https://api.weibo.com/2/statuses/share.json </code></pre> <p>参数如下:</p> <table> <thead> <tr> <th>&nbsp;</th> <th>必选</th> <th>类型及范围</th> <th>说明编号</th> </tr> </thead> <tbody> <tr> <td><code>access_token</code></td> <td>是</td> <td><code>string</code></td> <td>采用OAuth授权方式为必填参数,OAuth授权后获得</td> </tr> <tr> <td><code>status</code></td> <td>是</td> <td><code>string</code></td> <td>用户分享到微博的文本内容,必须<code>URL Encode</code>,文本中不能包含“#话题词#”,同时文本中必须包含至少一个分享的<code>URL</code>,且该<code>URL</code>的域名需要在后台设置。</td> </tr> <tr> <td><code>pic</code></td> <td>是</td> <td><code>binary</code></td> <td>用户分享到微博的图片,仅支持<code>.jpeg</code>、<code>.gif</code>、<code>.png</code>图片,上传图片大小限制为<code>5M</code>。上传图片时,<code>POST</code>方式提交请求,需要采用<code>multipart/form-data</code>编码方式。</td> </tr> <tr> <td><code>rip</code></td> <td>否</td> <td><code>string</code></td> <td>开发者上报的操作用户真实<code>IP</code>,比如:<code>211.156.0.1</code></td> </tr> </tbody> </table> <p>具体可参见<a href="http://www.xysjxj.com/quot;//open.weibo.com/wiki/2/statuses/share">微博分享平台</a>。</p>" <h3>通过JS API分享</h3> <p>微博同样有提供JS-SDK可供调用Native的方法,在使用前需要在微博开放平台申请轻应用,并设置安全域名。 使用微信的JS-SDK需要引入如下<code>.js</code>文件:</p> <pre><code>&lt;script src="//tjs.sjs.sinajs.cn/open/thirdpart/js/jsapi/mobile.js"&gt;&lt;/script&gt; </code></pre> <p>同样需要先设置初始化参数。</p> <pre><code>WeiboJS.init({ appkey : '轻应用key', debug: false, timestamp: '时间戳', noncestr: '随机字符串', signature: '签名', scope: ['openMenu', 'setMenuItems', 'menuItemSelected', 'setSharingContent'] }, function() { }); </code></pre> <p>有<code>3</code>个关于分享的JS API可供使用。</p> <h4><code>openMenu</code></h4> <p>该API可调起Native的分享面板。</p> <pre><code>WeiboJS.invoke('openMenu'); </code></pre> <h4><code>setSharingContent</code></h4> <p>该API可设置分享的内容。</p> <pre><code>WeiboJS.invoke('openMenu', { icon: share.title, desc: share.desc, icon: share.image_url }); </code></pre> <h4><code>invokeMenuItem</code></h4> <p>该API可以直接触发分享面板中点击相应菜单项。</p> <pre><code>WeiboJS.invoke('invokeMenuItem', { code: platform }); </code></pre> <p>其中<code>platform</code>是分享平台类型,取值如下:</p> <table> <thead> <tr> <th>编号</th> <th>分享平台</th> <th>编号</th> <th>分享平台</th> </tr> </thead> <tbody> <tr> <td>1001</td> <td>微博</td> <td>1002</td> <td>微博好友圈</td> </tr> <tr> <td>1003</td> <td>微博私信</td> <td>1004</td> <td>微信好友</td> </tr> <tr> <td>1005</td> <td>微信朋友圈</td> <td>1006</td> <td>微米好友</td> </tr> <tr> <td>1007</td> <td>微米圈</td> <td>1008</td> <td>来往(点点虫)好友</td> </tr> <tr> <td>1009</td> <td>来往(点点虫)动态</td> <td>1010</td> <td>QQ好友</td> </tr> <tr> <td>1011</td> <td>QQ空间</td> <td>1101</td> <td>短信</td> </tr> <tr> <td>2001</td> <td>系统浏览器</td> <td>2002</td> <td>复制链接</td> </tr> </tbody> </table> <p>通过使用API 1 + API 2(最佳)或API 2 + API 3即可实现分享。具体可参见<a href="http://www.xysjxj.com/quot;//open.weibo.com/wiki/%E8%BD%BB%E5%BA%94%E7%94%A8H5%E6%96%B0%E7%89%88JS">微博的开发文档</a>。</p>" <h2>支付宝的分享</h2> <p>支付宝同样提供了JS API,可以很方便的设置分享内容和唤起Native分享面板;不足之处在于不支持分享到QQ、微信等平台。使用支付宝的JS-SDK需要引入如下js文件:</p> <pre><code>&lt;script src="//a.alipayobjects.com/g/h5-lib/alipayjsapi/3.0.6/alipayjsapi.inc.min.js"&gt;&lt;/script&gt; </code></pre> <p>代码如下:</p> <pre><code>const share = { title: '分享标题', content: '分享内容', image: '图片URL', url: '分享链接', captureScreen: false, showToolBar: false }; ap.share(share, function() { }); </code></pre> <p>效果如下:</p> <p><img src="/sites/default/files/blogs/2018/1801/h5-share-6.png" alt="支付宝的分享" /></p> <h2>UC浏览器的分享</h2> <p>UC浏览器也提供了JS API调用Native的分享,支持唤起分享面板和分享到具体平台。代码如下:</p> <pre><code>const share = { title: '分享标题', desc: '分享内容', image_url: '图片URL', share_url: '分享链接' }; const isiOS = /(iPhone|iPad|iPod)/.test(navigator.userAgent); // 判断应用平台 if (isiOS) { if (ucbrowser.web_shareEX) { ucbrowser.web_shareEX( JSON.stringify({ title: share.title, content: share.desc, sourceUrl: share.share_url, imageUrl: share.image_url, source: '掌上理工大', target: platform }) ) } else { ucbrowser.web_share(share.title, share.desc, share.share_url, platform, '', '掌上理工大', share.image_url); } } else ucweb.startRequest('shell.page_share', [share.title, share.desc, share.share_url, platform, '', '掌上理工大', share.image_url]); </code></pre> <p>其中<code>platform</code>是分享平台类型,取值如下:</p> <table> <thead> <tr> <th>Android编号</th> <th>iOS编号</th> <th>分享平台</th> </tr> </thead> <tbody> <tr> <td><code>'WechatFriends'</code></td> <td><code>'kWeixinFriend'</code></td> <td>微信好友</td> </tr> <tr> <td><code>'WechatTimeline'</code></td> <td><code>'kWeixin'</code></td> <td>微信朋友圈</td> </tr> <tr> <td><code>'QQ'</code></td> <td><code>'kQQ'</code></td> <td>QQ好友</td> </tr> <tr> <td><code>'Qzone'</code></td> <td><code>'kQZone'</code></td> <td>QQ空间</td> </tr> <tr> <td><code>'SinaWeibo'</code></td> <td><code>'kSinaWeibo'</code></td> <td>微博</td> </tr> <tr> <td><code>undefined</code></td> <td><code>undefined</code></td> <td>分享面板</td> </tr> </tbody> </table> <p>调起分享面板的效果如下:</p> <p><img src="/sites/default/files/blogs/2018/1801/h5-share-7.png" alt="UC浏览器的分享" /></p> <p>调起微博:</p> <p><img src="/sites/default/files/blogs/2018/1801/h5-share-8.png" alt="UC浏览器的分享" /></p> <h2>QQ浏览器的分享</h2> <p>QQ浏览器也提供了JS API调用Native的分享,同样支持唤起分享面板、生成二维码和分享到具体平台。 首先需要引入如下JS文件:</p> <pre><code>&lt;script src="//jsapi.qq.com/get?api=app.share"&gt;&lt;/script&gt; </code></pre> <p>代码如下:</p> <pre><code>browser.app.share({ title: share.title, description: share.desc, url: share.share_url, img_url: share.image_url, from: '掌上理工大', to_app: platform }); </code></pre> <p>其中<code>platform</code>是分享平台类型,取值如下:</p> <table> <thead> <tr> <th>编号</th> <th>分享平台</th> <th>编号</th> <th>分享平台</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>微信好友</td> <td>8</td> <td>微信朋友圈</td> </tr> <tr> <td>4</td> <td>QQ好友</td> <td>3</td> <td>QQ空间</td> </tr> <tr> <td>11</td> <td>微博</td> <td>5</td> <td>更多</td> </tr> <tr> <td>7</td> <td>生成二维码</td> <td>10</td> <td>复制链接</td> </tr> <tr> <td>undefined</td> <td>分享面板</td> <td>&nbsp;</td> <td>&nbsp;</td> </tr> </tbody> </table> <p>调起分享面板的效果如下:</p> <p><img src="/sites/default/files/blogs/2018/1801/h5-share-9.png" alt="QQ浏览器的分享" /></p> <blockquote> <p><strong>特别声明:</strong> 文本转载@Crazy_Urus 发布在掘金的《<a href="http://www.xysjxj.com/quot;//juejin.im/post/5a61a8b86fb9a01cba42a742">移动端H5多平台分享实践</a>》一文。如需转载,烦请注明原文出处:<" href="//juejin.im/post/5a61a8b86fb9a01cba42a742">https://juejin.im/post/5a61a8b86fb9a01cba42a742</a></p> rel="nofollow" </blockquote> </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/624.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">转载</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/mobile"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">mobile</a></div></div></div> Sat, 20 Jan 2018 15:30:14 +0000 Airen 2350 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/create-progress-bar-with-svg.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>进度条是我们在Web中经常看到的一种效果,常见的进度条有水平横条和径向圆形的进度条。今天我们来看看怎么使用SVG来实现进度条的效果。使用SVG可以很容易的实现,也易于理解,最主要是使用SVG实现的进度条具有良好的跨浏览器,并且能根据浏览器屏幕尺寸很好的显示。</p> <h2>基础</h2> <p>在具体制作之前,有一些简单的概念要了解一下,这是制作进度条的一些基础。</p> <ul> <li>水平进度条,是一条直线,使用SVG的<code>&lt;line&gt;</code>元素可以绘制</li> <li>圆形进度条,是一个环形,使用SVG的<code>&lt;circle&gt;</code>元素可以绘制</li> <li>通过<code>fill:none</code>设置线条无填充色,使用<code>stroke-width</code>来设置进度条的粗细</li> </ul> <p>使用<code>stroke-width</code>设置进度条粗细,水平进度条相对而言较主简单,直接设置就能指定进度条的高度,对于其长度通过<code>(x1,y1)</code>和<code>(x2,y2)</code>来确定。对于圆形进度条,同样需要使用<code>fill:none</code>让圆形不填充任何颜色,<code>stroke-width</code>设置圆形的粗细,只是其值是圆周长的十分之一。</p> <p>通过<code>stroke-width</code>和圆的周长,我们可以计算出圆形的半径。比如我们圆形的外周长是<code>120</code>,同时<code>stroke-width</code>的值是<code>12</code>。这样我们就可以计算出圆形半径:</p> <pre><code>(120 / 2) - (12 / 2) = 54 </code></pre> <p>SVG代码很简单:</p> <pre><code>&lt;svg width="200" height="200" viewBox="0 0 200 200"&gt; &lt;line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#666" /&gt; &lt;circle cx="60" cy="80" r="54" fill="none" stroke="#666" stroke-width="12" /&gt; &lt;/svg&gt; </code></pre> <p>这个时候你看到的效果如下:</p> <div style="margin-bottom: 20px; padding: 2px; border: 1px solid #ccc;display: flex; justify-content: center; align-items: center; width: 100%;"> <svg width="200" height="200" viewBox="0 0 200 200"> <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#666" /> <circle cx="60" cy="80" r="54" fill="none" stroke="#666" stroke-width="12" /> </svg> </div> <h2>制作进度条</h2> <p>事实上,我们所看到的进度条都是有另一个颜色来表示进度的,而上面我们看到的只是进度条的背景色。也就是说,我们需要再绘制一个<code>&lt;line&gt;</code>和<code>&lt;circle&gt;</code>元素,其坐标参数,进度条粗细等参数都一样,唯一不同的是,线条的颜色要不一样。</p> <p>通过《<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-layer.html">SVG的图层和渲染顺序</a>》和《<" href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/elegant-outlines-with-svg-paint-order.html">优雅的轮廓" SVG <code>paint-order</code></a>》学习,了解了SVG中绘制过程有自己的基本原则:</p> <blockquote> <p>解析顺序和绘制顺序一致,都要遵守XML中元素的位置排列。SVG中元素在XML中有固定的排列顺序,浏览器渲染时会遵守这个顺序,绘制时也同样会遵守这个顺序。也就是说先出现的元素会出现在绘制的底层,而后出现的元素会绘制在顶层,如果元素间的位置有重叠,则会后绘制的元素会盖住先绘制的元素。</p> </blockquote> <p><img src="/sites/default/files/blogs/2017/1712/svg-layer-8.png" alt="" /></p> <p>了解了这一种,那就好办了。依次在<code>&lt;line&gt;</code>后面再绘制一个<code>&lt;line&gt;</code>,并把它的<code>stroke</code>设置为其他颜色,比如<code>orange</code>。同样的在<code>&lt;circle&gt;</code>之后再绘制一个<code>&lt;circle&gt;</code>,同样把<code>stroke</code>设置为<code>orange</code>:</p> <pre><code>&lt;svg width="200" height="200" viewBox="0 0 200 200"&gt; &lt;line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#666" /&gt; &lt;line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#FC4D04" /&gt; &lt;circle cx="60" cy="80" r="54" fill="none" stroke="#666" stroke-width="12" /&gt; &lt;circle cx="60" cy="80" r="54" fill="none" stroke="#FC4D04" stroke-width="12" /&gt; &lt;/svg&gt; </code></pre> <p>你将看到的效果现在变成这样了,橙色的覆盖了灰色的:</p> <div style="margin-bottom: 20px; padding: 2px; border: 1px solid #ccc;display: flex; justify-content: center; align-items: center; width: 100%;"> <svg width="200" height="200" viewBox="0 0 200 200"> <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#666" /> <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#FC4D04" /> <circle cx="60" cy="80" r="54" fill="none" stroke="#666" stroke-width="12" /> <circle cx="60" cy="80" r="54" fill="none" stroke="#FC4D04" stroke-width="12" /> </svg> </div> <h2>改变进度条位置</h2> <p>上面看到的效果就是进度条<code>100%</code>的位置,但我们很多时候不是<code>100%</code>,而是其他的位置,那么上面的效果就不是我们所需要的了。我们需要一些方法来处理不同进度时,橙色的进度位置。那怎么做呢?</p> <p>如果你阅读了前面整理的:</p> <ul> <li><a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-stroke.html">描边特性</a></li>" <li><a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-animation-guide.html">SV" 路径动画简易指南</a></li> <li><a href="https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-line-animation-works.html">SVG线条动画实现原理</a></li> rel="nofollow" <li><a href="//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/creating-a-border-animation-effect-with-svg-and-css.html">利用 SVG 和 CSS3 实现有趣的边框动画</a></li> <li><a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/the-beauty-of-the-lines-break-lines-svg-animation.html">线条之美,玩转SVG线条动画</a></li>" </ul> <p>我想你肯定会想到SVG的<code>stroke-dasharray</code>和<code>stroke-dashoffset</code>。是的,就是这两个属性能轻易的帮助我们要达到我们想要的效果。其技术关键点:</p> <ul> <li>如果<code>stroke-dasharray</code>和<code>stroke-dashoffset</code>设置的值都是路径(<code>line</code>的长度,<code>circle</code>的周长),那么橙色的<code>line</code>和<code>circle</code>将看不到,这个时候就是进度条<code>0%</code>的状态,当<code>stroke-dashoffset</code>加到<code>0</code>的位置时,这个时候就是进度条<code>100%</code>的状态。<strong>言外之意,改变<code>stroke-dashoffset</code>的值,就能得到进度条<code>0%~100%</code>之间的状态</strong>。</li> <li>通过<code>.getTotalLength()</code>获取对应图形的长度。</li> </ul> <p>比如:</p> <pre><code>document.querySelectorAll('line')[1].getTotalLength() // =&gt; 100 document.querySelectorAll('circle')[1].getTotalLength() // =&gt; 338.7438659667969 </code></pre> <p>这就好办了,在橙色的<code>line</code>和<code>circle</code>上设置<code>stroke-dasharray</code>和<code>stroke-dashoffset</code>值:</p> <pre><code>&lt;svg width="200" height="200" viewBox="0 0 200 200"&gt; &lt;line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#666" /&gt; &lt;line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#FC4D04" stroke-dasharray="100" stroke-dashoffset="100" /&gt; &lt;circle cx="60" cy="80" r="54" fill="none" stroke="#666" stroke-width="12" /&gt; &lt;circle cx="60" cy="80" r="54" fill="none" stroke="#FC4D04" stroke-width="12" stroke-dasharray="339" stroke-dashoffset="339" /&gt; &lt;/svg&gt; </code></pre> <p>这样一来,橙色的就看不到了:</p> <div style="margin-bottom: 20px; padding: 2px; border: 1px solid #ccc;display: flex; justify-content: center; align-items: center; width: 100%;"> <svg width="200" height="200" viewBox="0 0 200 200"> <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#666" /> <line x1="10" y1="10" x2="110" y2="10" fill="none" stroke-width="12" stroke="#FC4D04" stroke-dasharray="100" stroke-dashoffset="100" /> <circle cx="60" cy="80" r="54" fill="none" stroke="#666" stroke-width="12" /> <circle cx="60" cy="80" r="54" fill="none" stroke="#FC4D04" stroke-width="12" stroke-dasharray="339" stroke-dashoffset="339" /> </svg> </div> <p>为了更易于理解,在上面的基础上做一下简单的修改:</p> <div style="margin-bottom: 20px;"><iframe id="ZvmjON" src="//codepen.io/airen/embed/ZvmjON?height=400&amp;theme-id=0&amp;slug-hash=ZvmjON&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>上面的效果相对而言较为简单。如果你使用SVG的其他一些特性,比如渐变,甚至是将<code>line</code>和<code>circle</code>换成<code>path</code>。这样一来,要整成什么样形状的进度条都OK,也简单。比如下面这个示例:</p> <div style="margin-bottom: 20px;"><iframe id="vpQVKB" src="//codepen.io/airen/embed/vpQVKB?height=400&amp;theme-id=0&amp;slug-hash=vpQVKB&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <h2>总结</h2> <p>今天主要介绍了怎么使用SVG来制作水平和圆形的进度条,甚至怎么制作任意思形状的进度条。制作原理并不复杂,我想你要是阅读到这里,以及阅读前面的内容,你应该非常的清楚。但话说回来,现在的进度条效果还很粗陋,但并不要紧,如果你感兴趣的话,请关注后续的更新,下一次咱们来看看怎么用Vue来把今天这两个进度条封装成对应的韦德娱乐平台,并且将这个进度条打磨的更精美。</p> <div class="blog-author media"><a class="media-object" href="http://www.xysjxj.com/quot;//weibo.com/韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权)"" target="_blank"><img src="/sites/default/files/blogs/author/airen.jpg"></a><div class="media-body"><h3 class="media-heading"><a href="http://www.xysjxj.com/quot;//weibo.com/韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权)"" target="_blank">大漠</a></h3><div class="media-des">常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等韦德1946手机版客户端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/book-comment.html"" target="_blank">图解CSS3:核心技术与案例实战</a>》。</div></div></div> <p>如需转载,烦请注明出处:<a href="//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/create-progress-bar-with-svg.html">https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/create-progress-bar-with-svg.html</a></p> rel="nofollow" </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blogs/svg.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/svg-tutorial"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG</a></div></div></div> Thu, 18 Jan 2018 15:00:34 +0000 Airen 2349 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/the-beauty-of-the-lines-break-lines-svg-animation.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>在上一节的《<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-line-animation-works.html">SVG线条动画实现原理</a>》一文中,了解了SVG中线动画是怎么做的。在这篇文章中,了解了怎么借助Sketch这样的制作软件绘制SVG的路径,然后借助于SVG的<code>stroke-dasharray</code>和<code>stroke-dashoffset</code>值设置为路径的长度(最好是大于其长度,可以通过<code>.getTotalLength()</code>获取到路径的长度),在<code>@keframes</code>中的<code>100%</code>处设置<code>stroke-dashoffset</code>的值为<code>0</code>就可以实现线条自画的一个动画效果。</p>" <p>原理很简单,但在上一篇文章中,看到的仅是一条路径(也就是一条线的自画效果),如果我们想对一图形进行依次自动动效呢?其实也是可以实现的。今天我们在这篇文章中就来学习一下,怎么实现。</p> <h2>先上个效果</h2> <div style="margin-bottom: 20px;"><iframe id="dJgQMv" src="//codepen.io/airen/embed/dJgQMv?height=400&amp;theme-id=0&amp;slug-hash=dJgQMv&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <h2>扣图的活不能丢</h2> <p>要实现上面效果的图形,就得先要绘制出对应的一些路径效果。不过自已绘制总是蛋疼的。我在网上找了一个图:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-path-animation-1.png" alt="" /></p> <p>然后可以借助对应的绘图软件的钢笔工具,根据图形描边出需要的效果。我使用的是Sketch。</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-path-animation-2.png" alt="" /></p> <p>这仅仅是粗略的描出来的路径,为了效果更接近于原图,我们需要再打磨一下。</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-path-animation-3.png" alt="" /></p> <h2>导出SVG路径</h2> <p>虽然看上去还有丑丑的,事实上这个时候我需要一个美女设计师来帮我。最好是手把手的能教我怎么做。期待中...(^_^)。把刚才绘制的路径,导出一个<code>.svg</code>文件,并把用编辑器打开。并清理不需要的代码,把这些SVG代码放置到HTML中:</p> <pre><code>&lt;svg width="175px" height="231px" viewBox="0 0 175 231"&gt; &lt;path d="M4,68.5 C15.5117172,59.8043794 25.3450505,52.4710461 33.5,46.5 C45.7324243,37.5434309 59.5,39.5 63,36.5 C66.5,33.5 59.0969918,4.83258162 67,3 C74.9030082,1.16741838 97.9512056,10.8168783 99.5,32.5 C100,39.5 99.888886,35.5648143 117.5,38.5 C126.5,40 138.081405,46.841093 146,53 C155,60 163.5,67.9635628 163.5,68.5" class="header" fill="none" stroke="#FC4D04" stroke-width="5"&gt;&lt;/path&gt; &lt;path d="M43,77.5 C42.3143438,85.590743 43.0597683,91.1897744 48,96 C52.9402317,100.810226 56.8631639,100.734576 60.5,94.5 C64.1368361,88.2654238 64.6123158,80.7011579 62,74 C59.3876842,67.2988421 55.8263003,65.7476499 51.5,67 C47.1736997,68.2523501 43.6856562,69.409257 43,77.5 Z" class="eye" fill="none" stroke="#FB4B08" stroke-width="2"&gt;&lt;/path&gt; &lt;path d="M108,70.5 C103.173285,74.1494671 102.037015,85.8394525 105,93 C107.962985,100.160547 114.658219,100.038908 120,96 C125.341781,91.9610922 125.660258,80.637289 122.5,73 C119.339742,65.362711 112.826715,66.8505329 108,70.5 Z" class="eye" fill="none" stroke="#F84F04" stroke-width="2"&gt;&lt;/path&gt; &lt;path d="M127.5,122 C128.5,122.5 132.5,114.5 127.5,113 C122.5,111.5 21,112 19.5,112 C18,112 16,134 27.5,149.5 C39,165 44.1240033,175.272736 64,180 C83.8759967,184.727264 101,182.5 120,171.5 C139,160.5 135.222169,157.621052 142.5,146 C149.777831,134.378948 148.5,122.5 151,122 C153.5,121.5 159.5,120 162.5,122 C163.932223,122.954815 164.370326,125.750806 164.258821,128.675882 C164.136763,131.877804 163.356139,135.234403 162.5,136.5 C160.861745,138.921768 151,136 150,140 C149,144 150.763923,145.975983 155.5,147 C160.236077,148.024017 161.7167,147.699962 168.5,140 C175.2833,132.300038 173.536826,132.171852 172,125 C170.463174,117.828148 166.5,115 162.5,113.5 C158.5,112 147.5,112 143,113 C138.5,114 139.185047,135.464729 136.5,138.5 C133.814953,141.535271 125,145.5 119,140 C113,134.5 113.098161,134.086447 104,134.5 C94.9018386,134.913553 96.6264124,141.5 86,141.5 C75.3735876,141.5 74,134.5 64,134.5 C54,134.5 48.8344819,143.597972 42,144 C35.1655181,144.402028 34.4270564,143.216913 30,136.5 C25.5729436,129.783087 26.5,124.5 27.5,122 C28.5,119.5 126.5,121.5 127.5,122 Z" class="mouth" fill="none" stroke="#FC4F04" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M2,210 L20.5,210" class="t-1" fill="none" stroke="#020202" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M11,212 L11,229" class="t-2" fill="none" stroke="#020202" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M28.5,229.5 C27.5,216.833333 28.5,209.833333 31.5,208.5 C36,206.5 42,207.5 42.5,213 C42.8333333,216.666667 42.8333333,222.166667 42.5,229.5" class="a-1" fill="none" stroke="#050505" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M30,222 L36.5,219.5" class="a-2" fill="none" stroke="#040404" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M52.5,220.5 C51.772058,215.205876 52.5,209.5 58,208.5 C63.5,207.5 66.5,211 68,214.25 C69,216.416667 68.3333333,220.166667 66,225.5 C64.4336186,228.85813 62.266952,230.024797 59.5,229 C55.3495721,227.462804 53.227942,225.794124 52.5,220.5 Z" class="o" fill="none" stroke="#0A0A0A" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M91.5,209 C81.8333333,208.666667 76.6666667,210.666667 76,215 C75,221.5 76.5,224.5 79.5,227 C81.5,228.666667 85.5,229.166667 91.5,228.5" class="c" fill="none" stroke="#020202" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M100.5,229.5 C100.166667,219.5 100.333333,213.333333 101,211 C102,207.5 105,208 108.5,208 C112,208 115,210.5 115.5,214.5 C115.833333,217.166667 115.833333,222.166667 115.5,229.5" class="a2-1" fill="none" stroke="#100F0F" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M102,220.5 L108.5,218.5" class="a2-1" fill="none" stroke="#100F0F" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M126,228.5 C124.666667,216.833333 124.5,210.666667 125.5,210 C127,209 141,209 141,209.5" class="f-1" fill="none" stroke="#060405" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M126.5,219.5 L140,219.5" class="f-2" fill="none" stroke="#060405" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M164.5,209.5 C155.5,208.833333 150.5,209 149.5,210 C148,211.5 149.5,228 149.5,228.5 C149.5,228.833333 154.5,229 164.5,229" class="e-1" fill="none" stroke="#060405" stroke-width="3"&gt;&lt;/path&gt; &lt;path d="M150,219 L164,219" class="e-2" stroke="#060405" stroke-width="3" fill="none"&gt;&lt;/path&gt; &lt;/svg&gt; </code></pre> <p>上面的图总共有<code>16</code>个<code>path</code>路径。放到HTML中的效果如下:</p> <div style="margin-bottom: 20px; padding: 2px; border: 1px solid #ccc;display: flex; justify-content: center; align-items: center; width: 100%;"> <svg width="175px" height="231px" viewBox="0 0 175 231"> <path d="M4,68.5 C15.5117172,59.8043794 25.3450505,52.4710461 33.5,46.5 C45.7324243,37.5434309 59.5,39.5 63,36.5 C66.5,33.5 59.0969918,4.83258162 67,3 C74.9030082,1.16741838 97.9512056,10.8168783 99.5,32.5 C100,39.5 99.888886,35.5648143 117.5,38.5 C126.5,40 138.081405,46.841093 146,53 C155,60 163.5,67.9635628 163.5,68.5" class="header" fill="none" stroke="#FC4D04" stroke-width="5"></path> <path d="M43,77.5 C42.3143438,85.590743 43.0597683,91.1897744 48,96 C52.9402317,100.810226 56.8631639,100.734576 60.5,94.5 C64.1368361,88.2654238 64.6123158,80.7011579 62,74 C59.3876842,67.2988421 55.8263003,65.7476499 51.5,67 C47.1736997,68.2523501 43.6856562,69.409257 43,77.5 Z" class="eye" fill="none" stroke="#FB4B08" stroke-width="2"></path> <path d="M108,70.5 C103.173285,74.1494671 102.037015,85.8394525 105,93 C107.962985,100.160547 114.658219,100.038908 120,96 C125.341781,91.9610922 125.660258,80.637289 122.5,73 C119.339742,65.362711 112.826715,66.8505329 108,70.5 Z" class="eye" fill="none" stroke="#F84F04" stroke-width="2"></path> <path d="M127.5,122 C128.5,122.5 132.5,114.5 127.5,113 C122.5,111.5 21,112 19.5,112 C18,112 16,134 27.5,149.5 C39,165 44.1240033,175.272736 64,180 C83.8759967,184.727264 101,182.5 120,171.5 C139,160.5 135.222169,157.621052 142.5,146 C149.777831,134.378948 148.5,122.5 151,122 C153.5,121.5 159.5,120 162.5,122 C163.932223,122.954815 164.370326,125.750806 164.258821,128.675882 C164.136763,131.877804 163.356139,135.234403 162.5,136.5 C160.861745,138.921768 151,136 150,140 C149,144 150.763923,145.975983 155.5,147 C160.236077,148.024017 161.7167,147.699962 168.5,140 C175.2833,132.300038 173.536826,132.171852 172,125 C170.463174,117.828148 166.5,115 162.5,113.5 C158.5,112 147.5,112 143,113 C138.5,114 139.185047,135.464729 136.5,138.5 C133.814953,141.535271 125,145.5 119,140 C113,134.5 113.098161,134.086447 104,134.5 C94.9018386,134.913553 96.6264124,141.5 86,141.5 C75.3735876,141.5 74,134.5 64,134.5 C54,134.5 48.8344819,143.597972 42,144 C35.1655181,144.402028 34.4270564,143.216913 30,136.5 C25.5729436,129.783087 26.5,124.5 27.5,122 C28.5,119.5 126.5,121.5 127.5,122 Z" class="mouth" fill="none" stroke="#FC4F04" stroke-width="3"></path> <path d="M2,210 L20.5,210" class="t-1" fill="none" stroke="#020202" stroke-width="3"></path> <path d="M11,212 L11,229" class="t-2" fill="none" stroke="#020202" stroke-width="3"></path> <path d="M28.5,229.5 C27.5,216.833333 28.5,209.833333 31.5,208.5 C36,206.5 42,207.5 42.5,213 C42.8333333,216.666667 42.8333333,222.166667 42.5,229.5" class="a-1" fill="none" stroke="#050505" stroke-width="3"></path> <path d="M30,222 L36.5,219.5" class="a-2" fill="none" stroke="#040404" stroke-width="3"></path> <path d="M52.5,220.5 C51.772058,215.205876 52.5,209.5 58,208.5 C63.5,207.5 66.5,211 68,214.25 C69,216.416667 68.3333333,220.166667 66,225.5 C64.4336186,228.85813 62.266952,230.024797 59.5,229 C55.3495721,227.462804 53.227942,225.794124 52.5,220.5 Z" class="o" fill="none" stroke="#0A0A0A" stroke-width="3"></path> <path d="M91.5,209 C81.8333333,208.666667 76.6666667,210.666667 76,215 C75,221.5 76.5,224.5 79.5,227 C81.5,228.666667 85.5,229.166667 91.5,228.5" class="c" fill="none" stroke="#020202" stroke-width="3"></path> <path d="M100.5,229.5 C100.166667,219.5 100.333333,213.333333 101,211 C102,207.5 105,208 108.5,208 C112,208 115,210.5 115.5,214.5 C115.833333,217.166667 115.833333,222.166667 115.5,229.5" class="a2-1" fill="none" stroke="#100F0F" stroke-width="3"></path> <path d="M102,220.5 L108.5,218.5" class="a2-1" fill="none" stroke="#100F0F" stroke-width="3"></path> <path d="M126,228.5 C124.666667,216.833333 124.5,210.666667 125.5,210 C127,209 141,209 141,209.5" class="f-1" fill="none" stroke="#060405" stroke-width="3"></path> <path d="M126.5,219.5 L140,219.5" class="f-2" fill="none" stroke="#060405" stroke-width="3"></path> <path d="M164.5,209.5 C155.5,208.833333 150.5,209 149.5,210 C148,211.5 149.5,228 149.5,228.5 C149.5,228.833333 154.5,229 164.5,229" class="e-1" fill="none" stroke="#060405" stroke-width="3"></path> <path d="M150,219 L164,219" class="e-2" stroke="#060405" stroke-width="3" fill="none"></path> </svg> </div> <p>接下先给所有的<code>path</code>加上对应的<code>stroke-dasharray</code>和<code>stroke-dashoffset</code>的值:</p> <pre><code>path { stroke-dasharray: 3; stroke-dashoffset: 2; } </code></pre> <p>这个时候你看到的效果如下:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-path-animation-4.png" alt="" /></p> <h2>添加动画</h2> <blockquote> <p>将<code>stroke-dasharray</code>和<code>stroke-dashoffset</code>值设置为路径的长度(最好是大于其长度,可以通过<code>.getTotalLength()</code>获取到路径的长度),在<code>@keframes</code>中的<code>100%</code>处设置<code>stroke-dashoffset</code>的值为<code>0</code>就可以实现线条自画的一个动画效果。</p> </blockquote> <p>如查我们不分<code>path</code>的长短就直接使用:</p> <pre><code>path { stroke-dasharray: 1000; stroke-dashoffset: 1000; animation: dash 2s linear both infinite; } @keyframes dash { to { stroke-dashoffset: 0; } } </code></pre> <p>看到的效果如下:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-path-animation-5.gif" alt="" /></p> <p>这样的效果并不是我们所要的呀。说实话有点拙逼。这个时候我们就需要借助<code>.getTotalLength()</code>神器,拿到每条<code>path</code>的长度。写个段JavaScript代码:</p> <pre><code>let pathLength = document.querySelectorAll('path'); let ulEl = document.createElement('ul') pathLength.forEach((item, index) =&gt; { let itemLength = Math.ceil(item.getTotalLength()) let liEl = document.createElement('li') liEl.textContent = `path-${index + 1}: ${itemLength}` ulEl.appendChild(liEl) }) document.body.appendChild(ulEl); </code></pre> <p>JavaScript写得比较拙,请大神指点。重要的是,我们每条<code>path</code>的长度拿到了,如下:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-path-animation-6.png" alt="" /></p> <p>有了对应的值,那就好办了,把对应路径的<code>stroke-dasharray</code>和<code>stroke-dashoffset</code>设置其最大值:</p> <pre><code>path { animation: dash 2s linear both infinite; &amp;:nth-child(1) { stroke-dasharray: 229; stroke-dashoffset: 229; } &amp;:nth-child(2) { stroke-dasharray: 86; stroke-dashoffset: 86; } &amp;:nth-child(3) { stroke-dasharray: 85; stroke-dashoffset: 85; } &amp;:nth-child(4) { stroke-dasharray: 707; stroke-dashoffset: 707; } &amp;:nth-child(5) { stroke-dasharray: 19; stroke-dashoffset: 19; } &amp;:nth-child(6) { stroke-dasharray: 17; stroke-dashoffset: 17; } &amp;:nth-child(7) { stroke-dasharray: 53; stroke-dashoffset: 53; } &amp;:nth-child(8) { stroke-dasharray: 7; stroke-dashoffset: 7; } &amp;:nth-child(9) { stroke-dasharray: 60; stroke-dashoffset: 60; } &amp;:nth-child(10) { stroke-dasharray: 44; stroke-dashoffset: 44; } &amp;:nth-child(11) { stroke-dasharray: 53; stroke-dashoffset: 53; } &amp;:nth-child(12) { stroke-dasharray: 7; stroke-dashoffset: 7; } &amp;:nth-child(13) { stroke-dasharray: 35; stroke-dashoffset: 35; } &amp;:nth-child(14) { stroke-dasharray: 14; stroke-dashoffset: 14; } &amp;:nth-child(15) { stroke-dasharray: 49; stroke-dashoffset: 49; } &amp;:nth-child(16) { stroke-dasharray: 14; stroke-dashoffset: 14; } } </code></pre> <p><img src="/sites/default/files/blogs/2018/1801/svg-path-animation-7.gif" alt="" /></p> <p>Oh,My God!还是不OK呀。接下继续对动画的<code>duration</code>和<code>delay</code>进行修正。借助Chrome的Animation调试工具来帮我们:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-path-animation-8.png" alt="" /></p> <p>把调好的时间,对应的添加到对应的<code>path</code>中,动效就调整了:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-path-animation-9.gif" alt="" /></p> <p>为了更好的控制动效果,添加个按钮来做动画的再次播放效果:</p> <pre><code>let aniEl = document.querySelector('svg') let aniElLast = document.querySelector('#last') let playEl = document.querySelector('button') // 给播放按钮添加点击事件 playEl.addEventListener("click", function(){ // 给svg元素添加类名play aniEl.classList.add('play'); }, false); aniElLast.addEventListener("webkitAnimationEnd", function(){ // 监听svg中最后一个路径path的动画结束事件,然后移除svg中的play类名 aniEl.classList.remove ('play'); }, false); </code></pre> <p>最终的效果如下:</p> <div style="margin-bottom: 20px;"><iframe id="dJgQMv" src="//codepen.io/airen/embed/dJgQMv?height=400&amp;theme-id=0&amp;slug-hash=dJgQMv&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>点击<code>play</code>按钮就能看到SVG线条自画的动画效果。</p> <h2>总结</h2> <p>看到这里,你应该明白,<code>stroke-dasharray</code>是用来设置每段虚线的长度。而<code>stroke-dashoffset</code>是用来设置移动的距离。所以实际上,<code>stroke-dashoffset</code>的大小,以及<code>stroke-dasharray</code>的大小,是要根据的自己的路径去填的。</p> <p>上面这些就是SVG的线条之美。当然发挥你的想象力,你做得一定会比我更好。上面示例中的CSS整得有点蛋疼,如果使用JavaScript根据<code>path</code>的长度来计算<code>animation-duration</code>和<code>animation-delay</code>可以更轻松一些。如果你感兴趣,不仿自己动手试试。</p> <p class="btns-zone"><a class="btn-demo" href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-line-animation-works.html"" target="_blank">上一节</a></p> <div class="blog-author media"><a class="media-object" href="http://www.xysjxj.com/quot;//weibo.com/韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权)"" target="_blank"><img src="/sites/default/files/blogs/author/airen.jpg"></a><div class="media-body"><h3 class="media-heading"><a href="http://www.xysjxj.com/quot;//weibo.com/韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权)"" target="_blank">大漠</a></h3><div class="media-des">常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等韦德1946手机版客户端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/book-comment.html"" target="_blank">图解CSS3:核心技术与案例实战</a>》。</div></div></div> <p>如需转载,烦请注明出处:<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/the-beauty-of-the-lines-break-lines-svg-animation.html"">https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/the-beauty-of-the-lines-break-lines-svg-animation.html</a></p> rel="nofollow" </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blogs/svg.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/svg-tutorial"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/647.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG之旅</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/585.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG Animation</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/29.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Animation</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/532.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Web动画</a></div></div></div> Wed, 17 Jan 2018 16:00:45 +0000 Airen 2348 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/creating-a-border-animation-effect-with-svg-and-css.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>Carl Philipe Brenner的网站上有一些非常有创意和微妙的动画效果,今天我想和大家一起探计一下如何在SVG线条上使用CSS的<code>transition</code>来实现一些有意思的边框动画效果。</p> <p><img src="/sites/default/files/blogs/2018/1801/BorderAnimationSVG.png" alt="" /></p> <p>今天我们来探索一下<a href="http://www.xysjxj.com/quot;//carlphilippebrenner.com/">Car" Philipe Brenner的网站</a>上一个微妙而有趣的动画效果。当鼠标经过网格元素时,会有一个微妙的动画发生 —— 网格元素变得透明,每条边有个顺时针的动画,创造了非常好的效果。这种效果是通过JS给<code>span</code>标签的宽或者高做了动画。我们待会会用SVG和CSS的<code>transition</code>来完成。注意,这个技术还是实验性的。</p> <p>首先,让我们来看看基本的概念,然后我们会朝着这个方向努力。</p> <blockquote> <p>请注意,我们将在SVG上使用CSS过渡,可能无法得到所有浏览器的支持。</p> </blockquote> <p>乍眼一看可能不明白这个效果是怎么完成的。我们先仔细看看上面的边就会发现,白色的边的宽度不断从右边往左边延伸,而一条稍微延时的边紧跟着一起移动。每条边都有这样的做法。看起来就像上面的边经过拐角移动到了左边,并以此类推。</p> <p>不用SVG也能完成这样的效果,甚至只用伪元素。但是我们想探索一下怎样用CSS而不是JavaScript来控制SVG。</p> <p>现在,来思考一下要怎么创建出这样的效果。我们可以改变矩形的<code>stroke-dashoffset</code>或者直接画线。我们尝试不用JavaScript的解决方案。我们发现,CSS过渡<code>stroke-dashoffset</code> 和 <code>stroke-dasharray</code>的值会触发很多BUG。所以我们要尝试不同的解决方案,利用线条和它们的动画,这在CSS里很容易理解和实现。这也给我们更多机会去探索不同的动画效果。</p> <p>我们将要使用的线的特别之处是,它们在这个动画里将有三种状态。它们是方盒边长的三倍,其中中间一截是与边等长的间隙。我们将通过设置<code>stroke-dashoffset</code>的值来实现与方盒的边等长。现在,这个动画实现的关键在于线的位置转换:</p> <p><img src="/sites/default/files/blogs/2018/1801/bordereffect_01.gif" alt="" /></p> <p>SVG与方盒大小一致,就不会看到超出虚线的部分。我们先完成第一条线:</p> <pre><code>&lt;div&gt; &lt;svg width="200" height="200"&gt; &lt;line x1="0" y1="0" x2="600" y2="0" /&gt; &lt;/svg&gt; &lt;/div&gt; </code></pre> <p>这个<code>div</code>长宽<code>200px</code>,和SVG一样。把SVG位置设为<code>absolute</code>,线宽度为<code>10</code>,<code>stroke-dasharray</code>为<code>200</code>。</p> <pre><code>body { display: flex; width: 100vw; height: 100vh; justify-content: center; align-items: center; background: #2098ce; } div { width: 200px; height: 200px; position: relative; overflow: hidden; background: #ddd; } svg { position: absolute; top: 0; left: 0; } svg line { stroke-width: 10; stroke: #000; fill: none; stroke-dasharray: 200; transition: transform .6s ease-out; } div:hover svg line { transform: translateX(-400px); } </code></pre> <p>当数鼠标悬浮在<code>div</code>上时,线也有一个过渡。我们要把线移动到它的三分之二处,所以要在<code>x</code>轴上移动到<code>-400px</code>处,你可以看看这个效果。因为<code>translate</code>不能在这里用百分比做单位,所以用<code>px</code>。</p> <div style="margin-bottom: 20px;"><iframe id="YYOdro" src="//codepen.io/airen/embed/YYOdro?height=400&amp;theme-id=0&amp;slug-hash=YYOdro&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>接着添加其余三条线,gif效果:</p> <p><img src="/sites/default/files/blogs/2018/1801/bordereffect_02.gif" alt="" /></p> <p>我们需要实现以下效果:线的第一部分移出方盒后,旁边的线的最后一部分移动进来,这将传进直线在转角处转弯的假象。来看看坐标系的定义:</p> <p><img src="/sites/default/files/blogs/2018/1801/bordereffect03.png" alt="" /></p> <p>左边的线的坐标是<code>(0,200)</code> 到 <code>(0,-400)</code>,底部的是<code>(200,200)</code> 到 <code>(-400,200)</code>,右边的是 <code>(200,0)</code> 到 <code>(200,600)</code>:</p> <pre><code>&lt;div&gt; &lt;svg width="200" height="200"&gt; &lt;line class="top" x1="0" y1="0" x2="600" y2="0"/&gt; &lt;line class="left" x1="0" y1="200" x2="0" y2="-400"/&gt; &lt;line class="bottom" x1="200" y1="200" x2="-400" y2="200"/&gt; &lt;line class="right" x1="200" y1="0" x2="200" y2="600"/&gt; &lt;/svg&gt; &lt;/div&gt; </code></pre> <p>给每条线加上不同的<code>hover</code>效果:</p> <pre><code>div:hover svg line.top { transform: translateX(-400px); } div:hover svg line.bottom { transform: translateX(400px); } div:hover svg line.left { transform: translateY(400px); } div:hover svg line.right { transform: translateY(-400px); } </code></pre> <div style="margin-bottom: 20px;"><iframe id="MrqLjz" src="//codepen.io/airen/embed/MrqLjz?height=400&amp;theme-id=0&amp;slug-hash=MrqLjz&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>现在方盒大小改为<code>300 x 460</code>,再给它添加一些内容:</p> <pre><code>&lt;div class="box"&gt; &lt;svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"&gt; &lt;line class="top" x1="0" y1="0" x2="900" y2="0"/&gt; &lt;line class="left" x1="0" y1="460" x2="0" y2="-920"/&gt; &lt;line class="bottom" x1="300" y1="460" x2="-600" y2="460"/&gt; &lt;line class="right" x1="300" y1="0" x2="300" y2="1380"/&gt; &lt;/svg&gt; &lt;h3&gt;D&lt;/h3&gt; &lt;span&gt;2012&lt;/span&gt; &lt;span&gt;Broccoli, Asparagus, Curry&lt;/span&gt; &lt;/div&gt; </code></pre> <p>为了实现Carl Philipe Brenner的网站上的效果,我们还要添加颜色过渡效果、盒子阴影等:</p> <pre><code>body { display: flex; width: 100vw; height: 100vh; justify-content: center; align-items: center; background: #2098ce; } .box { width: 300px; height: 460px; position: relative; background: rgba(255,255,255,1); cursor: pointer; color: #2c3e50; box-shadow: inset 0 0 0 3px #2c3e50; transition: background 0.4s 0.5s; } .box:hover { background: rgba(255,255,255,0); transition-delay: 0s; } </code></pre> <p>给文字加上样式:</p> <pre><code>.box h3 { font-family: "Ruthie", cursive; font-size: 180px; line-height: 370px; margin: 0; font-weight: 400; width: 100%; } .box span { display: block; font-weight: 400; text-transform: uppercase; letter-spacing: 1px; font-size: 13px; padding: 5px; } .box h3, .box span { transition: color 0.4s 0.5s; } .box:hover h3, .box:hover span { color: #fff; transition-delay: 0s; } </code></pre> <p>给SVG和线条添加样式:</p> <pre><code>.box svg { position: absolute; top: 0; left: 0; } .box svg line { stroke-width: 3; stroke: #ecf0f1; fill: none; transition: all .8s ease-in-out; } </code></pre> <p>给线的过渡加上延时:</p> <pre><code>.box:hover svg line { transition-delay: 0.1s; } </code></pre> <p>之前我们定义的<code>stroke-dasharray</code>只有一个值,但是现在要因尺寸变化而修改:</p> <pre><code>.box svg line.top, .box svg line.bottom { stroke-dasharray: 330 240; } .box svg line.left, .box svg line.right { stroke-dasharray: 490 400; } </code></pre> <p>如果你尝试这些值,你就能看到这些线条不同的显示效果。</p> <p>最后,我们要个<code>hover</code>过渡设置相应的值。因为现在元素是<code>300px</code>宽,所以水平线条改为<code>900px</code>,竖线同理改变:</p> <pre><code>.box:hover svg line.top { transform: translateX(-600px); } .box:hover svg line.bottom { transform: translateX(600px); } .box:hover svg line.left { transform: translateY(920px); } .box:hover svg line.right { transform: translateY(-920px); } </code></pre> <p>大功告成。希望能通过这些效果激发你的创意,实现更多的效果~</p> <div style="margin-bottom: 20px;"><iframe id="qpMgmd" src="//codepen.io/airen/embed/qpMgmd?height=500&amp;theme-id=0&amp;slug-hash=qpMgmd&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="500" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <blockquote> <p>本文根据<a href="http://www.xysjxj.com/quot;//tympanus.net/codrops/author/crnacura/">@Mar" Lou</a>的《<a href="//tympanus.net/codrops/2014/02/26/creating-a-border-animation-effect-with-svg-and-css/">Creating a Border Animation Effect with SVG and CSS</a>》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:<a href="//tympanus.net/codrops/2014/02/26/creating-a-border-animation-effect-with-svg-and-css/">https://tympanus.net/codrops/2014/02/26/creating-a-border-animation-effect-with-svg-and-css/</a>。</p> </blockquote> <div class="blog-author media"><a class="media-object" href="http://www.xysjxj.com/quot;//weibo.com/韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权)"" target="_blank"><img src="/sites/default/files/blogs/author/airen.jpg"></a><div class="media-body"><h3 class="media-heading"><a href="http://www.xysjxj.com/quot;//weibo.com/韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权)"" target="_blank">大漠</a></h3><div class="media-des">常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等韦德1946手机版客户端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/book-comment.html"" target="_blank">图解CSS3:核心技术与案例实战</a>》。</div></div></div> <p>如需转载,烦请注明出处:<a href="//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/creating-a-border-animation-effect-with-svg-and-css.html">https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/creating-a-border-animation-effect-with-svg-and-css.html</a></p> </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/translations"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">译文</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/svg-tutorial"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/585.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG Animation</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/29.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Animation</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/532.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Web动画</a></div></div></div> Tue, 16 Jan 2018 16:00:18 +0000 Airen 2347 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-line-animation-works.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>对于SVG路径动画,我相信大家都看到过这样的动效:一条线就像它自己画自己。非常的酷。@Jake Archibald是这项技巧的先驱,他在自己的博客写了<a href="http://www.xysjxj.com/quot;//jakearchibald.com/2013/animated-line-drawing-svg/">一篇非常好的文章</a>来介绍SVG的线条动画是如何实现的。@Bria" Suda也在24 Ways网站上<a href="http://www.xysjxj.com/quot;//24ways.org/2013/animating-vectors-with-svg/">讨论过这种技术</a>。Polygon使用它在一篇设计方面的文章里创建出了<" href="http://www.xysjxj.com/quot;//product.voxmedia.com/post/68085482982/polygon-feature-design-svg-animations-for-fun-and">非常神奇的效果</a>。Codrops也有很多<" href="http://www.xysjxj.com/quot;//tympanus.net/Development/SVGDrawingAnimation/">非常酷的案例</a>。</p>" <p>在这篇文章中,我并没有什么要补充的,只是想把这种技术阐述的更简易些。所以,在这里我用我的方式把这种技术再次向大家阐述一遍。</p> <h2>你有一个SVG图形</h2> <p>首先你有一个SVG图形,如下图所示:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-shape.png" alt="SVG图形" /></p> <p>事实上这就是一个路径图形(SVG的路径图)。咱们可以使用<a href="http://www.xysjxj.com/quot;//en.wikipedia.org/wiki/Comparison_of_vector_graphics_editors">任何制作矢量图的软件</a>绘制这样的图形,比如韦德1946手机版客户端人员常用的:</p>" <p><img src="/sites/default/files/blogs/2018/1801/svg-shape-1.png" alt="SVG图形" /></p> <p>除些之外,还可以使用在线的绘制矢量图的Web运用,比如<a href="http://www.xysjxj.com/quot;//app.inker.co/">inker</a>。我个人比较喜欢使用Sketch软件。如比我们可以在Sketch上制作一个类似于上图的路径图:</p>" <p><img src="/sites/default/files/blogs/2018/1801/svg-shape-2.gif" alt="SVG图形" /></p> <h2>这个图形必须要一个<code>stroke</code>属性</h2> <p>上面的图导出来的<code>path.svg</code>使用编辑器打开,然后清理一下无用的代码,看到的就像下面这样:</p> <pre><code>&lt;svg width="318px" height="272px" viewBox="0 0 318 272" &gt; &lt;path d="M39.5,87.5 C45,81 48.9183868,9.33956041 94.5,4 C140.081613,-1.33956041 104,75.5 205,69.5 C306,63.5 342,112 292,137.5 C242,163 314.5,213.5 302,236 C289.5,258.5 224,193 204.5,203.5 C185,214 160.5,289.5 94.5,262.5 C28.5,235.5 102,231 83.5,188 C65,145 7.5,144.5 4,104.5 C0.5,64.5 34,94 39.5,87.5 Z" class="path" stroke="#000000" stroke-width="6" fill="none"&gt;&lt;/path&gt; &lt;/svg&gt; </code></pre> <p>这个路径<code>path</code>必须要有一个<code>stroke</code>属性。通过<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-stroke.html">上一节的学习</a>,我们知道<code>stroke</code>属性用来设置路径的描边颜色,而<code>stroke-width</code>是设置路径描边的粗细。上面的代码放到Web中,看到的效果如下:</p>" <div style="margin-bottom: 20px; padding: 2px; border: 1px solid #ccc;display: flex; justify-content: center; align-items: center; width: 100%;"> <svg width="318px" height="272px" viewBox="0 0 318 272" > <path d="M39.5,87.5 C45,81 48.9183868,9.33956041 94.5,4 C140.081613,-1.33956041 104,75.5 205,69.5 C306,63.5 342,112 292,137.5 C242,163 314.5,213.5 302,236 C289.5,258.5 224,193 204.5,203.5 C185,214 160.5,289.5 94.5,262.5 C28.5,235.5 102,231 83.5,188 C65,145 7.5,144.5 4,104.5 C0.5,64.5 34,94 39.5,87.5 Z" class="path" stroke="#000000" stroke-width="6" fill="none"></path> </svg> </div> <h2>线条可以是虚线</h2> <p>线条(路径)可以使用Sketch制作图软件制作,也可以直接来编码,只不过编辑会比较痛苦,比如上面的代码,那么多的数字和字母的配合,我想你和我一会,感觉要疯了。不过你了解了<code>path</code>相关的知识,那绘制一条像上图的路径(图形)还是可能的。但这里不阐述这方面的,如果感兴趣,可以阅读<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-path.html">SVG中<code>path</code>相关的知识</a>。</p>" <p>在SVG中,可以通过<code>stroke-dasharray</code>来设置路径为虚线,除了在使用这个属性之外,还可以使用CSS来设置,让它变成一个虚线的形式。</p> <pre><code>.path { stroke-dasharray: 20 } </code></pre> <p>效果如下:</p> <div style="margin-bottom: 20px; padding: 2px; border: 1px solid #ccc;display: flex; justify-content: center; align-items: center; width: 100%;"> <svg width="318px" height="272px" viewBox="0 0 318 272" > <path stroke-dasharray="20" d="M39.5,87.5 C45,81 48.9183868,9.33956041 94.5,4 C140.081613,-1.33956041 104,75.5 205,69.5 C306,63.5 342,112 292,137.5 C242,163 314.5,213.5 302,236 C289.5,258.5 224,193 204.5,203.5 C185,214 160.5,289.5 94.5,262.5 C28.5,235.5 102,231 83.5,188 C65,145 7.5,144.5 4,104.5 C0.5,64.5 34,94 39.5,87.5 Z" class="path" stroke="#000000" stroke-width="6" fill="none"></path> </svg> </div> <p>这个示例让虚线里的每个小线段长度为<code>20px</code>。</p> <h2>可以让虚线小段长度变得更长</h2> <p>我们只需要把<code>stroke-dasharray</code>的值设的更大,那么虚线里的每段就会变得更长,比如把上例的<code>20px</code>换成<code>100px</code>:</p> <pre><code>.path { stroke-dasharray: 100; } </code></pre> <p>你将看到的效果将是这样:</p> <div style="margin-bottom: 20px; padding: 2px; border: 1px solid #ccc;display: flex; justify-content: center; align-items: center; width: 100%;"> <svg width="318px" height="272px" viewBox="0 0 318 272" > <path stroke-dasharray="100" d="M39.5,87.5 C45,81 48.9183868,9.33956041 94.5,4 C140.081613,-1.33956041 104,75.5 205,69.5 C306,63.5 342,112 292,137.5 C242,163 314.5,213.5 302,236 C289.5,258.5 224,193 204.5,203.5 C185,214 160.5,289.5 94.5,262.5 C28.5,235.5 102,231 83.5,188 C65,145 7.5,144.5 4,104.5 C0.5,64.5 34,94 39.5,87.5 Z" class="path" stroke="#000000" stroke-width="6" fill="none"></path> </svg> </div> <h2>使用<code>stroke-dashoffset</code>设置线条的偏移量</h2> <p>在SVG中,可在以<code>path</code>元素中设置<code>stroke-dashoffset</code>的值,来控制SVG路径虚线的间的偏移量,这样会导致虚线里的小线段的位置发生移动。当然,也可以在CSS中设置:</p> <pre><code>.path { stroke-dashoffset: 1000; } </code></pre> <p>我们在浏览器的代码检查器中,不断的修改<code>stroke-dashoffset</code>的值,你将看到的效果如下图:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-shape-3.gif" alt="SVG图形" /></p> <p>当然,配合CSS的<code>animation</code>我们就可以看到一个简单的线条动画。</p> <pre><code>.path { stroke-dasharray: 100; animation: dash 5s linear infinite; } @keyframes dash { to { stroke-dashoffset: 1000; } } </code></pre> <p>效果如下:</p> <div style="margin-bottom: 20px; padding: 2px; border: 1px solid #ccc;display: flex; justify-content: center; align-items: center; width: 100%;"> <svg width="318px" height="272px" viewBox="0 0 318 272" class="svgDemo"> <style type="text/css"> .svgDemo .path { stroke-dasharray: 100; animation: dash 5s linear infinite; } @keyframes dash { to { stroke-dashoffset: 1000; } } </style> <path stroke-dasharray="100" d="M39.5,87.5 C45,81 48.9183868,9.33956041 94.5,4 C140.081613,-1.33956041 104,75.5 205,69.5 C306,63.5 342,112 292,137.5 C242,163 314.5,213.5 302,236 C289.5,258.5 224,193 204.5,203.5 C185,214 160.5,289.5 94.5,262.5 C28.5,235.5 102,231 83.5,188 C65,145 7.5,144.5 4,104.5 C0.5,64.5 34,94 39.5,87.5 Z" class="path" stroke="#000000" stroke-width="6" fill="none"></path> </svg> </div> <p>想像一下,当虎线的小线条足够长,超过图形的整个线条长度时。将会是一个什么样子呢?</p> <p>那怎么知道自己绘制的线条有多长呢?可以通过<code>getTotalLength()</code>方法来获取。比如上面的示例:</p> <pre><code>document.querySelector('.path').getTotalLength() // =&gt; 1038.357666015625 </code></pre> <p>也就是说上面示例的线条(路径)的总长度是<code>1038.357666015625px</code>。如果我们把<code>stroke-dashoffset</code>的值设置超过这个长度,比如我们设置为<code>1039</code>,将会是什么样子呢?还是能过浏览器检测器来给大家演示:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-shape-4.gif" alt="SVG图形" /></p> <p>这个时候很有意思了。把上面的动画再做一下调整:</p> <pre><code>.path { stroke-dasharray: 1039; stroke-dashoffset: 1039; animation: dash 8s linear both; } @keyframes dash { to { stroke-dashoffset: 0; } } </code></pre> <p>效果如下:</p> <div style="margin-bottom: 20px; padding: 2px; border: 1px solid #ccc;display: flex; justify-content: center; align-items: center; width: 100%;"> <svg width="318px" height="272px" viewBox="0 0 318 272" class="svgDemo2"> <style type="text/css"> .svgDemo2 .path { stroke-dasharray: 1039; stroke-dashoffset: 1039; animation: dash2 18s linear both; } @keyframes dash2 { to { stroke-dashoffset: 0; } } </style> <path stroke-dasharray="1039" d="M39.5,87.5 C45,81 48.9183868,9.33956041 94.5,4 C140.081613,-1.33956041 104,75.5 205,69.5 C306,63.5 342,112 292,137.5 C242,163 314.5,213.5 302,236 C289.5,258.5 224,193 204.5,203.5 C185,214 160.5,289.5 94.5,262.5 C28.5,235.5 102,231 83.5,188 C65,145 7.5,144.5 4,104.5 C0.5,64.5 34,94 39.5,87.5 Z" class="path" stroke="#000000" stroke-width="6" fill="none"></path> </svg> </div> <p>在CSS中,可以把<code>animation</code>属性中的<code>animation-fill-mode</code>设置成<code>forwards</code>或者<code>both</code>,这样整个动画就会在它的最终状态停止。</p> <blockquote> <p>有关于<code>animation-fill-mode</code>的详细介绍,可以阅读早前整理的相关伟德1946手机版《<a href="//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/css3/css-animation-fill-mode-property.html">你所不知道的<code>animation-fill-mode</code>细节</a>》和《<a href="//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/css3/understanding-css-animation-fill-mode-property.html">理解<code>animation-fill-mode</code>属性</a>》。</p> </blockquote> <p>为了更好的理解SVG的<code>stroke</code>、<code>stroke-dasharray</code>和<code>stroke-dashoffset</code>相关的知识。将上面的几个属性结合Vue写了一个简单的工具,可以通过修改对应的值。更能帮助大家理解SVG线条动画的工作原理。</p> <div style="margin-bottom: 20px;"><iframe id="LerXYd" src="//codepen.io/airen/embed/LerXYd?height=400&amp;theme-id=0&amp;slug-hash=LerXYd&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <h2>总结</h2> <p>这篇文章一步一步带着大家怎么理解SVG的线条动画工作的原理。其实要实现一个线条自画的动效很简单,首先通过绘制路径的工具拿到所需线条的路径。然后通过<code>stroke-dasharray</code>设置线条为虚线,利用CSS的<code>animation</code>来改变<code>stroke-dashoffset</code>的值,创建一个线段移动的效果。如果将<code>stroke-dasharray</code>和<code>stroke-dashoffset</code>值设置为路径的长度(最好是大于其长度,可以通过<code>.getTotalLength()</code>获取到路径的长度),在<code>@keframes</code>中的<code>100%</code>处设置<code>stroke-dashoffset</code>的值为<code>0</code>就可以实现线条自画的一个动画效果。</p> <p>是不是很简单呀。这就是上一节所说的SVG的线条之美。其实不仅仅这些,后续还会继续围绕SVG线条的动画展开深入介绍,以及实战。希望大家喜欢,更希望对大家有所帮助。</p> <blockquote> <p>特别声明:文章的思路来自于<a href="//css-tricks.com/author/chriscoyier/">@CHRIS COYIER</a>在2014年发布的一篇伟德1946手机版《<a href="//css-tricks.com/svg-line-animation-works/">https://css-tricks.com/svg-line-animation-works/</a>》。</p> </blockquote> <p class="btns-zone"><a class="btn-demo" href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-stroke.html"" target="_blank">上一节</a><a class="btn-demo" href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/the-beauty-of-the-lines-break-lines-svg-animation.html"" target="_blank">下一节</a></p> <div class="blog-author media"><a class="media-object" href="http://www.xysjxj.com/quot;//weibo.com/韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权)"" target="_blank"><img src="/sites/default/files/blogs/author/airen.jpg"></a><div class="media-body"><h3 class="media-heading"><a href="http://www.xysjxj.com/quot;//weibo.com/韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权)"" target="_blank">大漠</a></h3><div class="media-des">常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等韦德1946手机版客户端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/book-comment.html"" target="_blank">图解CSS3:核心技术与案例实战</a>》。</div></div></div> <p>如需转载,烦请注明出处:<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-line-animation-works.html"">https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-line-animation-works.html</a></p> </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blogs/svg.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/svg-tutorial"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/647.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG之旅</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/585.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG Animation</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/29.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Animation</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/532.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Web动画</a></div></div></div> Sat, 13 Jan 2018 17:04:30 +0000 Airen 2346 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com w3cplus_引领web前沿,打造前端精品教程 - 韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权) https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-animation-guide.html <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="content:encoded"><p>任何有开发经验的韦德1946手机版客户端工程师都会考虑到不成体系的设备生态所带来的挑战。设备间不同的屏幕尺寸、分辨率和比例使得产品难以提供一致的体验,对于那些对产品有着像素级完美追求的人这种体验差异尤其显著!SVG(可缩放的矢量图形)完美地解决了上文中提到的部分问题。尽管 SVG 有它的局限性,但是在某些场景下是非常有用的,如果你有一个好的设计团队,你也可以基于SVG创建一些震撼的视觉体验,而不必担心给浏览器带来过重的渲染负担或阻碍页面的加载时间。</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-animation-1.png" alt="" /></p> <p>在过去的几个月里,我一直在做一个大量使用了 SVG 及其动画效果的项目。在本文中,我将介绍如何使用SVG及其动画技术为你的 Web 韦德1946手机版客户端开发带来一些新鲜的体验。</p> <h2>可缩放矢量图形</h2> <p>SVG 是一种基于 XML 文档的图片格式,所以大部分情况其特性表现类似于 HTML。它为许多常见的几何图形定义了不同的元素,通过组合这些不同的形状元素可以生成 SVG 二维图形。<a href="http://www.xysjxj.com/quot;//www.w3.org/TR/SVG/">SV" 规范</a>是由万维网联盟(W3C)于1999制定的标准,所有的主流浏览器目前均支持了 <a href="http://www.xysjxj.com/quot;//caniuse.com/#search=svg">SV" 的渲染</a>。由于 SVG 图形是 XML 文档,因此 Web 浏览器提供的 DOM 相关的 API,同样可作用于与 SVG 图形的交互。</p> <h2>SVG 路径</h2> <p>如果要说出 SVG 中最强大的元素,毫无疑问是 <strong><code>&lt;path&gt;</code></strong> (路径元素)。 路径元素是一个可以构建出你所能想象的几乎任何高级的2D图形的基本形状。路径元素通过一系列绘图命令来生效,它非常类似于1967年的 Logo 编程语言,不同的是它只是更现代化的,为复杂花哨的图形而设计的。这些绘图命令如下图所示,被写在路径元素的 <strong><code>d</code></strong> 属性中 :</p> <pre><code>&lt;!-- A right-angled triangle --&gt; &lt;path d="M10 10 L75 10 L75 75 Z" /&gt; </code></pre> <p>你可以把它想象成一支虚拟的画笔在屏幕上作画,而路径元素的 <code>d</code> 属性中的绘图命令控制着画笔的走向。上图的示例中,画笔一开始移动到起点坐标 <code>(10, 10)</code> (<code>M10 10</code>),以 <code>(75, 10)</code> 为终点画直线(<code>L75 10</code>),接着又画一条直线至 <code>(75, 75)</code> (<code>L75 75</code>),最后的 <code>Z</code> 表示画笔回到起点坐标以闭合路径。</p> <p>使用一些其他的绘图命令,例如绘圆弧(<strong><code>A</code></strong>)、二次贝塞尔曲线(<strong><code>Q</code></strong>)、三次贝塞尔曲线(<strong><code>C</code></strong>)等等,你可以在 SVG 中创建出很多组合的形状和矢量图形。</p> <blockquote> <p>你可以点击这里了解更多关于路径元素的知识:</p> <ul> <li><a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-path.html">SVG之旅:路径</a></li>" <li><a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/deep-understand-svg-path-bezier-curves-command.html">深度掌握SVG路径<code>path</code>的贝塞尔曲线指令</a></li>" <li><a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/base-shapes-to-path.html">SVG基本形状<code>path</code>路径置换</a></li>" </ul> </blockquote> <h2>SVG 路径与 CSS</h2> <p>也许你会问:“好吧我知道 Paths 很强大,但是我怎样才能对它做路径动画呢?”。</p> <p>因此我们第一步需要利用到 SVG 的两个属性:<code>stroke-dasharray</code> 和 <code>stroke-dashoffset</code> 。</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-animation-2.jpg" alt="" /></p> <p><a href="http://www.xysjxj.com/quot;//developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray"><code>stroke-dasharray</code></a>" 属性可以控制图案描边路径的样式,如果你并不想用连续的直线去绘制路径,而希望通过一些不同样式的虚线,你就可以使用这个属性。</p> <p>由于 SVG 图形其实也是浏览器 DOM 的组成部分,因此 <code>stroke-dasharray</code> 作为一个控制外观的属性,也可以直接用作一个 CSS 样式属性,达到同样的设置效果。</p> <p>类似的,<a href="http://www.xysjxj.com/quot;//developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset"><code>stroke-dashoffset</code></a>" 属性(虚线在原路径下的偏移量)也同样可以使用 CSS 来进行设置。</p> <p>这两个属性的组合使用可以生成 SVG 路径动画,给人一种图案的轮廓线逐渐拟合的视觉感受。</p> <p>例如下面这个二次贝塞尔曲线的例子:</p> <p><img src="/sites/default/files/blogs/2018/1801/svg-animation-3.png" alt="" /></p> <pre><code>&lt;path fill="transparent" stroke="#000000" stroke-width="5" d="M10 80 Q 77.5 10, 145 80 T 280 80" class="path"&gt;&lt;/path&gt; </code></pre> <p>为了平稳流畅地绘制出这个路径,首先我们需要通过 <code>stroke-dasharray</code> 属性设置虚线段的长度,将 <code>stroke-dasharray</code> 属性的值设为该路径的长度。这样的话就将虚线的每一段 <code>dash</code> 和 <code>gap</code> 的长度等于整段路径的长。</p> <p>下一步我们需要使用 <code>stroke-dashoffset</code> 属性将虚线的偏移量设置为 <code>0</code>,此时我们看到的路径描边就是没有间断的连续曲线(实际上看到的是虚线段的第一段,前面已经设置每一虚线段的长度等于该曲线的长)。通过设置虚线偏移量等于曲线的长度,那该曲线恰好“消失”(实际上看到的是虚线段的一段间隙)。</p> <p>通过 <code>stroke-dashoffset</code> 属性,同时结合 CSS3 的 <code>animation</code>,你可以让该曲线一点点的出现在屏幕上,这就是 SVG 路径动画的原理。</p> <pre><code>&lt;svg width="300px" height="175px" version="1.1"&gt; &lt;path fill="transparent" stroke="#000000" stroke-width="4" d="M10 80 Q 77.5 10, 145 80 T 280 80" class="path"&gt;&lt;/path&gt; &lt;/svg&gt; svg { width: 300px; display: block; position: absolute; .path { stroke-dasharray: 320; stroke-dashoffset: 0; animation: dash 1s linear; } @keyframes dash { from { stroke-dashoffset: 320; } to { stroke-dashoffset: 0; } } } </code></pre> <p>你可以点击<a href="http://www.xysjxj.com/quot;//codepen.io/toptalblog/pen/MvjWEz">这里</a>查" CODEPEN 上的 <a href="http://www.xysjxj.com/quot;//codepen.io/toptalblog/pen/MvjWEz">DEMO</a>。</p>" <div style="margin-bottom: 20px;"><iframe id="XVYPQv" src="//codepen.io/airen/embed/XVYPQv?height=400&amp;theme-id=0&amp;slug-hash=XVYPQv&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>可以看到,我们只是改变了虚线的偏移来让虚线段的部分一点一点地出现。</p> <p>运用相同的原理来设置多条路径的动画,可以得到更炫酷的效果:</p> <pre><code>&lt;svg width="300px" height="175px" version="1.1"&gt; &lt;path fill="transparent" stroke="#000000" stroke-width="4" d="M10 80 Q 77.5 10, 145 80 T 280 80" class="path"&gt;&lt;/path&gt; &lt;path fill="transparent" stroke="#FF2851" stroke-width="4" d="M10 80 Q 77.5 10, 145 80 T 280 80" class="line2"&gt;&lt;/path&gt; &lt;path fill="transparent" stroke="#000000" stroke-width="4" d="M10 80 Q 77.5 10, 145 80 T 280 80" class="line1"&gt;&lt;/path&gt; &lt;/svg&gt; svg { width: 300px; display: block; position: absolute; } svg .line1 { stroke-dasharray: 340; stroke-dashoffset: 40; animation: dash 1.5s linear alternate infinite; } svg .line2 { stroke-dasharray: 320; stroke-dashoffset: 320; animation: dash2 1.5s linear alternate infinite; } @keyframes dash { from { stroke-dashoffset: 360; } to { stroke-dashoffset: 40; } } @keyframes dash2 { from { stroke-dashoffset: 280; } to { stroke-dashoffset: -40; } } </code></pre> <p>你可以点击<a href="http://www.xysjxj.com/quot;//codepen.io/toptalblog/pen/eEgPqW">这里</a>查" CODEPEN 上的 <a href="http://www.xysjxj.com/quot;//codepen.io/toptalblog/pen/eEgPqW">DEMO</a>。</p>" <div style="margin-bottom: 20px;"><iframe id="goKdNX" src="//codepen.io/airen/embed/goKdNX?height=400&amp;theme-id=0&amp;slug-hash=goKdNX&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>上面在 SVG 中画了<code>3</code>条路径:其中一条是固定的黑色曲线, 有一条沿着路径移动的红色曲线,后面跟着另一条黑色曲线。</p> <p><code>stroke-dasharray</code> 和 <code>stroke-dashoffset</code> 是创造大量 SVG 路径动画所要用到的两个重要属性,你可以点击<a href="http://www.xysjxj.com/quot;//codepen.io/airen/full/vprOaa/">这里</a>(一个方便的小工具)来体会这两个属性。</p>" <div style="margin-bottom: 20px;"><iframe id="vprOaa" src="//codepen.io/airen/embed/vprOaa?height=400&amp;theme-id=0&amp;slug-hash=vprOaa&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <blockquote> <p>有关于<code>stroke-dasharray</code> 和 <code>stroke-dashoffset</code>相关的介绍<a href="http://www.xysjxj.com/quot;//www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com/svg/svg-stroke.html"">可以点击这里阅读</a>。</p> </blockquote> <h2>沿 SVG 路径的动画对象</h2> <p>通过 SVG 和 CSS,我们可以让一个对象或者元素沿着 SVG 路径做一些动效,过程中我们会用到两个属性:</p> <ul> <li><a href="http://www.xysjxj.com/quot;//developer.mozilla.org/en-US/docs/Web/CSS/offset-path"><code>offset-path</code></a>:<code>offset-path</code>" 是一个 CSS 属性,它表示元素的运动路径; </li> <li><a href="http://www.xysjxj.com/quot;//developer.mozilla.org/en-US/docs/Web/CSS/offset-distance"><code>offset-distance</code></a>:同样是一" CSS 属性,定义了元素在路径上运动的距离,单位是数值或百分比;</li> </ul> <p>通过组合使用这两个属性,你可以非常容易地创建出类似下面的动画:</p> <pre><code>&lt;svg width="300px" height="175px" version="1.1"&gt; &lt;path fill="transparent" stroke="#888888" stroke-width="1" d="M10 80 Q 77.5 10, 145 80 T 280 80" class="path"&gt;&lt;/path&gt; &lt;/svg&gt; &lt;div class="ball"&gt;&lt;/div&gt; svg { width: 300px; display: block; position: absolute; } .ball { width: 10px; height: 10px; background-color: red; border-radius: 50%; offset-path: path('M10 80 Q 77.5 10, 145 80 T 280 80'); offset-distance: 0%; animation: red-ball 2s linear alternate infinite; } @keyframes red-ball { from { offset-distance: 0%; } to { offset-distance: 100%; } } </code></pre> <p>你可以点击<a href="http://www.xysjxj.com/quot;//codepen.io/toptalblog/pen/qXRJeY">这里</a>查" CODEPEN 上的 <a href="http://www.xysjxj.com/quot;//codepen.io/toptalblog/pen/qXRJeY">DEMO</a>。</p>" <div style="margin-bottom: 20px;"><iframe id="BJVqjV" src="//codepen.io/airen/embed/BJVqjV?height=400&amp;theme-id=0&amp;slug-hash=BJVqjV&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>上面我们让一个 <code>div.ball</code> 的元素动了起来,同样的我们可以对任何元素(<code>div</code> , <code>image</code> , <code>text</code> ...)做这种路径动画。在这个例子中我们简单的用 <code>offset-path</code> 画出了元素的运动路径,然后用 <code>offset-distance</code> 控制元素在路径上的运动距离从 <code>0%</code> 到<code>100%</code>。</p> <h2>使用 JavaScript 做 SVG 动画</h2> <p>以上如果还不足以满足你的动画需求,你可以考虑借助 JavaScript。</p> <p>使用 JavaScript 对 SVG 元素做动画与对 DOM 元素做动画相似。然而我们可以更容易地实现上面提到的动画效果。之前,我们需要将路径长度硬编码在 CSS 中。借助 JavaScript 的 <code>path.getTotalLength()</code> 函数可以获取 DOM 上路径的长度,你可以点击<a href="http://www.xysjxj.com/quot;//jakearchibald.com/2013/animated-line-drawing-svg/">这里</a>了解更多。除此之外,有很多第三方库可以帮助你十分容易地制" SVG 动画。</p> <p><a href="http://www.xysjxj.com/quot;//snapsvg.io/">Snap.svg</a>" 不仅可以使 JavaScript 绘制 SVG 图形变得更容易,它的使用也异常简单,只需要调用 <code>.animate({})</code> 这个API即可。 另外一个库 <a href="http://www.xysjxj.com/quot;//anime-js.com/">anime.js</a>" 通过几行代码就可以让一个元素沿着 SVG 路径运动,点击<a href="http://www.xysjxj.com/quot;//codepen.io/ainalem/pen/VWJRav">这里</a>" 常看更多 DEMO。</p> <div style="margin-bottom: 20px;"><iframe id="dJKgXW" src="//codepen.io/airen/embed/dJKgXW?height=600&amp;theme-id=0&amp;slug-hash=dJKgXW&amp;default-tab=result&amp;user=airen" scrolling="no" frameborder="0" height="600" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="width: 100%; overflow: hidden;"></iframe></div> <p>如果你需要一个本身已经为你做了大部分操作来生成复杂的动画的库,<a href="http://www.xysjxj.com/quot;//maxwellito.github.io/vivus/">Vivus</a>" 是比较适合你的,它采取了一种不同的调用方式,仅需要通过配置项的方式去生成 SVG 路径动画。你只需要用你想作用的 SVG 元素的 <code>id</code> 来新建一个 Vivus 对象,然后就交给 Vivus 来处理剩下的事情。</p> <h2>拓展阅读</h2> <ul> <li>更深入了解 SVG 动画可以阅读这篇文章:<a href="https://css-tricks.com/video-screencasts/135-three-ways-animate-svg/">three ways to animate SVG</a> ;</li> <li>本文中没有涉及的关于 SMIL(Synchronized Multimedia Integration Language)的内容可以阅读:<a href="https://css-tricks.com/guide-svg-animations-smil/">A Guide to SVG Animations (SMIL)</a></li> </ul> <blockquote> <p>本文转载自:<a href="http://www.xysjxj.com/quot;//www.zcfy.cc">众成翻译</a>" 译者:<a href="http://www.xysjxj.com/quot;//www.zcfy.cc/@licao404">@Gardo" Lee</a> 链接:<a href="//www.zcfy.cc/article/4357">http://www.zcfy.cc/article/4357</a> rel="nofollow" 原文:<a href="//www.toptal.com/front-end/svg-animation-guide">https://www.toptal.com/front-end/svg-animation-guide</a></p> rel="nofollow" <p>原文链接:<a href="https://www.toptal.com/front-end/svg-animation-guide">//www.toptal.com/front-end/svg-animation-guide</a></p> rel="nofollow" <p>作者:<a href="http://www.xysjxj.com/quot;//www.toptal.com/resume/juan-calou">@JUA" CALOU</a></p> </blockquote> </div></div></div><div class="field field-name-field-taxonomy field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/624.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">转载</a></div></div></div><div class="field field-name-field-blog-tag field-type-taxonomy-term-reference field-label-hidden"><div class="field-items"><div class="field-item even"><a href="http://www.xysjxj.com/quot;/svg-tutorial"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/585.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SVG Animation</a></div><div class="field-item even"><a href="http://www.xysjxj.com/quot;/blog/tags/29.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Animation</a></div><div class="field-item odd"><a href="http://www.xysjxj.com/quot;/blog/tags/532.html"" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Web动画</a></div></div></div> Sat, 13 Jan 2018 14:36:10 +0000 Airen 2345 at https://www.韦德1946手机版客户端_韦德娱乐平台_伟德1946手机版(官方唯一授权).com