00、前端图形

前端代码实现图形的几种方式:CSS、SVG、Canvas(主要是JavaScript编码)

CSS也是可以画图的,需要借助于高宽、边框borderclip-path裁剪、渐变色背景等属性来模拟实现各种图形,当然只能实现一些简单的图形。

border:用四条边框样式属性的各种组合变换,实现一些简单的图形。网上也有画一些稍微复杂的图形,如哆啦A梦,但代码量稍多,可读性不好,并不推荐。

<div class="gcss">
<p class="border">border</p>
<p class="rborder">圆角按钮</p>
<p class="radio"></p>radio
<p class="triangle1"></p>三角形
<p class="triangle2"></p>三角形
</div>
<style>
.gcss p {
display: inline-block;
text-align: center; vertical-align: middle;
}
.border {
border: 30px solid;
border-color: aqua tan violet peru;
border-radius: 20px;
}
.rborder {
background-color: #b1ccf3;
width: 100px; height: 40px; line-height: 40px;
border-radius: 20px;
}
.radio {
width: 40px; height: 40px;
border-radius: 50%;
border: 10px solid;
}
.triangle1 {
border: 50px solid #0001;
border-left-color: red;
}
.triangle2 {
border-left: 50px solid #0001;
border-right: 50px solid #0001;
border-bottom: 50px solid red;
}
</style>


01、< svg>矢量图形

< svg>可缩放矢量图形(Scalable Vector Graphics,SVG),是一种基于 XML(数学)描述的二维的矢量图形,内容可以直接插入网页,成为DOM的一部分,然后用 JavaScript 和 CSS 进行操作。SVG 内容也可以写在一个独立文件中,然后用CSS(background-url)、<img><object><embed><iframe>来引用。

大多数现代浏览器都支持SVG 图形,越来越多的项目在使用SVG图形,简单的像图标,复杂的一些图表Chart也有不少是基于SVG实现的。相比于位图,体积更小,可无线缩放而不失真。

比较 矢量图形 位图
存储的数据 存储元素、算法数据 存储像素数据
存储大小
缩放效果 无线缩放,不失真 固定大小,放大会失真
可维护性 很容易修改 修改麻烦
扩展性 支持CSS、JS 不支持
文件格式 .svg,直接嵌入数据到页面 .bmp/.png/.jpg/.gif,< img>可嵌入svg文件
支持的元素 <svg><img><iframe><object> <img><iframe>
兼容性 IE9开始支持 较好
渲染性能 复杂的SVG会占用很多时间 稳定
网络传输性能 和页面数据一起,体积小,速度快 需单独请求图片资源
缓存 随网页内容一起,不可单独缓存 图片可单独缓存

1.1、< svg>元素

<svg>内部支持多种图形算法,基础的如线line、圆形<circle>、矩形rect、文本text,复杂的有折线polyline、多边形polygon、路径数据path等。这些图形都以子元素的形式组合,因此也就都支持CSS、JS的操作了。iconfont-阿里巴巴矢量图标库上有非常丰富的< svg>矢量图形。

元素/属性 描述 值/示例
< svg> 矢量图形元素
viewBox SVG 画布显示区域,这里 1 单位等同于 1 屏幕单位,SVG里的坐标、尺寸都是基于此画布区域 viewBox="0 0 300 200"
width、height 宽度、高度 width="300" height="200"
xmlns xml标签的命名空间,为了区分html、svg,可以省略
< line> 线段
x1、y1 起点x、y坐标 <line x1="0" y1="100" />
x2、y2 终点x、y坐标 x2="300" y2="100"
< rect> 矩形:<rect x="5" y="50" height="100" width="290"/>
x、y 起点坐标
width、height 矩形的宽、高
rx、ry x、y方向的圆角半径。r=radius 半径 rx="50" ry="50"
<circle/ellipse> 圆和椭圆:<circle cx="150" cy="100" r="80"/>
cx、cy 圆心的x、y坐标
r 圆的半径长度
rx、ry 椭圆的x、y半径
<polyline/polygon> 折线、多边形,两者数据结构相似,多边形是自动首尾连接封闭成一个区域(Polygon /ˈpɒlɪɡən/ 多边形)
points x、y坐标的集合,多个坐标逗号,分割 points="0 0, 20 40, 70 80/>
< path> 路径,很常用、很强大的图形绘制,数据在属性d
< d> 路径数据&lt; path&gt;最重要的属性,由多组命令+ 坐标点组成 d="M 50 5 H250 V195 H50 Z"
M x y 移动画笔到坐标点x、y M50 5
L x y 划线到坐标x、y L 250 0
H x 绘制水平线,到坐标x;小写h的坐标为相对位置 H 250
V y 绘制垂直线,到坐标y;小写v的坐标为相对位置 V195
Z 闭合路径(closepath),放到最后用于闭合路径
C* 绘制曲线,包括贝塞尔曲线、圆弧。
<text> 文本标签,支持CSS样式中的文本样式
x、y 文本开始位置
font-size 字体大小
< textPath> 文字绘制的路径,这个就比较有趣了 <textPath xlink:href="#path1">
公共属性 部分属性可以用CSS设置,支持hover伪类
stroke 笔画颜色(stroke /stroʊk/ 笔画) ,包括线段、形状线条。 stroke="red"
stroke-width 画笔线宽 stroke-width="10"
fill 填充颜色,填充一个区域(矩形、圆形等) fill="#0001"

小提示:注意服务器添加对svg的支持,及gzip压缩。

<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<circle cx="150" cy="100" r="80" fill="green" />
<circle cx="150" cy="100" r="70" fill="#fff" />
<text x="150" y="125" font-size="60" text-anchor="middle" fill="orange">SVG</text>
<line x1="0" y1="100" x2="300" y2="100" stroke="white" stroke-width="8"/>
</svg>
<svg class="icon" height="200" viewBox="0 0 300 200" version="1.1">
<rect x="5" y="50" rx="50" ry="50" height="100" width="290" fill="white" stroke="blue" stroke-width="10"/>
<path d="M 50 5 H250 V195 H50 Z" stroke="red" stroke-width="10" fill="#00000001" />
<text x="145" y="125" font-size="60" text-anchor="middle" fill="#fab">Path</text>
</svg>
<style>
svg:hover{
background-color: aliceblue;
stroke: red;
stroke-width: 1px;
fill: red;
}
</style>

1.2、动画

SVG 本身就是一个HTML元素,因此动画可以用CSS的动画来实现(参考 CSS动画),SVG中也有专门用于实现动画的<animate>子元素。这里示例采用JavaScript+transform变换实现旋转效果。

<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<circle cx="150" cy="100" r="80" fill="green" />
<circle cx="150" cy="100" r="70" fill="#fff" />
<text class="svgc" x="150" y="125" font-size="60" text-anchor="middle" fill="orange" >SVG</text>
<line class="svgc" x1="0" y1="100" x2="300" y2="100" stroke="white" stroke-width="8" />
</svg>
<script>
let svgcs = document.querySelectorAll(".svgc");
//设置中心点
svgcs.forEach(element => {
element.setAttribute("transform-origin", '150 100');
});
let deg = 0;
setInterval(() => {
deg = deg > 360 ? 0 : deg+4;
svgcs.forEach(element => {
element.setAttribute("transform", `rotate(${deg})`);
});
}, 100);
</script>
<!-- 用CSS动画实现的版本 -->
<style>
.svgc {
transform-origin: 150px 100px;
animation: svgc-routate 2s linear 1s infinite;
}
@keyframes svgc-routate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>

1.3、svg工具/资源/库

矢量图标资源

  • Iconfont-阿里巴巴矢量图标库,功能很强大,及其提供丰富的矢量图标库,提供矢量图标下载、在线存储、格式转换等功能。应该就这个就够了!
  • flaticon,国外的矢量图标库

SVG工具

路径< path>可以绘制任意的图形,直接编码是比较困难的,特别是C贝塞尔曲线。所以一般都是用专业工具来绘制&lt; svg&gt;图形的,也有在线工具。

动画库

  • 第三方库GSAP,来自GreenSock,可以更简单的实现更丰富的动画效果,不光支持SVG,包括页面中任意可以通过JS访问的元素、属性,都可以实现动画。
  • anime.js,功能强大,非常轻量,压缩后大小9K。
  • SVG动画库:mo.jsSVG.js

02、< canvas>基础

< canvas>只是一块平平无奇的画布而已(在HTML中就一个<canvas>元素),提供了一点点API,由JS进行绘制各种图形。2D的canvas绘制和<SVG>挺像,都是一些线、矩形、圆、path路径数据。这里就先简单了解一下,<canvas>功能是很强大的,很多可视化图表都是基于<canvas>实现的。

基本特点

  • 双标签,必须包含闭合标签。标签内可以放提示文字,当浏览器不支持<canvas>会显示。
  • 坐标系以左上角为中心点,和SVG一样。

2.1、canvas API

canvas 属性/方法 描述
height、width 元素高度、宽度:<canvas width="400" height="400"></canvas>
getContext(contextType) 获取用于绘制的渲染上下文,contextType:
"2d":CanvasRenderingContext2D 二维渲染上下文
"webgl": WebGLRenderingContext 三维渲染上下文,OpenGL ES 2.0
"webgl2":WebGL2RenderingContext 三维渲染上下文,OpenGL ES 3.0
CanvasRenderingContext2D
fillStyle 填充(内部)颜色 ctx.fillStyle='rgba(250,0,0,0.6)'
strokeStyle 画笔(边框)颜色 ctx.strokeStyle='red',同上,支持color、渐变色画刷、图片画刷
font 字体设置 ctx.font = "bold 48px serif"
lineWidth 线宽 ctx.lineWidth = 15;
toDataURL(type, quality) 可以将canvas绘制的图形转换为Data URI 格式的图像,从而导出为位图文件
基础图形绘制
fillRect(x, y, width, height) 填充一个矩形
strokeRect(x, y, width, height) 绘制一个矩形框
clearRect(x, y, width, height) 清除指定区域的的像素
fillText(text, x, y, [maxWidth]) 填充文本
strokeText(text, x, y [, maxWidth]) 绘制文本(轮廓)
drawImage() 绘制位图
路径绘制 创建路径 >** ②创建路径 > ③**渲染路径
beginPath() 开始一个新的路径,清除已有路径列表
closePath() 闭合一个路径
moveTo(x, y) 移动画笔到坐标x、y
lineTo(x, y) 画线到坐标x、y
ellipse(x, y, radiusX, radiusY,r,sa,ea) 椭圆路径 ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle)
rect(x, y, width, height) 矩形路径
arc(x, y, radius, startAngle, endAngle) 绘制圆弧路径
quadraticCurveTo(cp1x, cp1y, x, y) 二次贝塞尔曲线
fill([path], [fillRule]) 填充当前、已存在的路径
stroke([path]) 描边子路径
Path2D 可以单独申明一个路径对象,支持上面的绘制,还支持SVG的path数据。
<canvas id="canvas" width="400" height="400"></canvas>
<script>
ctx = document.getElementById('canvas').getContext('2d');
// ctx.alpha = false;
ctx.fillStyle = 'rgba(250,0,0,0.6)';
ctx.fillRect(10, 10, 40, 40);
ctx.fillRect(30, 30, 40, 40);
ctx.strokeStyle = 'red';
ctx.lineWidth = 3;
ctx.strokeRect(90, 10, 150, 50);
ctx.fillStyle = 'rgba(0,0,250,0.5)';
ctx.font = '20px 微软雅黑';
ctx.fillText("文本Text", 120, 40)
//path
ctx.beginPath();
ctx.moveTo(90, 80);
ctx.lineTo(90, 200);
ctx.lineTo(190, 200);
ctx.closePath();
ctx.arc(120, 120, 50, 0, 360);
ctx.fill();
</script>

弧度 = ( Math.PI / 180 ) * 角度,360度的弧度= Math.PI*2

2.2、动画

Canvas的动画就是不停的重绘,其实任何动画都是这样,前端实现动画有以下几种姿势:

  1. setInterval(function, delay):定时重绘,适合不需要交互的场景。
  2. setTimeout(function, delay):定时重绘,适合通过键盘或者鼠标事件来捕捉用户的交互,再用 setTimeout 执行相应的动作。
  3. requestAnimationFrame(callback):动画专用API,这个方法更加平缓并更加有效率,当系统准备好了重绘条件的时候,才调用绘制动画帧。

requestAnimationFrame (render)是HTML5提供的动画API,他向浏览器申请执行一个动画帧渲染函数,浏览器在下次重绘(刷新)之前调用这个render回调函数。requestAnimationFrame还做了很多优化以提升性能和流畅度。

  • 稳定60帧:浏览器的刷新周期大多和屏幕刷新率匹配,为每秒60次,非常稳定高效。不像setIntervalsetTimeout还要在任务队列里排队等待,就可能发生丢帧和卡顿现象。
  • 合并优化:浏览器会优化动画的执行,把每一帧的所有DOM操作集中起来,在一个渲染周期内执行。
  • 隐藏优化:当前窗口或者标签页不可见时停止运行requestAnimationFrame
<canvas id="canvas" width="400" height="400"></canvas>
<script>
ctx = document.getElementById('canvas').getContext('2d');
//动画旋转
let eangle = 0;
function drawEllipse() {
ctx.clearRect(255, 150, 140, 140);
ctx.beginPath();
ctx.fillStyle = 'rgba(0,250,0,0.3)';
eangle = eangle > 360 ? 0 : eangle + 1;
ctx.ellipse(320, 230, 60, 30, eangle * Math.PI / 180, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
ctx.beginPath();
ctx.ellipse(320, 230, 30, 60, eangle * Math.PI / 180, 0, 2 * Math.PI);
ctx.fillStyle = 'rgba(0,0,250,0.3)';
ctx.stroke();
ctx.fill();
}
setInterval(drawEllipse, 20);
//水平移动
let lx = 40;
let ltr = true;
function drawRect() {
if (lx > 300) ltr = false;
if (lx < 40) ltr = true;
// ctx.clearRect(lx, 220, 40, 40);
ctx.fillStyle = 'rgb(255,255,255,0.4)';
ctx.fillRect(20, 290, 340, 60);
lx = ltr ? lx + 2 : lx - 2;
ctx.fillStyle = 'rgb(110,22,250)';
ctx.fillRect(lx, 300, 40, 40);
ctx.strokeRect(lx, 300, 40, 40);
requestAnimationFrame(drawRect); //永远不停的提交渲染申请,递归自己
}
requestAnimationFrame(drawRect);
</script>

用canvas实现的一个彩球大战:codepen


03、WebGL

WebGL 作为一种WEB 3D绘图技术,依托于<canvas>元素。WebGL是运行在GPU上的,可面向底层显卡编程,可调用底层的接口,实现硬件加速,在2D图形绘制上性能会优于Canvas2D。

传说原生的WebGL比较难学,可考虑使用使用第三方的WebGL库,如Three.js、Cesium.js(3D地图)、Babylon.js

MDN:WebGL 教程


️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址

前端图形:SVG与Canvas的更多相关文章

  1. Seen.js – 使用 SVG 或者 Canvas 渲染 3D 场景

    Seen.js 渲染3D场景为 SVG 或者 HTML5 画布.Seen.js 包含对于 SVG 和 HTML5 Canvas 元素的图形功能的最简单的抽象.所有这个库的其它组件都是不用关心将要渲染的 ...

  2. SVG 与 Canvas:如何选择

    SVG 与 Canvas:如何选择 61(共 69)对本文的评价是有帮助 - 评价此主题   本主题一开始将对 SVG 与 Canvas 进行简要比较,接下来会讨论大量的比较代码示例,如光线跟踪和绿屏 ...

  3. 三天学会HTML5——SVG和Canvas的使用

    在第一天学习了HTML5的一些非常重要的基本知识,今天将进行更深层学习 首先来回顾第一天学习的内容,第一天学习了新标签,新控件,验证功能,应用缓存等内容. 第2天将学习如何使用Canvas 和使用SV ...

  4. SVG 2D入门13 - svg对决canvas

    到目前为止,SVG与Canvas的主要特性均已经总结完毕了.它们都是HTML5中支持的2D图形展示技术,而且均支持向量图形.现在,我们就来比对一下这两种技术,分析一下它们的长处和适用场景.首先分析一下 ...

  5. 前端实现 SVG 转 PNG

    http://fex.baidu.com/blog/2015/11/convert-svg-to-png-at-frontend/ 前言 svg 是一种矢量图形,在 web 上应用很广泛,但是很多时候 ...

  6. html5 中的SVG 和canvas

    想到昨天看资料的时候,发现html5 中的SVG 和canvas 都可以表示图形,那它们到底有哪些区别呢?该如何正确的使用它们呢? 1.SVG:可缩放矢量图形,(Scalable Vector Gra ...

  7. HTML5 Canvas、内联 SVG、Canvas vs. SVG

    canvas 元素用于在网页上绘制图形. 什么是 Canvas? HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像. 画布是一个矩形区域,您可以控制其每一像素. canv ...

  8. SVG和canvas渲染的性能比较

    1.什么是SVG? 描述: 一种使用XML描述的2D图形的语言 SVG基于XML意味着,SVG DOM中的每个元素都是可用的,可以为某个元素附加Javascript事件处理器. 在 SVG 中,每个被 ...

  9. HTML5(三)SVG vs. Canvas

    HTML5 内联 SVG 什么是SVG? SVG 指可伸缩矢量图形 (Scalable Vector Graphics) SVG 用于定义用于网络的基于矢量的图形 SVG 使用 XML 格式定义图形 ...

随机推荐

  1. 技术分享 | 测试git上2500星的闪回小工具

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 1.实验环境 2.软件下载 3.开始测试 4.附参数说明 生产上发生误删数据或者误更新数据的事故时,传统恢复方法是利用备份 ...

  2. List的同步类比较

    TL;NRs CopyOnWriteArrayList类在多线程顺序读取上有很大的优势,但在随机读取上反而有较大的劣势,且在写入方面性能极差. Vector类在顺序读取方面性能较差,但在随机读取方面有 ...

  3. Java学习--基础

    java学习 基础 Java三大版本 javase 标准版 占领桌面端(基础) javame 移动版 嵌入式开发.占领手机端 javaee 企业版 占领服务器端 Java的特性和优势 跨平台.可移植性 ...

  4. 基于.NetCore开发博客项目 StarBlog - (17) 自动下载文章里的外部图片

    系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...

  5. SpingBoot解析Excel数据

    前言 在最近的工作中,由于导入模板除了前三列(姓名.手机号.实发工资)固定:其余的列不固定,并且可以做到两个模板的数据都能够正常入库进行对应业务处理. 一.数据模板数据展示: (1)模板一 (2)模板 ...

  6. 简单理解 Flutter 中 StatelessWidget 和 StatefulWidget

    Widget 分为了两种类型,分别为 StatelessWidget 和 StatefulWidget. 顾名思义,StatelessWidget 就是无状态的组件,它只是作为一个不发生任何更新状态的 ...

  7. CAD二次开发---关于JoinEntity出现eNotApplicable的问题

    作者在使用JoinEntity时出现eNotApplicable的问题,查阅了Autodesk论坛的相关帖子,发现大多数人都有遇到这个问题,但没有找到合适的解决方法,可能原因是进行Join时两Curv ...

  8. 【Java】学习路径55-练习:制作一个聊天室(多线程、UDP、双向传输数据)

    创建四个类,实现双向聊天的功能. 接收线程: import java.io.IOException; import java.net.*; public class ReceiveThread imp ...

  9. RTSP播放器开发填坑之道

    好多开发者提到,在目前开源播放器如此泛滥的情况下,为什么还需要做自研框架的RTSP播放器,自研和开源播放器,到底好在哪些方面?以下大概聊聊我们的一点经验,感兴趣的,可以关注 github: 1. 低延 ...

  10. KingbaseFlySync 评估工具的使用

    关键字: KingbaseFlySync.Linux.x86_64.mips64el.aarch64.Java **** 评估工具的使用**** 1.查询评估工具所在服务器的硬件平台(x86_64.m ...