当前位置: 首页 > article >正文

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.getPointerPosition() as Konva.Vector2d;
    x1 = x; // 记录起始点 x 坐标
    x2 = x; // 记录起始点 x 坐标
    y1 = y; // 记录起始点 y 坐标
    y2 = y; // 记录起始点 y 坐标
    selectionRect.visible(true); // 显示选择框
    selectionRect.width(0); // 初始化宽度为 0
    selectionRect.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
  });
}
</script>

<style scoped lang="scss">
.rect {
  padding: 20px; // 设置外边距

  #canvas {
    background-color: #eee; // 设置背景颜色
    border: 1px solid #666; // 设置边框
    height: calc(100vh - 42px); // 设置画布高度
  }
}
</style>

 逻辑过程

逻辑步骤说明

  1. 创建画布容器 - 在模板中定义画布的容器。
  2. 导入 Vue 和 Konva - 引入所需的库和模块。
  3. 初始化变量 - 创建舞台、层和变换器的实例。
  4. 挂载后初始化 - 在组件挂载时调用初始化函数。
  5. 获取 DOM 元素 - 获取画布的 DOM 元素,准备进行绘制。
  6. 创建舞台 - 创建 Konva 的舞台实例,并设置画布的尺寸。
  7. 添加层到舞台 - 将图层添加到舞台,以便在其上绘制图形。
  8. 创建矩形 - 依次创建第一个和第二个矩形,并设置其属性。
  9. 添加矩形到层 - 将创建的矩形添加到图层。
  10. 创建选择矩形 - 创建一个用于框选的矩形,但初始时设置为不可见。
  11. 处理点击事件 - 为舞台添加点击事件,以便选择图形或清空选择。
  12. 鼠标事件处理 - 处理鼠标按下、移动和松开事件以实现框选功能。
  13. 更新选择框 - 在鼠标移动时更新选择框的位置和大小。
  14. 完成选择 - 在鼠标松开时,计算选择的矩形,并将其传递给变换器。
  15. 样式设置 - 最后设置样式,定义画布的外观

 

 


http://www.kler.cn/news/363331.html

相关文章:

  • js中for...in 和 for...of 区别
  • Clickhouse笔记(二) 集群搭建
  • linux笔记(SSH)
  • React与TypeScript
  • MySQL - Navicat自动备份MySQL数据
  • Excel常用操作培训
  • PPT自动化:掌握 python-pptx 的基础元素
  • 20240818 字节跳动 笔试
  • Python小游戏11——扑克牌消消看小游戏
  • Go入门指南-3.1Go 开发环境的基本要求
  • 哈夫曼树的定义?如何构造?
  • XJ03、消费金融|从场景实例看懂背后的系统架构
  • Xcode使用的一些问题记录
  • 图文深入介绍oracle资源管理(续)
  • Pyspark中pyspark.sql.functions常用方法(4)
  • 机器学习运维(MLOps)
  • 考研篇——数据结构王道3.2.3_队列的链式实现
  • 2025年考PMP大概需要多少钱?提前了解!
  • 【计算机网络 - 基础问题】每日 3 题(四十六)
  • MBI6665Q聚积升降压LED驱动芯片车规级AEC-Q100认证
  • 从0开始深度学习(15)——权重衰退法(L2正则化)
  • 5. AOP
  • 口含烟贴纸设计公司哪家好?
  • docker之redis安装(项目部署准备)
  • 从 0 开发一个系统
  • 渗透测试+oneforall+nmap+zenmap+7kbscan+dic+pkav+御剑+netcat