fabric.js实现鼠标左键框选截图

1.示例

大家先看看示例截图,fabric.js中文学习网址

请添加图片描述

2.实现步骤

  • 通过fabric.js将图片当做图片背景写入到canvas
  • 利用右键mouseup事件实现一个rect
  • 通过fabric.js新建一个image对象,将上面的rect坐标、宽高传入image的toDataUrl事件里面,直接转换成图片

3.源码

我采用的vue3.0, 所以大家新建一个vue3.0的项目,新建一个index.vue文件就可以跑起来了。

<script setup lang="ts">
import { onMounted, reactive } from "vue";
import { fabric } from "fabric";
const state = reactive<any>({
  // 储存截图区域的图片,自己传
  imgSrc:
    "https://img1.baidu.com/it/u=413643897,2296924942&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500", // 图片地址替换成自己的就行了。
  // 判断当前是否处于截图状态
  imgC: null, // fabric image实例
  imgUrl: "" // 截图的图片
});
let drawcanvas = null;

let downPoint = null; // 按下鼠标时的坐标
let upPoint = null; // 松开鼠标时的坐标

onMounted(() => {
  //绘制图片

  drawcanvas = new fabric.Canvas("drawcanvas", {});

  fabric.Image.fromURL(
    state.imgSrc,
    img => {
      console.log("🚀 ~ file: index.vue:44 ~ onMounted ~ img:", img);
      drawcanvas.setWidth(img.width);
      drawcanvas.setHeight(img.height);
      drawcanvas.setBackgroundImage(
        img,
        drawcanvas.renderAll.bind(drawcanvas),
        {
          crossOrigin: "anonymous"
        }
      );
      state.imgC = img;
      // img.selectable = false;
    },
    {
      crossOrigin: "anonymous"
    }
  );

  drawcanvas.on("mouse:down", canvasMouseDown); // 鼠标在画布上按下
  drawcanvas.on("mouse:up", canvasMouseUp); // 鼠标在画布上松开

  drawcanvas.on("object:rotating", canvasObjectRotating); // 鼠标在画布上松开
  drawcanvas.on("object:resizing", canvasObjectResizing); // 鼠标在画布上松开

  // 鼠标在画布上按下
  function canvasMouseDown(e) {
    console.log("🚀 ~ file: index.vue:39 ~ canvasMouseDown ~ e:", e);
    // 鼠标左键按下时,将当前坐标 赋值给 downPoint。{x: xxx, y: xxx} 的格式
    downPoint = e.absolutePointer;
  }
  // 鼠标在画布上松开
  function canvasMouseUp(e) {
    console.log("🚀 ~ file: index.vue:44 ~ canvasMouseUp ~ e:", e);

    // 松开鼠标左键时,将当前坐标 赋值给 upPoint
    upPoint = e.absolutePointer;
    // 调用 创建矩形 的方法
    if (!e.transform) {
      createRect();
    }
  }

  function canvasObjectRotating(e) {
    console.log("🚀 ~ file: index.vue:44 ~ canvasObjectRotating ~ e:", e);
  }
  function canvasObjectResizing(e) {
    console.log("🚀 ~ file: index.vue:44 ~ canvasObjectResizing ~ e:", e);
  }
  // 创建矩形
  function createRect() {
    // 如果点击和松开鼠标,都是在同一个坐标点,不会生成矩形
    if (JSON.stringify(downPoint) === JSON.stringify(upPoint)) {
      return;
    }

    // 创建矩形
    // 矩形参数计算(前面总结的4条公式)
    const top = Math.min(downPoint.y, upPoint.y);
    const left = Math.min(downPoint.x, upPoint.x);
    const width = Math.abs(downPoint.x - upPoint.x);
    const height = Math.abs(downPoint.y - upPoint.y);

    // 矩形对象
    const rect = new fabric.Rect({
      top,
      left,
      width,
      height,
      fill: "transparent", // 填充色:透明
      stroke: "#000" // 边框颜色:黑色
    });

    const maxYDis = state.imageHeight - rect.height;
    const maxXDis = state.imageWidth - rect.width;

    rect.on({
      moving: e => {
        console.log("🚀 ~ file: index.vue:143 ~ moving ~  e:", e);

        // objectMoving(e, rect);
      },
      dragleave: e => {
        console.log("🚀 ~ file: index.vue:143 ~ dragleave ~  e:", e);
      },
      mouseup: e => {
        console.log("🚀 ~ file: index.vue:143 ~ mouseup ~  e:", e);
        const target = e.target;
        if (target.left <= 0) target.left = 20;
        if (target.top <= 0) target.top = 20;
        if (target.left >= maxXDis) target.left = maxXDis - 20;

        if (target.top >= maxYDis) target.top = maxYDis - 20;
      }
    }); // 鼠标
    // 将矩形添加到画布上
    drawcanvas.add(rect);
    state.imgUrl = state.imgC.toDataURL({
      left,
      top,
      width,
      height
    });
    // 创建完矩形,清空 downPoint 和 upPoint。当然,你也可以不做这步。
    downPoint = null;
    upPoint = null;
  }
});
</script>

<template>
  <div>
    <div>
      <img :src="state.imgUrl" alt="" />
    </div>
    <div id="clip-img-w" class="img_box">
      <canvas id="drawcanvas" />
    </div>

    <!--回显区域-->
    <div class="img_group_item"><img id="img" :src="state.cutImgSrc" /></div>
  </div>
</template>
<style scoped lang="scss">
.img_box {
  position: relative;
}
</style>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值