如何访问原生 2d 上下文
如何从 Konva 访问原生 2d 画布上下文
Konva 为你提供了在画布上绘制图形的对象模型。你的应用从一个舞台(div 容器)开始,舞台内有一个或多个图层(canvas DOM 元素)。
你可以深入 Konva 内部(或 DOM 内部)直接在画布上绘图而不创建任何形状。但这不推荐。因为 Konva 完全控制绘图,可能会重置你的手动绘制内容,或者在任何导出操作(比如 stage.toDataURL()
)时丢失它们。
如果你想手动绘制,推荐有两种方式:
- 使用自定义形状
- 手动创建一个新的 canvas 元素,然后将其用于
Konva.Image
。
- Vanilla
- 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>