整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

HTML5基础知识(2)初识canvas、svg、地理定位和新语义元素

节主要简单讲解canvas、svg、地理定位和新语义元素

HTML 5 Canvas

canvas 元素用于在网页上绘制图形。HTML5 的 canvas 元素使JavaScript 在网页上绘制图像。画布是一个矩形区域,您可以控制其每一像素。canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

<canvas id="myCanvas" width="200" height="100"></canvas>

canvas 元素本身是没有绘图能力的。所有的绘制工作必须在 JavaScript 内部完成:

<script type="text/javascript">

var c=document.getElementById("myCanvas");

var cxt=c.getContext("2d");返回一个用于在画布上绘图的环境,目前仅支持2d,

cxt.fillStyle="#FF0000";//染成红色

cxt.fillRect(0,0,150,75);//fillRect 方法规定了形状、位置和尺寸

</script>

、什么是Canvas

想必学习前端的同学们对Canvas 都不陌生,它是 HTML5 新增的“画布”元素,可以使用JavaScript来绘制图形。

Canvas元素是在HTML5中新增的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap)。Canvas 由一个可绘制区域HTML代码中的属性定义决定高度和宽度。JavaScript代码可以访问该区域,通过一套完整的绘图功能的API生成动态的图形。

二. 引入Canvas的重要性

HTML5 在 2012 年已形成了稳定的版本,在此之前很长一段时间,开发者们绘制图形选择的方案更多是SVG来实现。SVG使用XML来定义图形,就像使用HTML标签一样来控制元素的排布,SVG的本质就是一个DOM元素。当图形内容太过丰富后,性能和内存上就会大打折扣。一旦涉及频繁的图片绘制场景,这个实现对于用户的体验将是毁灭性的。

渲染动画的基本原理,无非是反复地擦除和重绘。为了动画的流畅,留给开发者渲染一帧的时间,只有短短的 16.67ms。在这16.67ms中,我不仅需要处理一些绘制逻辑,计算每个对象的位置、状态,还需要把它们都画出来。如果消耗的时间稍稍多了一些,用户就会感受到“卡顿”。所以,在编写动画时,开发者们无时无刻不担忧着动画的性能,唯恐渲染的耗时过长。

在现代 Web 开发中,开发者们更多的会借助 Canvas 提供的API去绘制上下文,可以自由绘制各种2D和3D图形,创建富有视觉冲击力的游戏场景和角色。Canvas的使用可以使得游戏能够实现流畅的动态效果和用户交互。无论是简单的小游戏还是复杂的游戏引擎,Canvas 都被广泛应用。

下面是做的一个简单的对比试验,可以很明显感受到两者的差距,分别使用SVG和Canvas绘制一个包含着100w个圆形的500*500的图片,根据耗时计算对比,Canvas耗费的时间几乎只有SVG的一半:

三. 计算与渲染

把动画的一帧渲染出来,需要经过以下步骤:

  1. 计算:处理网页渲染逻辑,计算每个对象的状态和位置。
  2. 渲染:真正把对象绘制出来。
  • JavaScript 调用 DOM API(包括 Canvas API)以进行渲染。
  • 浏览器(通常是另一个渲染线程)把渲染后的结果呈现在屏幕上的过程。

之前提到过,在动画设计和开发中,每帧只有16.67毫秒的时间用于渲染。这个数值是通过计算每秒60帧得出的平均每帧渲染时间。实际上,并不是所有设备都能够稳定地达到60FPS。因此,为了确保在不同设备上实现一致性的动画效果,最好将每帧的渲染时间控制在10毫秒以内。

大家都知道,通常情况下,渲染的开销远大于计算(相差3~4个量级)。除非使用了一些时间复杂度很高的算法,否则不需要过于深入优化计算环节。Canvas的渲染是在JavaScript引擎中执行绘制逻辑,通过构建画布在内存中,并遍历所有像素点的颜色,最终输出到屏幕上。这种强大的功能可能会增加学习成本,但如今仍然有很多开发者选择和接受Canvas,这要归功于Canvas最大的优势:渲染性能的出色表现。

四. Canvas渲染性能优势

当谈论图形渲染技术时,就不得不提到DOM驻留模式和Canvas快速模式。

DOM驻留模式

DOM驻留模式是一种基于文档对象模型(DOM)的渲染技术。在DOM驻留模式下,页面的布局和样式是由DOM树来掌管的。当页面需要更新时,浏览器会重新计算布局和样式并重新渲染。此模式非常灵活,特别适用于处理动态页面交互和多样化的样式控制。然而,由于需要频繁地重新计算布局和样式,对于复杂的图形渲染任务来说,性能开销相对较高。

Canvas快速模式

Canvas快速模式利用HTML5的Canvas元素进行图形渲染。在这种模式下,开发者可以使用Canvas提供的2D或3D绘图API直接在画布上绘制图形。相比于DOM驻留模式,Canvas快速模式更加高效。它不关心页面的布局和样式,而是在需要时只重绘受影响的部分。这样就避免了频繁的布局和样式计算,提高了渲染性能。

分层提高Canvas性能

开发者们通过分析大量实际场景,总结出一套可以进一步提升Canvas性能的策略,即对变化较少和变化较多的内容进行分开渲染。这种策略就是所谓的分层Canvas。它能够显著降低完全没有必要的渲染性能开销。分层渲染的思想被广泛应用于各种图形相关的领域,从古老的皮影戏、套色印刷术,到现代电影/游戏工业以及虚拟现实领域等等。而分层Canvas只是分层渲染思想在Canvas动画上的一个基础应用。

分层Canvas的核心理念是,动态页面中的每种元素(层)对于渲染频率的需求是不同的。对于许多金融会计等大数据行业的从业者来说,主要数据内容的变化频率和幅度较大(他们通常面临数据变动和频繁计算),而背景表格样式的变化频率或幅度相对较小(基本不变,或者变化缓慢,或者仅在特定时机变化)。因此,需要频繁更新和重绘数据,但对于背景,可能只需要绘制一次,或者每隔200毫秒才重绘一次,而没有必要每16毫秒就重绘一次。

视野之外的绘制

在许多情况下,Canvas 仅仅作为数据展示页面的一部分,充当着一个“窗口”的角色。如果在每次数据更新时,都将所有数据完全绘制到 Canvas 上,很可能会出现大量内容绘制到Canvas 范围之外的情况。虽然调用了绘制 API,但实际上并没有产生任何效果。

因此,判断对象是否位于 Canvas 范围内需要进行额外的计算(例如,需要通过对游戏角色的全局模型矩阵求逆来得出对象的世界坐标,这是一项相对耗时的操作),同时也会增加代码的复杂性。因此,关键是是否需要这样做。

通过在本地代码中进行测试,比较了在视野内和视野外分别绘制100万个圆的耗时。在视野内绘制耗时8936ms,而在视野外绘制耗时2540ms。考虑到计算和绘制之间的耗时差距在3~4个数量级,因此通过计算来判断并避免绘制视野外的内容是一种非常有效的方法。

五. Canvas的应用

之前探讨了SVG和Canvas的绘制性能差异以及Canvas常见的优化方法。知道,对于使用快速模式渲染的Canvas来说,浏览器的每次重绘都是由代码驱动的,无须进行多层解析,因此它的速度非常快。除了速度快之外,Canvas的灵活性也显著优于DOM。可以通过代码精确控制何时以及如何绘制出期望的效果。

在资源消耗方面,DOM的驻留模式意味着场景中的每一个新增元素都会导致额外的内存消耗,而Canvas则没有这个问题。这种差异在页面元素数量增多时尤为明显。

在Canvas出现之前,前端渲染表格只能通过构建复杂的DOM来实现。然而,这种方式会导致浏览器性能成为Web应用的瓶颈,许多开发人员因此放弃了在浏览器上实现电子表格的想法。

Canvas出现后,其快速模式带来的出色性能优势成为了一大亮点,大量、复杂的DOM渲染处理所带来的性能问题因此有了解决之道。

回到电子表格的应用场景,现在已经出现了使用Canvas绘制画布的表格组件。这类组件在渲染数据层时无须重复创建和销毁DOM元素,而且在画布的绘制过程中受到的限制也比DOM元素渲染更少。其中,葡萄城公司的纯前端表格控件——SpreadJS就用到了Canvas实现表格绘制,除了表格之外,Canvas也为数字孪生可视化大屏、页面游戏等应用场景带来了变革(如下图所示)。

六、总结

本文通过介绍Canvas的原理、Canvas的重要性、Canvas在计算与渲染上的作用、Canvas渲染性能优势和Canvas的应用这五个部分,全面而系统地阐述了HTML Canvas在高性能渲染方面的相关知识和技巧。希望读者通过阅读本文能够深入了解Canvas的基本原理和特性,认识到Canvas在Web开发中的重要性,并掌握Canvas在计算与渲染上的作用。

开发vue项目,有时会遇到需要页面截图或指定区域截图需求。今天给大家推荐2个超赞的截图插件。

1、html2canvas

一款超强大的Javascript页面截图类库,star高达21.4K+。支持h5页面截图、区域截图及跨域截图等功能。

截图效果

下面讲一下如何在vue中使用html2canvas截图。

安装

$ npm i html2canvas -S

使用组件

<template>
  <div class="shot-wrapper">
    <!-- 要截图的区域,动态生成 -->
    <div class="shot-area" id="content" ref="imageToFile"></div>
    
    <!-- 截图生成图片 -->   
    <img :src="img" v-if="img"/>
    
    <button type="button" class="shot-btn" @click="screenShot">开始截图</button>
  </div>
</template>
<script>
  import html2canvas from 'html2canvas'
  export default {
    data() {
      return {
        img: ""
      }
    },
    methods: {
      screenShot() {
        html2canvas(this.$refs.imageToFile, {
          width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
          height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight,
        }).then((canvas) => {// 第一个参数是需要生成截图的元素,第二个是自己需要配置的参数,宽高等
          this.img = canvas.toDataURL('image/png');
        })
      },
    },
    components: {
      html2canvas
    }
  }
</script>

如果大家想要了解更多用法,可以自行去官网查阅资料哈~~

# 文档地址
http://html2canvas.hertzen.com/

# 仓库地址
https://github.com/niklasvh/html2canvas

2、Dom-To-Image

一款超不错的将任意DOM节点转换为用JavaScript编写的矢量(SVG)或光栅(PNG或JPEG)图像的库。star高达6.4K+

下面介绍下在vue中如何使用domtoimage进行截图。

安装

$ npm i dom-to-image -S

使用组件

<template>
  <div class="domtoimage-wrapper">
    <!-- 要截图的区域,动态生成 -->
    <div class="dom-area" id="my-node"></div>
    
    <!-- 截图生成图片 -->   
    <img :src="img" v-if="img"/>
    
    <button type="button" class="shot-btn" @click="shotPic">开始截图</button>
  </div>
</template>

<script>
  import domtoimage from 'dom-to-image'
  export default {
    data() {
      return {
        img: ""
      }
    },
    methods: {
      shotPic() {
        let node = document.getElementById('my-node');
        domtoimage.toPng(node)
          .then((dataUrl) => {
            this.img = dataUrl;
          })
          .catch(function (error) {
            console.error('oops, something went wrong!', error);
          });
      }
    },
    components: {
      domtoimage
    }
  }
</script>

domtoimage主要的属性

  • filter:过滤器节点中默写不需要的节点;
  • bgcolor:图片背景颜色;
  • height,width:图片宽高;
  • style:传入节点的样式,可以是任何有效的样式;
  • quality:图片的质量,也就是清晰度;
  • cacheBust:将时间戳加入到图片的url中,相当于添加新的图片;
  • imagePlaceholder:图片生成失败时,在图片上面的提示,相当于img标签的alt;

domtoimage主要的方法

  • domtoimage.toPng(...); 将节点转化为png格式的图片;
  • domtoimage.toJpeg(...); 将节点转化为jpg格式的图片;
  • domtoimage.toSvg(...); 将节点转化为svg格式的图片,生成的图片的格式都是base64格式;
  • domtoimage.toBlob(...); 将节点转化为二进制格式,这个可以直接将图片下载;
  • domtoimage.toPixelData(...); 获取原始像素值,以Uint8Array 数组的形式返回;

最后附上项目地址,可以去了解更多信息。

# 仓库地址
https://github.com/tsayen/dom-to-image

ok,就介绍到这里。如果大家有其它优秀的Vue截图组件,欢迎分享交流!