纯 CSS 实现大量小块儿绘制

更新日期: 2019-11-04阅读: 1.7k标签: 绘制

现在做的项目是公司内部全部组要用的 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

<span class="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


链接: https://www.fly63.com/article/detial/6720

css实现自适应正方形的多种方法实现

纯CSS实现自适应浏览器宽度的正方形有以下三种方法:CSS3 vw 单位、设置垂直方向的padding撑开容器、利用伪元素的 margin(padding)-top 撑开容器

如何使用css3绘制任意角度扇形+动画

使用两个半圆做角度拼接。比如想绘制一个缺口朝右,缺口弧度30度角的扇形,那么将由一个旋转65度角的半圆A+一个旋转-65度角的半圆B组合而成。

纯css如何绘制三角形_利用border实现画三角形的原理方法

使用css画三角形,首先想到的思路是:利用border边框样式来实现,这是由于border的边框是由四个三角形组成的。

使用css3绘制画圆,扇形,三角形的实现

css已经越来越强大了 ,可以使用它来绘制各种简单的形状,用于代替图片显示,这次的分享主要用到画圆,扇形,三角形等知识点,由于IE9以上才支持圆角,暂时不考虑兼容问题

我是如何用 CSS 绘制各种形状的

实现方式是通过border-radius这个属性;border-radius它可以单独指定水平和垂直半径。用 / 分隔这两个值。并且该属性的值不仅可以接受长度值,还能接收百分比的值。百分比的值会基于元素的尺寸进行解析,宽是水平半径的解析,高是垂直半径的解析。

css怎么绘制箭头?

在网页制作中,很多时候都会有箭头的情况,我们可以使用css来绘制箭头,css是如何绘制箭头的呢?下面我们来看一下使用css绘制箭头的方法。

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!