Day13 - 用 canvas 复刻 小画家 选择剪下移动

说明

在选择剪下时,我们可以建立一个新的 canvas来建立我们所剪下的内容

  /**
   * 滑鼠点下画布
   */
  const handleMouseDown = (event: any) => {
   ....
      case "select":
        createCanvas(point);
        break;
      default:
        break;
    }
  };
/** 建立选择的 canvas */
  const createCanvas = (point: any, ctx) => {
    const div = document.createElement("div");
    div.style.position = "absolute";
    div.style.left = point?.x + "px";
    div.style.top = point?.y + "px";
    div.style.width = 200 + "px";
    div.style.height = 200 + "px";
    div.style.zIndex = "10";
    div.style.border = `2px dashed #999`;
    const b = document.createElement("canvas");
    b.width = 200;
    b.height = 200;
    div.appendChild(b);
    div.style.cursor = `url(${moveIcon}) 8 8, move`;
    canvasWrapRef.current.appendChild(div);

    let dragFlag = false;
    let x = 0,
      y = 0;

// 可任意移动
    div.onmousedown = (e) => {
      e = e || window.event;
      x = e.clientX - div.offsetLeft;
      y = e.clientY - div.offsetTop;
      dragFlag = true;
    };

    div.onmousemove = (e) => {
      if (dragFlag) {
        e = e || window.event;
        div.style.left = e.clientX - x + "px";
        div.style.top = e.clientY - y + "px";
      }
    };

    div.onmouseup = function (e) {
      dragFlag = false;
    };
  };

思考

但目前上面只写到了建立,重点的剪下没有做到!
这时又需要 canvas 的 API 了
来到今天的学习重点

getImageData

CanvasRenderingContext2D.getImageData() getImageData()返回一个ImageData对象,该 对象表示画布指定部分的底层像素数据。
此方法不受画布变换矩阵的影响。如果指定的矩形超出画布边界,则画布外的像素在返回的对ImageData像中为透明黑色。

putImageData

CanvasRenderingContext2D.putImageData() Canvas 2D API 的 方法将来自给定ImageData对象的数据绘制到画布上。如果提供了脏矩形,则仅绘制该矩形中的像素。此方法不受画布变换矩阵的影响。画布边界,则画布外的像素在返回的对ImageData像中为透明黑色。

所以只需要在刚才的 createCanvas 底下补上以下的程序码

 let imageData = ctx.getImageData(point.x, point.y, b.width, b.height);
    const ctx_b = b.getContext("2d");
    ctx_b && ctx_b.putImageData(imageData, 0, 0);
    ctx.clearRect(point.x, point.y, b.width, b.height);

b->> 刚才所新建立的 canvas
ctx ->> 原先的 canvas

查看效果


<<:  连续 30 天 玩玩看 ProtoPie - Day 13

>>:  [Day13] 建立订单交易API_6

DAY 6 ROS 通讯架构2

前言 今天我们要来讲 ROS 中最为核心的部分,ROS 提供了 四种通讯方式,分别为 Topic、S...

Day 9 老照片效果

老照片效果 教学原文参考:老照片效果 这篇文章会介绍使用 GIMP 图层的混合模式,做出老旧照片的图...

Day2 Visual Studio Code 安装与设定

IDE的抉择 「工欲善其事,必先利其器」这句话从小听到大,选择适合的IDE可以提高开发的效率。 在学...

DAY27 把这个Google maps 放在 APP 上(三)

写完第26天之後我思考了很久(大概一天),因为 Google maps 的功能也介绍的差不多了,但是...

Domain layer testing

今天会为上一篇所写的两个 use case 加上 unit test。 GetLinesAndSta...