继续发明,加速成长!这是我参加「日新计划 10 月更文挑战」的第 8 天,点击查看活动详情
1. Vue 中运用 ZRender
上一篇中,咱们经过最原始的方法体会了一下 ZRender
的运用。接下来,为了更便利办理制作测试作用,运用 Vue
结构集成 ZRender
库。看完本篇应该能体会出这个办理的必要性,咱们要完结如下的制作样例展现作用:
如下,经过 vue cli
创立一个 zrender-player
的项目,这儿组件运用类的方法 : class-component
----> vue -V
@vue/cli 5.0.8
----> vue create zrender-player
然后经过经过 npm
装置 zrender
:
----> npm install zrender
如下所示,界说一个 PaperBox
组件来展现制作的单体,其间组件的布局结构和款式基于 【上一篇】 完成,界说 PaperBox
承继自 Vue
,作为独立的组件运用。界说 ZRenderType
类型的 render2d
私有成员,在 mounted
回调中初始化。
---->[PaperBox.vue]----
<template>
<div class="wrapper">
<div :id= label class="box"></div>
<span class="label">{{label}}</span>
</div>
</template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component';
import { ZRenderType } from "zrender";
import * as zrender from "zrender";
@Options({
props: {
leabel: String
}
})
export default class PaperBox extends Vue {
leabel!: string
private render2d? :ZRenderType;
mounted(){
this.render2d = zrender.init(document.getElementById(this.label))
}
</script>
<style scoped lang="scss">
//同上篇
</style>
2. 遇到问题 -> 剖析问题 -> 处理问题
在集成的过程中,没想到这么快就不得不瞄 ZRender
的源码。呈现了一个问题 :
Renderer 'undefined' is not imported. Please import it first.
遇到问题,不要怕,剖析问题是一项很重要的能力,自主处理问题
是累积经历的重要途径之一。过错呈现时,往往都会随同一些蛛丝马迹,如下所示,其间有过错时的栈信息:
点击栈信息,能够看到过错产生的位置:是在 ZRender
目标初始化时,能够在源码稍上一些点断掉调试一下:
重点是这段逻辑,核心目标是 painterCtors
和 rendererType
,其间 rendererType
是个字符串,在设置为项中为空时,运用 canvas
。 painterCtors
是一个目标,经过 rendererType
能够获取个东西,假如获取不到会出问题。
所以现在的显示是 painterCtors
目标,在 19
行中目标声明的场合,默许是的空目标。经过观察能够看到它现在仍是一个空目标,也便是说,没有为 painterCtors
增加内容是这个过错的本源:
然后追寻 painterCtors
的赋值情况,能够看到在 registerPainter
中会为 painterCtors
根据 name
设置 Ctor
目标。也便是说需求运用 registerPainter
方法来注册制作器,理论上来说 ZRender
应该会默许注册一个制作器,但现在来看,实践上没有。
所以想要处理这个问题,最简略的方法是手动注册一下, 如下在 mian.ts
中注册一下。
---->[main.ts]----
import { createApp } from 'vue'
import App from './App.vue'
import CanvasPainter from "zrender/lib/canvas/Painter"; // 引进 Canvas 制作器
import * as zrender from "zrender"; // 引进 zrender 制作器
zrender.registerPainter('canvas', CanvasPainter); // 注册制作器
createApp(App).mount('#app')
这样再调试时,就能够看到 painterCtors
目标在存在键值对,在网页中也能够正常显示制作的内容。别的假如需求制作 svg
的话,也能够注册一下 SVGPainter
。
别的,在 zrender
的 all.ts
中能够看到注册的逻辑,可是实践如同不起作用。网上对 zrender
在 Vue
中的集成文章都比较简略,没有呈现这个问题,可能是 Vue3
或者是 TS
引起的。至于详细的原因,咱们也不怎么清楚,期望在行的能够解释一下。好在这个小问题能够处理。
3. 封装制作单体
如下所示,现在的目标是让制作的单体能够顺次摆放展现,也便是说根据 数组数据
遍历显示 单体组件 PaperBox
。所以完成需求界说数据的安排方法,从展现的方法上来看,主要需求两个数据:标题
与 图元列表
,经过 ExModel
类对数据进行安排办理:
import * as zrender from "zrender";
export class ExModel {
label: string;
elements: zrender.Element[];
constructor(label: string, elements: zrender.Element[]) {
this.label = label;
this.elements = elements;
}
}
也便是说,ExModel
数据便是对制作样例的封装, 就代表一个数据,决定一个单体的体现。如下,运用 PaperBox
组件的处理对 ExModel
目标进行烘托呈现。
---->[PaperBox]----
<script lang="ts">
import { Options, Vue } from 'vue-class-component';
import { ZRenderType } from "zrender";
import * as zrender from "zrender";
import { ExModel } from '../examples/ExModel';
@Options({
props: {
model: ExModel,
}
})
export default class PaperBox extends Vue {
model!: ExModel
private render2d?: ZRenderType;
mounted() {
this.render2d = zrender.init(document.getElementById(this.model.label))
for (let i = 0; i < this.model.elements.length; i++) {
this.render2d.add(this.model.elements[i])
}
}
}
</script>
其间 Html
布局将之前的死数据经过 ExModel
目标进行呈现设置。其实从本质上来看,这和 Flutter
中的组件封装的思维并没有什么区别,都是经过 数据
来驱动 视图
。
<template>
<div class="wrapper">
<div :id=model.label class="box"></div>
<span class="label">{{model.label}}</span>
</div>
</template>
4. 数据的供给
单体组件封装结束后,接下来需求考虑数据的来源问题,这儿的数据自然是咱们自己发明的。如下,经过一个文件来统一收录数据, 其间每个 exModels
数组中的元素觉得一个样例的展现:
---->[examples/exData.ts]----
import polylineExs from './polyline';
import lineExs from './line';
import circleExs from './circle';
import rectExs from './rect';
import ellipsExs from './ellipse';
import { ExModel } from './ExModel';
const exModels = [
new ExModel('折线: Polyline',polylineExs),
new ExModel('直线: Line',lineExs),
new ExModel('圆形: CirCle',circleExs),
new ExModel('矩形: Rect',rectExs),
new ExModel('椭圆: Ellipse',ellipsExs),
];
export default exModels;
为了便利独立办理,这儿将每个样例放在一个文件在,比方下面是 polyline
的图元目标:
---->[examples/polyline.ts]----
import * as zrender from "zrender";
const polylineEx1 = new zrender.Polyline({
shape: {
points: [
[0, 50],
[10, 60,],
[20, 40,],
[30, 80,],
[40, 20,],
[50, 50,],
[60, 40,],
[100, 40,],
]
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
const polylineExs = [polylineEx1]
export default polylineExs;
5. 展现组件
这样数据和单体都预备结束,接下来遍历烘托即可,如下界说 ZrenderPage
组件,经过 v-for
指令遍历 exModels
的数据烘托 PaperBox
组件,即可完结显示:
<template>
<div class="container">
<PaperBox
v-for=" item ,i in models"
:key=i
:model=item
PaperBox />
</div>
</template>
<script lang="ts">
import { Options, Vue } from 'vue-class-component'
import exModels from '../examples/exData'
import { ExModel } from '../examples/ExModel';
import PaperBox from '../components/PaperBox.vue'
@Options({
props: {
leabel: String
},
components: {
PaperBox,
},
})
export default class ZrenderPage extends Vue {
leabel!: string
models: ExModel[] = exModels;
}
</script>
<style scoped lang="scss">
.container {
display: flex;
justify-items: center;
justify-items: center;
gap: 20px;
}
</style>
这样,假如需在界面上增加一个图元的样例,只需求在 exModels
中增加数据即可。比方现在想在界面中增加圆弧的样例。
只要在 exModels
中增加一个元素即可:
import * as zrender from "zrender";
const arcEx1 = new zrender.Arc({
shape: {
cx: 50,
cy: 50,
r: 40,
startAngle: 0,
endAngle: 135 * Math.PI / 180,
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
const arcExs = [arcEx1]
export default arcExs;
这样就能够将上一篇中制作的图元同屏展现,也便利接下来的制作测试。所以 Vue
经过组件化完成 数据
和 界面
的映射关系,关于批量同类视图的显示是很有利的。假如运用原始的 html
结构进行布局,一个个写出来将非常繁琐,并且难以保护。
5. 扇形区、多边形、正多边形、星形
扇形区
、多边形
、正多边形
、星形
别离经过 Sector
、Polygon
、Isogon
、Star
进行制作。简略看下作用,这儿就不细说特点了,想详细了解的能够参考官方文档:zrender-doc。官网的文档没有配图,这儿就当给文档配图了:
扇形区: Sector
扇形区域关于统计图中的 饼图
是非常重要的,它能够制作内外半径间的部分圆环区域。上图中红色区域是 sectorEx1
,黄色区域是 sectorEx2
:
const sectorEx1 = new zrender.Sector({
shape: {
cx: 50,
cy: 50,
r: 40,
r0: 30,
startAngle: 0,
endAngle: 135 * Math.PI / 180,
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
const sectorEx2 = new zrender.Sector({
shape: {
cx: 50,
cy: 50,
r: 40,
r0: 30,
startAngle: -90 * Math.PI / 180,
endAngle: -165 * Math.PI / 180,
clockwise: false
},
style: {
stroke: 'blue',
lineWidth: 1,
fill: 'yellow',
},
})
多边形: Polygon
多边形便是一个会主动封闭首尾的折线,也是指定 shape
中的点集进行连线:
const polygonEx1 = new zrender.Polygon({
shape: {
points: [
[0, 50],
[10, 60,],
[20, 40,],
[30, 80,],
[40, 20,],
[50, 50,],
[60, 40,],
[100, 40,],
]
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
正多边形: Isogon
const isogonEx1 = new zrender.Isogon({
shape: {
x: 50,
y: 50,
r: 40,
n: 8
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
星形: Star
const starEx1 = new zrender.Star({
shape: {
cx: 50,
cy: 50,
r: 40,
n: 7,
r0: 20,
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
6. 水滴、心形、玫瑰线、旋轮线、圆环
下面来看五个没啥大用的形状,水滴
、心形
、玫瑰线
、旋轮线
、圆环
别离经过 Droplet
、Heart
、Rose
、Trochoid
、Ring
进行制作。
水滴: Droplet
const dropletEx1 = new zrender.Droplet({
shape: {
cx: 50 ,
cy: 65,
width: 25,
height: 60,
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
心形: Heart
const heartEx1 = new zrender.Heart({
shape: {
cx: 50 ,
cy: 30,
width: 35,
height: 60,
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
玫瑰线: Rose
const roseEx1 = new zrender.Rose({
shape: {
cx: 50,
cy: 50,
r: [50],
k: 2,
n: 15
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
玫瑰线: Trochoid
其间 location 为out
表明外旋轮
,图中红线所示;in
表明内旋轮
,图中蓝线所示。
const trochoidEx1 = new zrender.Trochoid({
shape: {
cx: 50,
cy: 50,
r: 40,
r0: 5,
d:6 ,
location: 'out'
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
const trochoidEx2 = new zrender.Trochoid({
shape: {
cx: 50,
cy: 50,
r: 40,
r0: 5,
d:6 ,
location: 'in'
},
style: {
stroke: 'blue',
lineWidth: 1,
fill: 'none',
},
})
圆环: Ring
const ringEx1 = new zrender.Ring({
shape: {
cx: 50,
cy: 50,
r: 40,
r0: 30,
},
style: {
stroke: 'red',
lineWidth: 1,
fill: 'none',
},
})
到这儿,ZRender
中的 18
的根本图元的制作了解结束,并且经过 Vue
结构搭建了一个便利测试的环境。别的还有路径 Path
的制作这儿暂时不介绍,将在后期单独说明。那本文就到这儿,谢谢观看 ~
@张风捷特烈 2022.10.21 未允禁转
我的 大众号: 编程之王
-
我的 github 主页
: toly1994328