欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > Konva画布缩放

Konva画布缩放

2024/10/25 7:22:44 来源:https://blog.csdn.net/wj0712/article/details/143217161  浏览:    关键词:Konva画布缩放

滚动鼠标,可以缩放画布

<template><div class="rect"><div id="canvas"></div> <!-- 画布容器 --></div>
</template><script setup lang="ts">
import { onMounted } from 'vue'; // 导入 Vue 的 onMounted 钩子
import Konva from 'konva'; // 导入 Konva 图形库// 声明 stage、layer 和 transformer
let stage: Konva.Stage | null = null; // 初始化 stage 为 null
const layer: Konva.Layer = new Konva.Layer(); // 创建一个新的图层
const tr: Konva.Transformer = new Konva.Transformer(); // 创建一个 Transformer 用于选中和调整形状// 在组件挂载后初始化
onMounted(() => {init(); // 调用初始化函数
});const init = () => {const el = document.getElementById("canvas"); // 获取画布 DOM 元素if (!el) {return; // 如果没有找到画布元素,结束函数}const { clientWidth, clientHeight } = el; // 获取画布的宽度和高度// 创建一个 Konva Stage 平台stage = new Konva.Stage({container: 'canvas', // 指定画布容器width: clientWidth, // 设置宽度height: clientHeight, // 设置高度});stage.add(layer); // 将层添加到舞台// 创建第一个矩形const rect1 = new Konva.Rect({name: "rect", // 给图形添加名称x: clientWidth / 2 - 100, // 设置 x 坐标y: clientHeight / 2, // 设置 y 坐标width: 200, // 矩形的宽度height: 100, // 矩形的高度fill: "#ff8800", // 填充颜色stroke: 'black', // 边框颜色strokeWidth: 1, // 边框宽度draggable: true, // 设置可拖拽});layer.add(rect1); // 将第一个矩形添加到图层// 创建第二个矩形const rect2 = new Konva.Rect({name: "rect", // 同样的名称,可能导致选择问题x: clientWidth / 2 + 100, // 设置 x 坐标y: clientHeight / 2, // 设置 y 坐标width: 200, // 矩形的宽度height: 100, // 矩形的高度fill: "#ff00ff", // 填充颜色stroke: 'black', // 边框颜色strokeWidth: 1, // 边框宽度draggable: true, // 设置可拖拽});layer.add(rect2); // 将第二个矩形添加到图层// 新增一个矩形用于框选功能const selectionRect = new Konva.Rect({fill: "rgba(0,0,255,0.1)", // 填充颜色visible: false, // 初始时隐藏stroke: "rgba(0,0,255,0.5)", // 边框颜色strokeWidth: 1, // 边框宽度});layer.add(selectionRect); // 将选择矩形添加到图层layer.add(tr); // 将 Transformer 添加到图层// 点击图形时进行编辑,点击画布则取消编辑stage.on("click tap", (e) => {const dom = e.target; // 获取点击的目标if (dom.getType() === "Shape") { // 判断目标是否为形状tr.nodes([dom]); // 选中该形状} else {tr.nodes([]); // 如果点击的是画布,则清空选中}});let x1 = 0, y1 = 0, x2 = 0, y2 = 0; // 初始化坐标变量// 鼠标按下时开始框选stage.on("mousedown touchstart", (e) => {if (e.target !== stage) { // 如果点击的不是画布return; // 结束函数}e.evt.preventDefault(); // 阻止默认行为// 获取鼠标位置const { x, y } = stage.getRelativePointerPosition() as Konva.Vector2d;x1 = x; // 记录起始点 x 坐标x2 = x; // 记录起始点 x 坐标y1 = y; // 记录起始点 y 坐标y2 = y; // 记录起始点 y 坐标selectionRect.visible(true); // 显示选择框selectionRect.width(0); // 初始化宽度为 0selectionRect.height(0); // 初始化高度为 0});// 鼠标移动时更新选择框stage.on("mousemove touchmove", (e) => {if (!selectionRect.visible()) { // 如果选择框不可见return; // 结束函数}const { x, y } = stage.getPointerPosition() as Konva.Vector2d; // 获取当前鼠标位置x2 = x; // 更新结束点 x 坐标y2 = y; // 更新结束点 y 坐标// 更新选择矩形的属性selectionRect.setAttrs({x: Math.min(x1, x2), // 设置选择框的 x 坐标y: Math.min(y1, y2), // 设置选择框的 y 坐标width: Math.abs(x1 - x2), // 设置选择框的宽度height: Math.abs(y1 - y2), // 设置选择框的高度});});// 鼠标松开时完成选择stage.on("mouseup touchend", (e) => {if (!stage || !selectionRect.visible()) { // 如果舞台不存在或选择框不可见return; // 结束函数}// 隐藏选择框selectionRect.visible(false);// 获取所有矩形形状并进行选择const shapes = stage.find(".rect"); // 查找所有矩形const box = selectionRect.getClientRect(); // 获取选择框的边界const selected = shapes.filter((shape) =>Konva.Util.haveIntersection(box, shape.getClientRect()) // 判断是否与选择框相交);tr.nodes(selected); // 将选中的形状传给 Transformer});/缩放/const SCALE_BY = 1.1; // 缩放倍数stage.on("wheel", (e) => {console.log('wheel event triggered'); // 检查事件触发e.evt.preventDefault(); // 阻止默认的页面滚动if (!stage) return; // 如果 stage 没有初始化,则退出// 获取当前舞台的缩放比例const oldScale = stage.scaleX();// 获取鼠标指针在舞台坐标系内的位置const pointer = stage.getPointerPosition() as Konva.Vector2d;if (!pointer) return; // 如果鼠标位置无效,退出// 计算当前鼠标点在缩放前的相对位置const mousePointTo = {x: (pointer.x - stage.x()) / oldScale,y: (pointer.y - stage.y()) / oldScale,};// 判断滚轮方向:deltaY > 0 表示缩小,< 0 表示放大let direction = e.evt.deltaY > 0 ? -1 : 1;// 支持 ctrl 键反转缩放方向(可选功能)if (e.evt.ctrlKey) {direction = -direction;}// 根据滚轮方向计算新的缩放比例const newScale = direction > 0 ? oldScale * SCALE_BY : oldScale / SCALE_BY;// 更新舞台的缩放比例stage.scale({ x: newScale, y: newScale });// 计算缩放后舞台新的位置,以保持鼠标相对位置不变const newPos = {x: pointer.x - mousePointTo.x * newScale,y: pointer.y - mousePointTo.y * newScale,};// 设置舞台的新位置stage.position(newPos);// 使用 batchDraw 来优化更新频率stage.batchDraw();});}
</script><style scoped lang="scss">
.rect {padding: 20px; // 设置外边距#canvas {background-color: #eee; // 设置背景颜色border: 1px solid #666; // 设置边框height: calc(100vh - 42px); // 设置画布高度}
}
</style>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com