如何访问原生 2D 上下文
如何从 Konva 访问原生 2D Canvas 上下文
Konva 为您提供了一个用于在 Canvas 上绘制形状的对象模型。应用从 div 中的 Stage 开始。Stage 包含一个或多个 Layer。每个 Layer 使用 Canvas 元素。
您可以访问内部 Canvas 上下文,并在不使用 Konva 形状的情况下进行绘制。此方法并不安全。Konva 控制 Layer 的绘制,因此可能会擦除手动绘制的内容。诸如 stage.toDataURL() 之类的导出操作也可能遗漏这些内容。
请使用以下方法之一进行手动绘制:
- 使用自定义形状。
- 创建一个 Canvas 元素,并将其用作
Konva.Image的源。
这两种方法都会将绘制内容保留在 Konva 的场景图和导出流程中。
- 原生
- React
- Vue
import Konva from 'konva';
const width = window.innerWidth;
const height = window.innerHeight;
const stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
const layer = new Konva.Layer();
stage.add(layer);
// 如果你想使用原生 2d 画布操作
// 可以创建一个画布用于 Konva.Image
const canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 150;
const ctx = canvas.getContext('2d');
const image = new Konva.Image({
x: 50,
y: 50,
image: canvas,
draggable: true,
});
layer.add(image);
// 手动绘制内容
ctx.fillStyle = 'blue';
ctx.fillRect(5, 5, canvas.width - 10, canvas.height / 2);
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2 * Math.PI);
ctx.fill();
// 由于画布已更新,需要重绘图层
layer.batchDraw();
import { Stage, Layer, Image } from 'react-konva';
import { useMemo, useState } from 'react';
const App = () => {
const [position, setPosition] = useState({ x: 50, y: 50 });
const canvas = useMemo(() => {
const canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 150;
const ctx = canvas.getContext('2d');
// 手动绘制内容
ctx.fillStyle = 'blue';
ctx.fillRect(5, 5, canvas.width - 10, canvas.height / 2);
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2 * Math.PI);
ctx.fill();
return canvas;
}, []);
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Image
x={position.x}
y={position.y}
image={canvas}
draggable
onDragEnd={(e) => {
setPosition({
x: e.target.x(),
y: e.target.y(),
});
}}
/>
</Layer>
</Stage>
);
};
export default App;
<template>
<v-stage :config="stageSize">
<v-layer>
<v-image
:config="{
x: position.x,
y: position.y,
image: canvas,
draggable: true,
}"
@dragend="handleDragEnd"
/>
</v-layer>
</v-stage>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const stageSize = {
width: window.innerWidth,
height: window.innerHeight
};
const position = ref({ x: 50, y: 50 });
const canvas = ref(null);
onMounted(() => {
const canvasEl = document.createElement('canvas');
canvasEl.width = 200;
canvasEl.height = 150;
const ctx = canvasEl.getContext('2d');
// 手动绘制内容
ctx.fillStyle = 'blue';
ctx.fillRect(5, 5, canvasEl.width - 10, canvasEl.height / 2);
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2 * Math.PI);
ctx.fill();
canvas.value = canvasEl;
});
const handleDragEnd = (e) => {
position.value = {
x: e.target.x(),
y: e.target.y(),
};
};
</script>