老甲不假 2021-03-13 20:00 采纳率: 0%
浏览 579

fabricjs背景图缩放平移功能实现的操作并支持手势的

<template>
  <div class="box">
    <el-scrollbar style="height: 100%;">
      <canvas id="canvas"></canvas>
      <div class="right" v-if="!editStatus">
        <div
          @click="selectType('painting')"
          class="item"
          :class="type == 'painting' ? 'selectItem' : ''"
        >
          <img :src="require('../../assets/images/k.png')" alt="" />
          <div>选 框</div>
        </div>
        <div
          @click="selectType('text')"
          class="item"
          :class="type == 'text' ? 'selectItem' : ''"
        >
          <img :src="require('../../assets/images/z.png')" alt="" />
          <div>标 注</div>
        </div>
        <div class="item" @click="deleteSelect">
          <img :src="require('../../assets/images/empty_fill.png')" alt="" />
          <div>删 除</div>
        </div>
        <div class="item" @click="preservation">
          <img :src="require('../../assets/images/preservation.png')" alt="" />
          <div>保 存</div>
        </div>
        <div class="item" @click="signOut">
          <img :src="require('../../assets/images/cl.png')" alt="" />
          <div>退 出</div>
        </div>
      </div>
      <img id="imgNode" :src="newImgString" style="display: none;" />
    </el-scrollbar>
  </div>
</template>

<script>
import { fabric } from "fabric";
export default {
  props: ["imgString"],
  data() {
    return {
      newImgString: "",
      type: "", //选中绘画类型
      editStatus: false, //true可编辑 false不可编辑
      canvas: null, //舞台对象
      textObj: null, //文本对象
      mouseFrom: {}, //当前鼠标或手指触摸的位置
      mouseTo: {}, //当前鼠标离开或手指触摸离开的位置
      selectObj: null, //选中组件对象
      drawingObject: null, //画图对象
      imgInstance: null
    };
  },
  created() {
    this.newImgString = this.imgString;
  },
  watch: {
    imgString(n, o) {
      this.newImgString = n;
    }
  },
  mounted() {
    const imgElement = document.getElementById("imgNode");

    imgElement.onload = res => {
      console.log("图片信息", imgElement.width, imgElement.height);
      //创建舞台
      this.canvas = new fabric.Canvas("canvas", {
        //   isDrawingMode: false,
        //   skipTargetFind: false,
        //   selectable: false,
        selection: false,
        width: window.innerWidth > 768 ? 768 : window.innerWidth,
        height:
          window.innerWidth > 768
            ? 768 / (imgElement.width / imgElement.height)
            : window.innerWidth / (imgElement.width / imgElement.height)
      });

      const imgInstance = new fabric.Image(imgElement, {
        scaleX: this.canvas.width / imgElement.width,
        scaleY: this.canvas.width / imgElement.width,
        id: "bg",
        hasControls: false,
        hasBorders: false,
        zIndex: 1,
        selectable: false, //false 可移动
        lockMovementX: true //垂直移动
      });
      this.imgInstance = imgInstance;
      this.canvas.add(imgInstance);

      //舞台事件
      this.canvas.on("mouse:down", this.canvasMouseDown); //点击
      this.canvas.on("mouse:move", this.canvasMouseMove);
      this.canvas.on("mouse:up", this.canvasMouseUp); //离开
      //this.canvas.on("mouse:wheel", this.canvasMouseWheel); //鼠标滚轮事件

      this.canvas.on("selection:created", this.canvasSelectObjIn); //选中对象
      this.canvas.on("selection:cleared", this.canvasSelectObjOut); //取消选中
    };

    // 添加对象后, 如下图
    // fabric.Image.fromURL(imgElement.src, img => {
    //   img.set({
    //     // 通过scale来设置图片大小,这里设置和画布一样大
    //     scaleX: this.canvas.width / img.width,
    //     scaleY: this.canvas.height / img.height
    //   });
    //   // 设置背景
    //   this.canvas.setBackgroundImage(
    //     img,
    //     this.canvas.renderAll.bind(this.canvas)
    //   );
    //   this.canvas.renderAll();
    // });
  },

  methods: {
    signOut() {
      this.$emit("out");
    },
    preservation() {
      // console.log(this.canvas.toDataURL(), "=========------------");
      let textList = "";
      this.canvas.getObjects().filter(res => {
        if (res.type == "textbox") {
          // console.log(res.text)
          textList += res.text + "\n";
        }
      });
      this.$emit("getImgBlob", {
        base64String: this.canvas.toDataURL(),
        content: textList
      });
    },
    //选择绘画类型
    selectType(type) {
      console.log("触发选择函数");
      if (this.type == type) {
        this.type = "";
        if (this.textObj) {
          this.textObj.exitEditing();
          this.textObj = null;
        }
      } else {
        this.type = type;
      }
    },

    //删除选取
    deleteSelect() {
      this.canvas.remove(this.selectObj);
    },

    /*------------- 鼠标事件 start ---------------*/
    canvasMouseDown(e) {
      console.log(e, "鼠标点击");
      //点击时开启编辑
      //如果当前为选中对象 则不触发鼠标点击事件
      if (this.selectObj) {
        return;
      }
      this.editStatus = true; //开启编辑模式
      this.mouseFrom = e.pointer;
      if (this.textObj) {
        this.textObj.exitEditing(); //关闭编辑
        this.textObj = null; //清空
        return;
      }
      if (this.type == "text") {
        this.drawing();
      }
    },
    //鼠标移动
    canvasMouseMove(e) {
      console.log(this.editStatus);
      this.mouseTo = e.pointer;
      //未开启编辑模式 或 处于选中对象时禁止鼠标移动
      if (!this.editStatus || this.selectObj) {
        return;
      }
      if (this.type != "text") {
        this.drawing();
      }
    },

    //鼠标离开
    canvasMouseUp(e) {
      console.log("触发鼠标离开", e);
      this.mouseTo = e.pointer;
      //离开后禁止编辑
      this.editStatus = false;
      this.drawingObject = null; //清空输入方法
    },

    //鼠标滚轮
    canvasMouseWheel(e) {
      if (this.type) {
        return;
      }
      var zoom = (e.e.deltaY > 0 ? 0.1 : -0.1) + this.canvas.getZoom(); //缩放倍数
      zoom = Math.max(1, zoom); //最小缩放0.5倍
      zoom = Math.min(4, zoom); //最大是原来的3倍
      var zoomPoint = new fabric.Point(
        this.canvas.width / 2,
        this.canvas.height / 2
      ); //居中缩放
      this.canvas.zoomToPoint(zoomPoint, zoom);
      // this.canvas.setZoom(zoom)

      var vpt = this.canvas.viewportTransform;
      console.log(vpt);
    },

    //组件对象操作
    //选中
    canvasSelectObjIn(e) {
      //点击图像时阻止选中
      if (e.target.id == "bg") {
        return;
      }
      console.log(e.target, "对象选中");
      this.selectObj = e.target; //存选中对象

      // if (e.target.type == "textbox") {
      //   this.selectObj.enterEditing();
      // }

      if (this.textObj) {
        this.textObj.exitEditing(); //关闭编辑
        this.textObj = null; //清空
      }
    },

    //取消选中
    canvasSelectObjOut(e) {
      console.log(e, "取消选中");
      if (this.selectObj.type == "textbox") {
        this.selectObj.exitEditing();
      }
      this.selectObj = null; //清空选中对象
    },

    /*------------- 鼠标事件 end------------------*/
    //绘画函数
    drawing() {
      if (this.drawingObject) {
        this.canvas.remove(this.drawingObject);
      }
      switch (this.type) {
        case "text":
          //添加一个 text 输入框
          this.textObj = new fabric.Textbox("", {
            left: this.mouseFrom.x,
            top: this.mouseFrom.y,
            fontSize: 18,
            borderColor: "#FF0000",
            fill: "#FF0000",
            hasBorders: true
          });
          this.canvas.add(this.textObj);
          //设置当前输入框为可编辑模式
          this.textObj.enterEditing();
          break;
        case "painting":
          let mouseFrom = this.mouseFrom;
          let mouseTo = this.mouseTo;

          var path =
            "M " +
            mouseFrom.x +
            " " +
            mouseFrom.y +
            " L " +
            mouseTo.x +
            " " +
            mouseFrom.y +
            " L " +
            mouseTo.x +
            " " +
            mouseTo.y +
            " L " +
            mouseFrom.x +
            " " +
            mouseTo.y +
            " L " +
            mouseFrom.x +
            " " +
            mouseFrom.y +
            " z";
          let canvasObject = new fabric.Path(path, {
            left: this.mouseFrom.x,
            top: this.mouseFrom.y,
            stroke: "#FF0000",
            strokeWidth: 3,
            fill: "rgba(255, 255, 255, 0)",
            hasControls: true,
            zIndex: 1
          });
          this.canvas.add(canvasObject);
          this.drawingObject = canvasObject;

          console.log("画图开启");
          break;
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.box {
  position: relative;
  height: 100vh;
  overflow: hidden;
  overflow-y: hidden;
  display: flex;
  justify-content: center;
  align-content: center;
}

.right {
  position: absolute;
  width: 70px;
  top: 30%;
  right: 20px;
  // transform: translate(-50%, -50%);
  padding: 6px 0;
  border-radius: 4px;
  background: #ffffff;
  box-shadow: 0px 0px 9px #d8d8d8;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.right .item {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 10px;
  font-size: 12px;
  padding: 5px 0;
  width: 50px;
}

.right .item:first-child {
  margin-top: 0;
}

.selectItem {
  background: #d2d2d2;
  border-radius: 4px;
}

.right .item > img {
  width: 30px;
  height: 30px;
  margin: 5px 0 4px;
}
</style>

这是代码,目前未完成的操作有缩放与平移,请各位麻烦告诉我一下 该怎么实现缩放 平移并不会超出界限?

我参考例子 http://fabricjs.com/fabric-intro-part-5   但是缩放时 会闪屏不知什么原因 而且缩放位置不正确

 

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2022-09-07 18:17
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:

    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 以帮助更多的人 ^-^
    评论

报告相同问题?

悬赏问题

  • ¥15 高通uboot 打印ubi init err 22
  • ¥20 PDF元数据中的XMP媒体管理属性
  • ¥15 R语言中lasso回归报错
  • ¥15 网站突然不能访问了,上午还好好的
  • ¥15 有没有dl可以帮弄”我去图书馆”秒选道具和积分
  • ¥15 semrush,SEO,内嵌网站,api
  • ¥15 Stata:为什么reghdfe后的因变量没有被发现识别啊
  • ¥15 振荡电路,ADS仿真
  • ¥15 关于#c语言#的问题,请各位专家解答!
  • ¥15 这个如何解决详细步骤