svg画六边形 6个项目完成状态的对应展示,你知道吗?

  • A+
所属分类:未分类
摘要

画法绘制多边形这个标签绘制多边形绘制多边形的渐变单线定义渐变元素右图是gradientUnits=objectBoundingBox,它绘制出来的渐变线段是一致的,但垂直的线段无法绘制。画法绘制多边形绘制多边形的渐变单线的动画主要是使用了requestAnimationFrame函数,每帧绘制。

最近收到一个请求,要根据用户6个项目的完成情况显示1、2、3、4、5、6个正六边形,但后续要每条边都动画化并引导到每个角。

大概疗效如图所示:

这时候我就想有什么办法可以更快的实现呢?

计算六边形点的位置

无论我们使用canvas还是svg,我们仍然需要知道绘制点的位置,所以我们第一步就是询问每个点的位置(我不会告诉你svg画六边形,这篇文章的主要目的是记住这个估计... )

由于这里使用的都是正n边形,因此可以根据角度和直径计算出每个点的位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

画六边形怎么画_svg画六边形_画六边形的简易画法

let len = 6;
// 正多边形的点位置
let points = [];
// 内角角度
let angle = 360 / len;
// 半径
let radio = 100;
// 控制方向,i从0-len算,顺时针绘制,i从len-0,逆时针绘制
for (let i = len; i > 0; i--) {
// 270是控制初始点位置
var x = Math.cos(((i * angle + 270) / 180) * Math.PI);
var y = Math.sin(((i * angle + 270) / 180) * Math.PI);
// 如果只有1个时,放圆心
if (len === 1) {
x = 0;
y = 0;
}
let sx = x * radio + radio;
let sy = y * radio + radio;
points.push(sx, sy);
}

轮廓六边形svg绘制方法 轮廓五边形

svg中有一个polygon标签可以绘制五边形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

<svg
width="100%"
height="100%"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 200 200"
>
<polygon
points="100 0
13.397 50
13.397 150
100 200
186.602 150
186.602 50"
stroke="#242d50"
fill="transparent"
stroke-width="2"
stroke-linejoin="miter"
stroke-linecap="butt"
/>
</svg>

勾勒出六边形的渐变单线来定义渐变元素

svg画六边形_画六边形怎么画_画六边形的简易画法

1
2
3
4
5
6
7
8
9
10
11
12
13

<defs>
<linearGradient id="Gradient1" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#c25813" />
<stop offset="50%" stop-color="#c28112" />
<stop offset="100%" stop-color="#caac11" />
</linearGradient>
<filter id="f1" x="0" y="0" width="100%" height="100%">
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="2" />
</filter>
</defs>

如右图所示,垂直线外圆的宽度为0svg画六边形,这样就无法绘制渐变线,但非垂直线可以

右图中,左图是gradientUnits="userSpaceOnUse",可以绘制垂直渐变线段,但是这里的渐变颜色范围是整个svg而不是单个线段(导致每条线段的渐变不一致);

下图是gradientUnits="objectBoundingBox",它绘制的渐变线段是一致的,但是无法绘制垂直线段。

画六边形的简易画法_svg画六边形_画六边形怎么画

定义单线并使用渐变元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

<g class="active">
<line
x1="100"
x2="13.397"
y1="0"
y2="50"
stroke="#535244"
stroke-width="4"
filter="url(#f1)"
/>
<line
x1="100"
x2="13.397"
y1="0"
y2="50"
stroke="url(#Gradient1)"
stroke-width="2"
/>
</g>

单行动漫

使用strike-dasharray和css3动画来实现动画。 当需要动画的时候,给对应的元素添加active类,这样就可以显示动画了

svg画六边形_画六边形的简易画法_画六边形怎么画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

.active line {
fill: transparent;
stroke-dasharray: 100px;
animation-name: outline;
animation-duration: 0.5s;
animation-timing-function: ease-in-out;
animation-fill-mode: both;
}
@keyframes outline {
0% {
stroke-dashoffset: 100px;
}
100% {
stroke-dashoffset: 0;
}
}

canvas绘制方法绘制六边形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

let canvas = document.getElementById('polyline');
let devicePixelRatio = window.devicePixelRatio;
let width = Math.min(canvas.width, canvas.height);
// 考虑高清屏
canvas.width = width * devicePixelRatio;
canvas.height = width * devicePixelRatio;
// 计算绘制的多边形的半径
let radio = canvas.width / 2;
let len = 6;
let angle = 360 / len;
let points = [];
for (let i = len; i > 0; i--) {
// 270 控制初始点位置
var x = Math.cos(((i * angle + 270) / 180) * Math.PI);
var y = Math.sin(((i * angle + 270) / 180) * Math.PI);
// 如果只有1个时,放圆心
if (len === 1) {
x = 0;
y = 0;
}
let sx = x * radio + radio;
let sy = y * radio + radio;
points.push(sx, sy);
}
let ctx = canvas.getContext('2d');
// 绘制正六边形
ctx.beginPath();
for (let i = 0; i < points.length; i += 2) {
let fn = 'lineTo';
if (i === 0) {
fn = 'moveTo';
}
console.log(points[i], points[i + 1]);
ctx[fn](points[i], points[i + 1]);
}
ctx.closePath();
ctx.lineWidth = 2 * devicePixelRatio;
ctx.strokeStyle = '#242d50';
ctx.stroke();
// 将点闭合
points.push(points[0], points[1]);
// 动画绘制单线
animateDrawLine(canvas, points[0], points[1], points[2], points[3]);

渐变单线勾勒出六边形

svg画六边形_画六边形的简易画法_画六边形怎么画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

// 绘制渐变色单线
for (let i = 0; i < points.length - 2; i += 2) {
// 底线虚化,使用shadowBlur 属性实现
ctx.shadowBlur = 6;
ctx.shadowColor = '#535244';
//由于每条线的渐变位置不同,所以需每次都重新定义
let gradient = ctx.createLinearGradient(
points[i],
points[i + 1],
points[i + 2],
points[i + 3]
);
gradient.addColorStop('0', '#caac11');
gradient.addColorStop('0.5', '#c28112');
gradient.addColorStop('1.0', '#c25813');
ctx.strokeStyle = gradient;
ctx.beginPath();
ctx.moveTo(points[i], points[i + 1]);
ctx.lineTo(points[i + 2], points[i + 3]);
ctx.stroke();
}

单行动漫

画布的动画主要使用requestAnimationFrame函数来绘制每一帧。 这里的animate是一个自己封装的动画类,它给出开始状态、结束状态和持续时间,在onTick函数中估计中间状态,然后自己处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

function animateDrawLine(canvas, x1, y1, x2, y2, duration = 500) {
console.log(x1, y1, x2, y2);
let ctx = canvas.getContext('2d');
let gradient = ctx.createLinearGradient(x1, y1, x2, y2);
gradient.addColorStop('0', '#caac11');
gradient.addColorStop('0.5', '#c28112');
gradient.addColorStop('1.0', '#c25813');
let lastX = x1;
let lastY = y1;
new Animate({
start: {
x: x1,
y: y1
},
end: {
x: x2,
y: y2
},
during: duration,
onTick: function(value) {
let { x, y } = value;
// 由于这里没有clear掉之前画的内容,如果用showdow的话,上一帧绘制的阴影会影响下一帧的
// ctx.shadowBlur=6;
// ctx.shadowColor="#535244";
// 改用filter只绘制当前帧的小段距离
ctx.filter = 'blur(6px)';
ctx.strokeStyle = '#535244';
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(x, y);
ctx.stroke();
// 如果下面的线也是只画当前帧的小段距离的话,会有间隙
ctx.filter = 'none';
ctx.strokeStyle = gradient;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x, y);
ctx.stroke();
lastX = x;
lastY = y;
}
});
}

异同比较

svg/canvas 轮廓正多边形演示

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: