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. Luogu2915 [USACO08NOV]奶牛混合起来Mixed Up Cows (状压DP)

    枚举末位状态 #include <iostream> #include <cstdio> #include <cstring> #include <algor ...

  2. MySQL 数据定义语句

    表相关 修改表名 alter table grade rename hang; 新增表字段 alter table grade add `name` varchar(100); 修改表字段类型 alt ...

  3. 服务器时间同步架构与实现chrony

    实验背景 模拟企业局域服务器时间同步,保障各服务器系统准确性和时间一致性. 时间服务器系统搭建 实验架构图 环境设备 设备IP规划 国内互联网NTP服务器 ntp.aliyun.com #阿里云NTP ...

  4. 技术管理进阶——技术Leader需要数据思维

    原创不易,求分享.求一键三连 假设我长得很漂亮,拥有众多追求者,但是初出闺房的我对这世界上的男人毫无认知,那么该如何选择呢?这真是一个问题! 妈妈说,愿意为我花钱的男人未必爱我,但不愿意为我花钱的男人 ...

  5. C++ 性能小测 1 二维数组的遍历效率

    C++ 性能小测 1 二维数组的遍历效率 遍历二维数组时,常规思路是使用一个嵌套循环.一方面,由于 CPU 使用了分支预测技术,因此通常将循环次数最多循环的放在最内层.另一方面,由于二维数组是按行存储 ...

  6. Merge Into 语法支持

    KINGBASE 兼容Oracle 语法,实现了merge into 的功能.以下以例子的形式,介绍merge into语法的使用.以下例子在V8R6 ,且 database_mode=oracle ...

  7. 跟羽夏学 Ghidra ——工具

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正. 如有好的建议,欢迎反馈.码字不易,如果本篇文章 ...

  8. LFS(Linux From Scratch)构建过程全记录(五):交叉工具链的构建

    写在前面 本文将详细讲述如何构建工具链 前置知识 在LFS-BOOK中,我们需要学习一些关于"交叉编译"的内容,详见书本 安装Binutils-2.39 我们cd到sources文 ...

  9. 华南理工大学 Python第1章课后小测

    1.(单选)计算机有两个基本特性:功能性和()性.(本题分数:5)A) 可存储B) 可计算C) 可通信D) 可编程您的答案:D  正确率:100%2.(单选)计算机硬件可以直接识别和执行的程序设计语言 ...

  10. Windows服务器无法配置IP

    前天在给一台服务器配置IP地址的时候发现一个奇怪的问题.IP地址配置之后不生效,还是使用的169.254这个微软保留自动分配地址.由于这个是一台虚拟机,尝试了删除添加网卡也没有用.配置IP不成功的时候 ...