今天小编跟大家讲解下有关纯 CSS 实现大量小块儿绘制 ,相信小伙伴们对这个话题应该有所关注吧,小编也收集到了有关纯 CSS 实现大量小块儿绘制 的相关资料,希望小伙伴们看了有所帮助。
现在做的项目是公司内部全部组要用的 viewer 库. Viewer 需要的功能非常的多,其中的一个就是需要提供一些常用的绘图API功能, 比如用户鼠标移动画箭头,画圈圈,高光选中文本等等。
挑战目前遇到的挑战就是在 canvas, svg, dom + css 之间如何选择的问题,canvas 绘图的方案已经有了成品,我们可以直接拿过来添加到现有的 Viewer 上面。但是基于以下考虑,主要用哪种技术迟迟不能下定论。
Canvas 纠结点:1) 各部门合作问题,如果采用 canvas, 其他部门需要添加自定义图形操作的时候就需要他们了解 Canvas 开发 重绘到 Viewer 已有的 Canvas 上面。2) Canvas 会失去很多 Element 原生的属性,比如文字选中,aria标签, 事件等。3) Viewer 的文件可能会非常的大,并且可能会有成千上万个页面,每个页面管理自己的绘图。如果每个页面一个Canvas, 性能会非常差(采用了 View Virtualization 思想,只渲染视图需要的元素,这里是做了个极限假设)。如果所有的图形都绘制在一个Canvas上面,需要根据视图区域的页面属性重绘图形计算,开发成本会增加非常多。4)Canvas 只能用于最底层,否则会覆盖其他元素(Viewer上面的层非常多,需要绘图层能管理事件,同时不丢失其他层的事件)。
于是老大就给几天时间,让我们尽情地先试着用其他的方式画一下各种图形,比较一下优劣(最后,我们应该会几样技术结合起来用)。其中一个案例就是高光选中文本,后端传会传一堆需要高光块儿大小位置,前端画出高光部分。 像这种非常多小面积的绘图,Canvas是最合适不过的了,不过这几天时间就是看看有没有还有什么其他的方案。大概就长这样,高光是无数个小块儿。
寻找方案Canvas 画高光的方案已经有了,我们首先想到的就是每一个块儿给个 span 渲染,但因为需要高光的块儿可能会非常多,并且可能会是动态的。哪么这就涉及到 DOM 的频繁操作,性能非常不好。后来采用createdocumentFragment,添加到DOM,性能明显提升。
我当时有个非常大胆的想法,要是只用一个span,然后所有的块儿都添加成背景可不可以实现(考虑到现在的css3已经有了多背景重叠技术)。找路子的时候千万次觉得不可能,结果实现之后再返回去看,其实原理非常的简单。全部采用css, 用linear-gradient画块儿(采用linear-gradient, 是因为它可以背景重叠,如果有更好的方法欢迎指教),background-position, background-size分别给每个块儿定位,结束!性能当然是惊人的好,因为根本没有涉及到元素的增加删除,只是css重绘(Viewer 有大量消耗性能的scroll监听,操作等情况下都能无缝操作,Canvas 有非常微小地快闪)。这一试,仿佛大概了新世界,很多大量,简单的图形绘制完全可以尝试纯css实现,上代码。
Angular template
<spanclass="layer-content"[style.background]="_background"[style.backgroundSize]="_backgroundSize"[style.backgroundPosition]="_backgroundPosition"></span>Angular ts file
this._subscription = this.highlights$.subscribe((highlights) => { let background = ``; let backgroundSize = ``; let backgroundPosition = ``; for (let i = 0; i < highlights.length; i++) { const { x, y, width, height } = highlights[i]; // add connection comma when i is not the last one. const comma = (i < highlights.length - 1) ? ', ' : ''; // 0px transparent to fill gradient syntax. background += `linear-gradient(CurrentColor 100%, transparent 0px)${comma}`; backgroundSize += `${width}px ${height}px${comma}`; backgroundPosition += `${x}px ${y}px${comma}`; } this._background = this.sanitizer.bypassSecurityTrustStyle(background); this._backgroundSize = backgroundSize; this._backgroundPosition = backgroundPosition; });css
span.layer-content { z-index: 0; display: inline-block; width: 100%; height: 100%; background-repeat: no-repeat !important;}期间看了些 Canvas, Svg 比较的文章,其中一篇觉得比较有意思的分享给大家。https://www.yworks.com/blog/
原文:https://segmentfault.com/a/1190000021201248
来源:爱蒂网