Arc绘制圆
绘制弧线
arc(x, y, r, startAngle, endAngle, anticlockwise): 以(x, y) 为圆心,以r 为半径,从 startAngle 弧度开始到endAngle弧 度结束。
anticlosewise 是布尔值,true 表示逆时针,false 表示顺时针(默认是顺时针)。
注意:
这里的度数都是弧度。
0 弧度是指的 x 轴正方向。
radians=(Math.PI/180)*degrees //角度转换成弧度
下面我们来尝试绘制圆
绘制圆

1.1设置canvas元素
<canvas id="canvas" width="200" height="200"></canvas><script>
1.2获取canvas画布
/* 获取canvas画布 */const canvas = document.getElementById("canvas");
1.3获取绘制对象
/* getContext获取绘制对象 */const ctx = canvas.getContext("2d");
1.4设置圆的参数
/* arc(x,y,radius,startAngle,endAngle) */ctx.arc(50, 50, 50, 0, Math.PI * 2);ctx.closePath();ctx.stroke();
完整代码示例:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><canvas id="canvas" width="200" height="200"></canvas><script>/* 获取canvas画布 */const canvas = document.getElementById("canvas");/* getContext获取绘制对象 */const ctx = canvas.getContext("2d");ctx.beginPath();/* arc(x,y,radius,startAngle,endAngle) */ctx.arc(50, 50, 50, 0, Math.PI * 2);ctx.closePath();ctx.stroke();</script></body></html>
绘制两个圆

2.1 第一个圆:
/* 第一个圆 */ctx.beginPath();ctx.arc(200, 200, 100, 0, Math.PI * 2);ctx.closePath();ctx.fillStyle = "#ff2d51";ctx.fill();
2.2 第二个圆
/* 第二个圆 */ctx.beginPath();ctx.arc(200, 200, 50, 0, Math.PI * 2);ctx.closePath();ctx.fillStyle = "#333";ctx.fill();
完整代码示例:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><canvas id="canvas" width="400" height="400"></canvas><script>/* 100 50 */const canvas = document.getElementById("canvas");const ctx = canvas.getContext("2d");/* 第一个圆 */ctx.beginPath();ctx.arc(200, 200, 100, 0, Math.PI * 2);ctx.closePath();ctx.fillStyle = "#ff2d51";ctx.fill();/* 第二个圆 */ctx.beginPath();ctx.arc(200, 200, 50, 0, Math.PI * 2);ctx.closePath();ctx.fillStyle = "#333";ctx.fill();</script></body></html>
绘制动画圆
3.1 绘制动画圆

3.1.1使用setInterval实现动画圆
在 JavaScript 中,setInterval 函数用于按照指定的周期(以毫秒计)来调用一个函数或执行一个代码片段。它返回一个间隔的ID,之后可以用于 clearInterval 函数来停止执行该函数setInterval 被用来每隔20毫秒执行一次 draw 函数。这个 draw 函数负责在 canvas 上绘制一个圆形,并且动态地改变圆的半径。
主要实现步骤:
-
var canvas = document.getElementById("canvas");获取页面上的 canvas 元素。 -
const ctx = canvas.getContext("2d");获取 canvas 的 2D 绘图上下文。 -
var radius = 50;初始化圆的半径为50。 -
var increase = true;初始化一个布尔值,用来控制半径的增减。 -
function draw() { ... }定义了一个draw函数,该函数首先清除 canvas,然后绘制一个圆,并且根据increase的值来增加或减少半径。 -
setInterval(() => { draw() }, 20)设置一个定时器,每隔20毫秒调用一次draw函数。
示例代码:
<body><canvasid="canvas"width="200"height="200"></canvas><script>/* canvas */var canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d");var radius = 50;/* */var increase = true;/*100 false50 true*/functiondraw() {/* */ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath();ctx.arc(100, 100, radius, 0, Math.PI * 2, false); ctx.closePath();ctx.fillStyle = "#6528e0"ctx.fill();if (radius >= 100) {/* 100, */increase = false} elseif (radius < 50) { /* 50 */increase = true;}if (increase) {radius++} else {radius--;} }setInterval(() => {draw()}, 20)</script></body>
3.2. setTimeout实现动画圆
setTimeout(draw, 20) 会在每次 draw 函数执行完毕后,再次设置一个20毫秒后执行 draw 函数的定时器。
draw 函数会以大约每20毫秒一次的频率被调用,这与 setInterval 的效果相似,但是 setTimeout 可以更精确地控制每次调用之间的时间间隔。
主要步骤:
-
初始化 canvas 元素和绘图上下文。
-
设置初始半径
radius为 50。 -
定义
draw函数,该函数首先清除 canvas,然后绘制一个圆,并且根据increase的值来增加或减少半径。 -
在
draw函数的末尾,使用setTimeout再次调用draw函数,延迟时间为 20 毫秒。 -
调用
draw函数开始执行。draw函数会不断被调用,每次调用都会更新圆的半径,并在 canvas 上重新绘制圆。半径会在 50 和 100 之间变化,形成一种动态效果。
代码示例:
<body><canvasid="canvas"width="200"height="200"></canvas><script>/* canvas */var canvas = document.getElementById("canvas");const ctx = canvas.getContext("2d");var radius = 50;/* */var increase = true;/*100 false50 true*/functiondraw() {/* */ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath();ctx.arc(100, 100, radius, 0, Math.PI * 2, false); ctx.closePath();ctx.fillStyle = "#6528e0"ctx.fill();if (radius >= 100) {/* 100, */increase = false} elseif (radius < 50) {/* 50 */increase = true;}if (increase){radius++} else {radius--;}setTimeout(draw, 20)}draw();</script></body>
多圈动画

创建了一个 canvas 元素,并在其中绘制两个圆形:
主要步骤:
- 通过
document.getElementById("canvas")获取页面上的 canvas 元素,并使用getContext("2d")获取其 2D 绘图上下文。 - 初始化变量
radius为 60,这将用于控制较大圆的半径。 - 定义一个布尔变量
increase,初始值为true,用于控制半径的增减。 - 定义
draw函数,该函数执行以下操作:- 使用
ctx.clearRect清除 canvas 上的绘制内容。 - 使用
ctx.beginPath开始一个新的路径。 - 使用
ctx.arc绘制一个圆,其位置在 canvas 中心 (100, 100),半径为radius,颜色为半透明的紫色 (#6528e080)。 - 使用
ctx.closePath结束当前路径。 - 使用
ctx.fill填充颜色。 - 再次使用
ctx.beginPath和ctx.arc绘制一个固定半径为 50 的圆,颜色为蓝色 (#0088ff)。 - 检查
radius的值,如果达到 100,则将increase设置为false,开始减小半径;如果小于 60,则将increase设置为true,开始增加半径。 - 根据
increase的值,增加或减少radius。 - 使用
setTimeout延迟 30 毫秒后再次调用draw函数,创建动画效果。
- 使用
- 调用
draw函数开始执行动画。
代码示例:
<body><canvas id="canvas" width="200" height="200"></canvas> <script>/* canvas */var canvas = document.getElementById("canvas"); const ctx = canvas.getContext("2d");var radius = 60;/* */var increase = true;/*100 false50 true*/function draw() {/* */ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath();ctx.arc(100, 100, radius, 0, Math.PI * 2, false); ctx.closePath();ctx.fillStyle = "#6528e080"ctx.fill();/* */ctx.beginPath();ctx.arc(100, 100, 50, 0, Math.PI * 2, false);ctx.closePath();ctx.fillStyle = "#0088ff" ctx.fill();if (radius >= 100) {/* 100, */increase = false} else if (radius < 60) { /* 50 */increase = true;}if (increase) {radius++} else {radius--;}setTimeout(draw, 30)}draw();</script></body>
Canvas结合Openlayer

5.1 openlayer-canvas
canvas 是作为样式设置给要素的。
这里分享的案例中使用了 OpenLayers 库来在网页上显示一个地图,并在地图上添加了两个点,其中一个点使用了动态生成的 canvas 图像作为图标。
主要步骤如下:
- 引入 OpenLayers 的 CSS 和 JS 文件。
- 创建一个
div元素,其 ID 为map,这将作为地图的容器。 - 初始化一个地图图层
gaode,使用高德地图的瓦片服务作为地图的背景。 - 创建一个矢量图层
layer,用于在地图上添加自定义的点。 - 初始化地图
map,设置其显示的中心点、缩放级别,并将之前创建的图层添加到地图上。 - 创建一个 canvas 元素,并在其中绘制两个动态变化的圆,一个较大,一个较小,较大圆的颜色是半透明的红色,较小圆的颜色是蓝色。
- 使用
setTimeout函数每隔 100 毫秒调用draw函数,更新 canvas 上的图像,并重新渲染地图。 - 创建一个 OpenLayers 的样式
style,使用 canvas 作为图标。 - 创建两个 OpenLayers 的特征
shape和beijing,分别代表地图上的两个点。 - 将样式应用到矢量图层
layer上,并将两个特征添加到图层的源中。
代码示例:
var style = new ol.style.Style({image: new ol.style.Icon({img: canvas,imgSize: [canvas.width, canvas.height]})});<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="https://lib.baomitu.com/openlayers/4.6.5/ol.css"><script src="https://lib.baomitu.com/openlayers/4.6.5/ol.js"></script></head><body><div id="map"></div><script>var gaode = new ol.layer.Tile({title: "",source: new ol.source.XYZ({url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',wrapX: false})});/* */var layer = new ol.layer.Vector({source: new ol.source.Vector()})var map = new ol.Map({target: "map",layers: [gaode, layer],view: new ol.View({projection: 'EPSG:4326',center: [114.30, 30.50],zoom: 8})})var center = [114.30, 30.50]let size = 40;var canvas = document.createElement('canvas');canvas.width = size;canvas.height = size;var ctx = canvas.getContext('2d');var radius = size / 4;var increase = true;function draw() {ctx.clearRect(0, 0, size, size);/* */ctx.beginPath();ctx.arc(size / 2, size / 2, radius, 0, Math.PI * 2); ctx.closePath();ctx.fillStyle = "#ff2d5166";ctx.fill();/* */ctx.beginPath();ctx.arc(size / 2, size / 2, 8, 0, Math.PI * 2);ctx.closePath();ctx.fillStyle = "#0088ff";ctx.fill();if (radius > 14) {increase = false}if (radius < 10) {increase = true;}if (increase) {radius++} else {radius--;}setTimeout(draw, 100)map.render();}draw();var style = new ol.style.Style({image: new ol.style.Icon({img: canvas,imgSize: [canvas.width, canvas.height] })});var shape = new ol.Feature({geometry: new ol.geom.Point(center)});var beijing = new ol.Feature({geometry: new ol.geom.Point([120, 40])})layer.setStyle(style)layer.getSource().addFeatures([shape, beijing]);</script></body></html>
5.2. 封装
代码示例:
function setCanvas(map) {let size = 40;var canvas = document.createElement('canvas'); canvas.width = size;canvas.height = size;var ctx = canvas.getContext('2d');var radius = size / 4;var increase = true;function draw() {ctx.clearRect(0, 0, size, size);/* */ctx.beginPath();ctx.arc(size / 2, size / 2, radius, 0, Math.PI * 2); ctx.closePath();ctx.fillStyle = "#ff2d5166";ctx.fill();/* */ctx.beginPath();ctx.arc(size / 2, size / 2, 8, 0, Math.PI * 2);ctx.closePath();ctx.fillStyle = "#0088ff";ctx.fill();if (radius > 14) {increase = false}if (radius < 10) {increase = true;}if (increase) {radius++} else {radius--;}setTimeout(draw, 180)map.render();}draw();return canvas;}//let canvas = setCanvas(map);var style = new ol.style.Style({image: new ol.style.Icon({img: canvas,imgSize: [canvas.width, canvas.height] })});
为了帮助大家更快的了解GIS开发,我们还特别推出了项目教程,部分含笔记,有兴趣的可以扫码领取,备注相关课程名字:
1.智慧校园系统项目
2.Echarts数据可视化实战项目
3.零基础入门WebGIS开发实例
4.cesiume系列教程
5.前端框架VUE3入门教程
6.二维地图框架mapbox系列教程
7.嘉yaogis888备注资料名称
Canvas结合openlayers绘制画、实现动画效果&spm=1001.2101.3001.5002&articleId=150267512&d=1&t=3&u=bc0e52582eb74601988238525aed6ea1)
1万+

被折叠的 条评论
为什么被折叠?



