首先先看效果看是否是你想要效果
这里主要使用canvas 的drawImage方法
context
.drawImage(img
,sx
,sy
,swidth
,sheight
,x
,y
,width
,height
);
参数描述
img规定要使用的图像、画布或视频。sx可选。开始剪切的 x 坐标位置。sy可选。开始剪切的 y 坐标位置。swidth可选。被剪切图像的宽度。sheight可选。被剪切图像的高度。x在画布上放置图像的 x 坐标位置。y在画布上放置图像的 y 坐标位置。width可选。要使用的图像的宽度。(伸展或缩小图像)height可选。要使用的图像的高度。(伸展或缩小图像)
原理及用法(下方有完整代码组件)
1、首先 创建 画布 使用 id绑定
<canvas
:id
="`circle(1)${index}`"></canvas
>
2、获取画布 获取绘图工具
const cvs
= document
.getElementById('circle(1)'+this.index
);
const ctx
= cvs
.getContext("2d");
3、获取需要绘制的图片 首先先创建图片,再使用canvas绘制出来 注意点:由于图片加载需要时间 是异步的,所以需要等图片加载完成创建dom后,canvas才能绘制出来
const img
= document
.createElement("img");
img
.src
= this.list
.img
;
ctx
.drawImage(img
,0,0);
这里我给出参考图片
4、使用定时器setInterva进行刷新 产生帧动画 注意点:定时刷新时 如果canvas 没有设置宽度和高度会出现重影效果,因为重新设置宽度和高度相当于重绘了,关闭页面时记得清理定时器 问题效果
setInterval(() => {
cvs
.width
= radius
* 2;
cvs
.height
= radius
* 2;
},20)
5、旋转 及计算出旋转的角速度 使用ctx.rotate();进行旋转 注意点1:旋转时需要设置偏移,保证为中心旋转,先偏移再旋转后在纠正回来。 注意点2:旋转了多少 后面就要 反旋转回来 不然会导致旋转累加,实际效果和最终效果会产生有很大的区别 计算旋转角速度(1°/s):转换为rad/s及(1度/秒),定时器设置的刷新时间为fps(毫秒) ,1°=π/180,设置speed单位为(1°/s),最终可以算出 旋转度数= speed*fps/10000
ctx
.translate(radius
, radius
);
ctx
.rotate(rotate
);
ctx
.translate(-radius
, -radius
);
ctx
.drawImage(img
,0,0);
ctx
.translate(radius
, radius
);
ctx
.rotate(-rotate
);
ctx
.translate(-radius
, -radius
);
6、画布上居中 context.drawImage();方法有三种写法
context
.drawImage(img
,sx
,sy
);
context
.drawImage(img
,sx
,sy
,swidth
,sheight
);
context
.drawImage(img
,sx
,sy
,swidth
,sheight
,x
,y
,width
,height
);
图片在画布上居中需要使用第三种完整写法 计算居中
x
= 画布宽度
/2 - 图片宽度
/2;
y
= 画布高度
/2 - 图片高度
/2;
vue组件完整代码(供参考缺失部分css样式)
<template
>
<div id
="paralist" class="row">
<div
class="list-left">
<canvas
:id
="`circle(1)${index}`"></canvas
>
<!-- <div
>
<span
class="span-mini">{{this.list
.parameter
}}</span
>
</div
> -->
</div
>
<!-- <div
class="list-right">
<div
class="normal" v
-if="this.list.status=='正常'">
<span
class="span-mini">正常
</span
>
</div
>
<div
class="unusual" v
-else-if="!(this.list.status=='正常')">
<span
class="span-mini">
{{this.list
.describe
}}
<br
/>
<span
class="unusual-bottom span-mini" @click
="this.popup">处理
</span
>
</span
>
</div
>
</div
> -->
</div
>
</template
>
<script
>
export default {
props
: ["list", "index"],
data() {
return {
angleTimer
: "",
radius
: 105 / 2,
imgModule
: [
{
src
: this.list
.img
,
dom
: "",
distance
: 0,
speed
: 0,
angle
: 0,
rotate
: 0,
sx
: 0,
sy
: 0,
swidth
: this.radius
* 2,
sheight
: this.radius
* 2,
x
: "",
y
: "",
width
: this.radius
* 2,
height
: this.radius
* 2,
},
{
src
: require("@/assets/images2/circle1/资源 88.png"),
dom
: "",
distance
: 0,
speed
: 0.5 * 360,
angle
: 1,
rotate
: 0,
sx
: 0,
sy
: 0,
swidth
: this.radius
* 2,
sheight
: this.radius
* 2,
x
: "",
y
: "",
width
: this.radius
* 2,
height
: this.radius
* 2,
},
{
src
: require("@/assets/images2/circle1/资源 87.png"),
dom
: "",
distance
: 0,
speed
: 0,
angle
: 0,
rotate
: 0,
sx
: 0,
sy
: 0,
swidth
: this.radius
* 2,
sheight
: this.radius
* 2,
x
: "",
y
: "",
width
: this.radius
* 2,
height
: this.radius
* 2,
},
{
src
: require("@/assets/images2/circle1/资源 86.png"),
dom
: "",
distance
: 0,
speed
: 0.2 * 360,
angle
: -1,
rotate
: 0,
sx
: 0,
sy
: 0,
swidth
: this.radius
* 2,
sheight
: this.radius
* 2,
x
: "",
y
: "",
width
: this.radius
* 2,
height
: this.radius
* 2,
},
],
};
},
mounted() {
this.draw("circle(1)" + this.index
);
},
beforeDestroy() {
if (this.angleTimer
) {
clearInterval(this.angleTimer
);
}
},
methods
: {
routerTo() {
this.$store
.commit("setIsBack", true);
this.$router
.push({
path
: "/dw/equipmentAlert",
});
},
popup() {
alert("弹窗!");
},
draw(id
, fps
= 20) {
const radius
= this.radius
;
const imgModule
= this.imgModule
;
const img
= document
.createElement("img");
img
.src
= this.list
.img
;
imgModule
.forEach((item
) => {
item
.dom
= document
.createElement("img");
item
.dom
.src
= item
.src
;
});
const cvs
= document
.getElementById(id
);
const ctx
= cvs
.getContext("2d");
if (this.angleTimer
) {
clearInterval(this.angleTimer
);
}
this.angleTimer
= setInterval(() => {
cvs
.width
= radius
* 2;
cvs
.height
= radius
* 2;
let rotateTotal
= 0;
imgModule
.forEach((item
, index
) => {
item
.distance
+= (item
.speed
* fps
) / 1000;
if (item
.distance
% 360 == 0) {
item
.distance
= 0;
}
let rotate
=
(-item
.rotate
* Math
.PI) / 180 +
(item
.angle
* item
.distance
* Math
.PI) / 180;
rotateTotal
+= rotate
;
let naturalWidth
= item
.dom
.naturalWidth
;
let naturalHeight
= item
.dom
.naturalHeight
;
ctx
.translate(radius
, radius
);
ctx
.rotate(rotate
);
ctx
.translate(-radius
, -radius
);
ctx
.drawImage(
item
.dom
,
item
.sx
|| 0,
item
.sy
|| 0,
item
.swidth
|| cvs
.width
,
item
.sheight
|| cvs
.height
,
(item
.x
= (radius
* 2) / 2 - naturalWidth
/ 2 || 0),
(item
.y
= (radius
* 2) / 2 - naturalHeight
/ 2 || 0),
item
.width
|| cvs
.width
,
item
.height
|| cvs
.height
);
ctx
.translate(radius
, radius
);
ctx
.rotate(-rotate
);
ctx
.translate(-radius
, -radius
);
});
}, fps
);
},
},
};
</script
>
<style lang
="less" scoped
>
.row
{
background
: transparent
;
margin
-top
: 0;
}
#paralist
{
width
: 220px
;
min
-width
: 220px
;
height
: 100%;
display
: flex
;
justify
-content
: center
;
align
-items
: center
;
.list
-left
{
flex
: 1;
img
{
max
-width
: 105px
;
max
-height
: 113px
;
}
div
{
box
-sizing
: border
-box
;
span
{
font
-size
: 15pt
;
color
: #def5fe
;
}
}
}
.list
-right
{
flex
: 1;
height
: 100%;
position
: relative
;
.normal
{
height
: 100%;
position
: relative
;
span
{
font
-size
: 14pt
;
position
: absolute
;
left
: 10%;
top
: 50%;
transform
: translateY(-100%);
}
}
.unusual
{
position
: absolute
;
top
: 10%;
text
-align
: left
;
span
{
display
: inline
-block
;
font
-size
: 8pt
;
color
: red
;
}
.unusual
-bottom
{
color
: hsl(190, 99%, 51%);
border
-bottom
: 1px solid #
06d6fe
;
cursor
: pointer
;
}
}
}
}
</style
>