Stage
+------+------+
| |
Layer Layer
| |
+-----+-----+ Shape
| |
Group Group
| |
+ +---+---+
| | |
Shape Group Shape
Shape
Stage(容器)
在 Konva 中,一切的开端始于 Konva.Stage
这个类,它包含了用户定义的 Konva.Layer
,可以说 Stage 是 Konva 的容器,我们的图形都存在于这里面。
在 H5 中,Stage 表现为一个普通的 div 标签,例如,创建一个 Konva 容器:
file:[创建 Konva.Stage]
<div id="container"></div>
<script>
// stage 是一个容器,装所有的 layer
const stage = new Konva.Stage({
container: "container", // id 选择器
width: window.innerWidth,
height: window.innerHeight
</script>
</body>
Layer(图层)
如上结构所示,Stage 下面有许多 Layer(图层),图层在 PS、绘画中很容易出现,我们可以理解图层中包含了许多的 Shapes(图形)、组(Group)。
<div id="container"></div>
<script>
// stage 是一个容器,装所有的 layer
const stage = new Konva.Stage({
container: "container",
width: window.innerWidth,
height: window.innerHeight
// 创建图层1
const layer1 = new Konva.Layer();
// 创建 rect1
const rect1 = new Konva.Rect({
x: 20,
y: 20,
width: 100,
height: 50,
fill: "green",
stroke: "black",
strokeWidth: 2
// 把 rect1 添加到图层1中,一个图层有许多的图形、组。
layer1.add(rect1);
const layer2 = new Konva.Layer();
const rect2 = new Konva.Rect({
x: 150,
y: 40,
width: 100,
height: 50,
fill: "red",
shadowBlur: 10,
cornerRadius: 10
layer2.add(rect2);
const layer3 = new Konva.Layer();
const rect3 = new Konva.Rect({
x: 50,
y: 120,
width: 100,
height: 100,
fill: "blue",
cornerRadius: [0, 10, 20, 30]
const rect4 = new Konva.Rect({
x: 250,
y: 150,
width: 100,
height: 100,
fill: "#525288",
cornerRadius: 5
layer3.add(rect3);
layer3.add(rect4);
// 把图层1、2、3添加到容器中
stage.add(layer1);
stage.add(layer2);
stage.add(layer3);
</script>
</body>
JS 代码解释
如上所示中,我创建了三个 Layer,每一个图层都有一个矩形(Shape),Layer 图层创建好了之后把它放入 Stage 中。
每一个图形都可以自定义样式,如圆角、填充颜色、宽度、高度等。
H5 结构解释
如上图所示,容器下面有三个 canvas 标签,正好对应了我们三个图层(Layer),图层中有自己的图形(Shape)。
我们可以很容易地使用 Konva 提供的输入事件:click(点击)、dblclick(双击)、mouseover(鼠标移入)、tap(移动端点击)、dbltap(移动端双击)、touchstart(点击开始)。
以及,属性点击事件:sacleXChange、FillChange;拖拽&松手事件:dragstart、dragmove、dragend。
const rect4 = new Konva.Rect({
x: 250,
y: 150,
width: 100,
height: 100,
fill: "#525288",
cornerRadius: 5
rect4.on("mouseout", e => {
console.log(e);
rect4.draggable("true");
Konva.js 有两种方式创建动画,这里我演示其中一种:通过 Konva.Animation
类实现。另一种方式查看官方文档:Konva - Animation。
const layer = new Konva.Layer();
const rect = new Konva.Rect({
x: 250,
y: 150,
width: 100,
height: 100,
fill: "#525288",
cornerRadius: 5
layer.add(rect);
const animation = new Konva.Animation(frame => {
const B = frame.time / 2000;
const radian = 2 * Math.PI;
rect.x(200 * Math.sin(radian * B));
}, layer);
animation.start();
Konva.Animation
对象中传递一个回调函数以及第二个参数图层对象(Layer),在前面中说到,一个图层在 H5 中就是一个 canvas 标签(Canvas 对象)。我认为,一个图层拥有一个动画比较合理。
tip:[start]在使用 Konva.Animation
创建动画时,针对的是一个图层(Layer),也就是一个 Canvas 中对应一个动画,每过一个帧就会执行一次回调,所以在回调中改变某图层的图形 tip:[end]
分析回调代码
const animation = new Konva.Animation(frame => {
const B = frame.time / 2000;
const radian = 2 * Math.PI;
rect.x(200 * Math.sin(radian * B));
}, layer);
一旦程序运行,Konva.Animation
就会每一帧执行一次回调函数并传递一个变量 frame
,这个 frame 包含了从开始到现在距离的毫秒数(也就是从程序开始到目前已经过去了多少毫秒)。
在回调中,我修改 rect 图形的 x 轴,使其能够周期性地、规律地、连续地运动,我们可以通过 Math.sin
(正弦函数)或者 Math.cos
(余弦函数)来让它保持一个周期性地、规律地、连续地运动。cos 和 sin 都是连续的函数,tan 函数周期之间有断开,不适合做一个连续地运动。
frame.time
来自于 Animation 回调的变量,只需调节 2000 这个值的大小就可以改变这个图形动画运行的速度(快慢)。
sin 函数
\[y = A * sin(B * x)
振幅 A 影响 sin 函数的谷峰和谷底之间的差距。意思是说,A 越大,两者距离越高,那么这个图形水平移动的距离就越长,反之越短。
周期因子 B 决定了正弦函数图像重复自身的水平距离。意思是说,B 越大,一个周期就拉的越长,图形从一个周期开始到周期结束的水平距离就越长,那么这个图形在一个周期内走完所需要的时间就越长,反之越短。
因此,B 才是影响动画快慢的变量。