Vue3中使用paper.js

news2024/11/17 15:48:32

目录

  • Paper.js的使用
    • 安装Paper
    • 引入Paper.js
    • 创建画布
    • 实例化Paper、Project以及Tool
      • 画圆
      • 画点和线
      • 画矩形
      • 导入图片
      • 画文字
      • Item组
      • 曲线
      • 监听键盘事件
      • 监听鼠标事件
      • 设置动画
      • 下载成图片
      • 完整代码

Paper.js的使用

在这里插入图片描述

安装Paper

npm install paper

引入Paper.js

import * as Paper from "paper";

创建画布

// 创建画布
<template>
  <canvas id="myCanvas" ref="myCanvas"></canvas>
</template>

实例化Paper、Project以及Tool

const paperInstance = new Paper.PaperScope();
let project: null | paper.Project = null;//全局项目,用来设置图层、导入导出数据等
const tool = new Paper.Tool();//全局工具,用来监听事件

onMounted(() => {
  paperInstance.setup(document.getElementById("myCanvas") as HTMLCanvasElement);
  project = new Paper.Project(
    document.getElementById("myCanvas") as HTMLCanvasElement
  );
  tool.activate();
});

画圆

const drawCircle = () => {
  const circle = new Paper.Path.Circle({
    center: [200, 100], //中心点  或者使用new Path.Point(200,100)
    radius: 50, //半径
    fillColor: new Paper.Color("red"), //填充颜色
    strokeColor: new Paper.Color("black"), //边框颜色
  });
  circle.strokeWidth = 2;
};

画点和线

const drawPointAndLine = () => {
  const point = new Paper.Point(500, 100); //点位置
  const path = new Paper.Path(); //需要path才能画出来
  // point.selected = true; //选中样式
  path.add(point); // 将点添加到路径中
  const copyPoint = point.clone(); // 克隆点
  copyPoint.set(600, 100); // 设置克隆点的位置
  path.add(copyPoint); // 将克隆点添加到路径中 2个点形成一条线
  path.strokeColor = new Paper.Color("black"); // 设置路径的边框颜色
  path.strokeWidth = 4;
  path.selected = true; // 选中路径
};

画矩形

const drawRectangle = () => {
  // 方式一
  const rect1 = new Paper.Path.Rectangle({
    center: [200, 400], //中心点
    size: [50, 100], //边长
    radius: [5, 5], //圆角
    fillColor: "orange",
    strokeColor: "black",
    strokeWidth: 4,
    rotation: 45, //旋转角度
    selected: true, //选中样式
  });
  // 方式二
  const topLeft = new Paper.Point(200, 20); //坐上角位置
  const rectSize = new Paper.Size(200, 200); //大小
  const rect2 = new Paper.Rectangle(topLeft, rectSize); //通过坐上角和大小创建矩形 还可以通过坐上角和右下角创建矩形等
  const radius = new Paper.Size(30, 30); //圆角
  const path = new Paper.Path.Rectangle(rect2, radius); //将矩形通过path画出来
  path.fillColor = new Paper.Color("blue");
  path.position.set({
    x: 300,
    y: 300,
  });
  path.selected = true;
};

导入图片

import Demo1 from "../../assets/demo1.jpg";

const drawImg = () => {
  const img = new Paper.Raster(Demo1);
  img.position.set(700, 600);
  img.scale(0.2);
};

画文字

const drawText = () => {
  const text = new Paper.PointText({
    position: [500, 200], //文本位置
    fillColor: "black",
    justification: "center",
    fontSize: 20, //字体大小
    content: "测试文字",
    locked: false, //锁定
  });
};

Item组

  const drawGroup = () => {
  const group = new Paper.Group();
  const text = new Paper.PointText({
    position: [0, -50 - 10], //文本位置
    content: "圆",
    fillColor: "black",
    justification: "center",
    fontSize: 20, //字体大小
  });
  const circle = new Paper.Path.Circle({
    center: [0, 0], //中心点
    radius: 50, //半径
    fillColor: "red", //填充颜色
  });
  group.addChildren([text, circle]);
  group.position.set(1200, 800);
};

曲线

const drawCurve = () => {
  const group = new Paper.Group();
  const earth = new Paper.Path.Circle({
    center: [800, 200],
    radius: 50,
    fillColor: new Paper.Color("green"),
  });

  var firstPoint1 = calculatePointOnCircle(800, 200, 50, (Math.PI / 18) * 19);
  var secondPoint1 = calculatePointOnCircle(800, 200, 50, (Math.PI / 18) * 1);
  var handleOut1 = new Paper.Point(160, 60);
  var handleIn1 = new Paper.Point(-160, 20);
  var firstSegment = new Paper.Segment(firstPoint1, undefined, handleIn1);
  var secondSegment = new Paper.Segment(secondPoint1, handleOut1, undefined);
  const curve1 = new Paper.Path([firstSegment, secondSegment]);
  curve1.strokeColor = new Paper.Color("black");
  curve1.strokeWidth = 8;
  curve1.locked = true;
  curve1.selected = false;

  group.addChildren([earth, curve1]);
};

监听键盘事件

const onKeyDown = () => {
   // 通过tool来监听
  tool.onKeyDown = (event: any) => {
    console.log(event);
    if (event.event.key === "z" && event.event.ctrlKey) {
    }
  };
};

监听鼠标事件

const onMouse = () => {
  const children = project?.activeLayer.children; //获取所有的item
  // 全局的鼠标事件
  tool.onMouseDown = (event: any) => {
    if (!event.item) {
      children?.forEach((item: any) => {
        item.selected = false;
      });
    } else {
      children?.forEach((item: any) => {
        item.selected = false;
      });
      event.item.selected = true;
    }
  };
  // 单个item的事件
  children?.forEach((item: any) => {
    // 每个item添加按下鼠标事件
    item.onMouseDown = () => {
      project?.activeLayer.addChild(item);//提高层级
      item.selected = true;
    };
    // 每个item添加鼠标拖动事件
    item.onMouseDrag = (event: paper.MouseEvent) => {
      item.position.set(
        item.position.x + event.delta.x,
        item.position.y + event.delta.y
      );
    };
  });
};

设置动画

let direction = "right";
const drawAnimate = () => {
  const node = new Paper.Path.Circle({
    center: [200, 100],
    radius: 50,
  });
  node.strokeColor = new Paper.Color("black");
  node.fillColor = new Paper.Color("white");
  node.onFrame = () => {
    const maxWidth = document.body.clientWidth;
    if (direction === "right") {
      if (node.bounds.right >= maxWidth) {
        direction = "left";
      }
    } else {
      if (node.bounds.left <= 0) {
        direction = "right";
      }
    }
    if (direction === "right") {
      node.bounds.x += 5;
    } else {
      node.bounds.x -= 5;
    }
  };
};

下载成图片

const screenShot = () => {
  // 获取svg元素,将整个canvas导出为svg
  const flash = project?.exportSVG();
  // 将SVG元素转换为字符串
  var serializer = new XMLSerializer();
  var xmlString = serializer.serializeToString(flash as SVGAElement);
  // 创建一个Blob对象
  var blob = new Blob([xmlString], { type: "image/svg+xml;charset=utf-8" });
  // 创建一个指向该Blob的URL
  var url = URL.createObjectURL(blob);
  // 创建一个a标签
  var a = document.createElement("a");
  a.href = url;
  a.download = "my-svg-file.svg";
  // 将a标签添加到文档中,触发点击事件,然后将其从文档中删除
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
};

完整代码

<template>
  <canvas id="myCanvas" ref="myCanvas"></canvas>
</template>

<script lang="ts">
export default { name: "Paper" };
</script>
<script lang="ts" setup>
import * as Paper from "paper";
import { onMounted } from "vue";
import Demo1 from "../../assets/demo1.jpg";

const paperInstance = new Paper.PaperScope();
let project: null | paper.Project = null;
const tool = new Paper.Tool();

let direction = "right";
const drawAnimate = () => {
  const node = new Paper.Path.Circle({
    center: [200, 100],
    radius: 50,
  });
  node.strokeColor = new Paper.Color("black");
  node.fillColor = new Paper.Color("white");
  node.onFrame = () => {
    const maxWidth = document.body.clientWidth;
    if (direction === "right") {
      if (node.bounds.right >= maxWidth) {
        direction = "left";
      }
    } else {
      if (node.bounds.left <= 0) {
        direction = "right";
      }
    }
    if (direction === "right") {
      node.bounds.x += 5;
    } else {
      node.bounds.x -= 5;
    }
  };
};

const drawCircle = () => {
  const circle = new Paper.Path.Circle({
    center: [200, 100], //中心点
    radius: 50, //半径
    fillColor: new Paper.Color("red"), //填充颜色
    strokeColor: new Paper.Color("black"), //边框颜色
  });
  circle.strokeWidth = 2;

  const pathData = "M 50 100 L 100 0 L 0 0 Z";
  const path = new Paper.Path(pathData);
  path.strokeColor = new Paper.Color("black");
  path.fillColor = new Paper.Color("green");
  path.strokeWidth = 2;
  path.strokeWidth = 2;
  path.position.set(400, 100);
};

const drawPointAndLine = () => {
  const point = new Paper.Point(500, 100); //点位置
  const path = new Paper.Path(); //需要path才能画出来
  // point.selected = true; //选中样式
  path.add(point); // 将点添加到路径中
  const copyPoint = point.clone(); // 克隆点
  copyPoint.set(600, 100); // 设置克隆点的位置
  path.add(copyPoint); // 将克隆点添加到路径中 2个点形成一条线
  path.strokeColor = new Paper.Color("black"); // 设置路径的边框颜色
  path.strokeWidth = 4;
  path.selected = true; // 选中路径
};

const drawRectangle = () => {
  // 方式一
  const rect1 = new Paper.Path.Rectangle({
    center: [200, 400], //中心点
    size: [50, 100], //边长
    radius: [5, 5], //圆角
    fillColor: "orange",
    strokeColor: "black",
    strokeWidth: 4,
    rotation: 45, //旋转角度
    selected: true, //选中样式
  });
  // 方式二
  const topLeft = new Paper.Point(200, 20); //坐上角位置
  const rectSize = new Paper.Size(200, 200); //大小
  const rect2 = new Paper.Rectangle(topLeft, rectSize); //通过坐上角和大小创建矩形 还可以通过坐上角和右下角创建矩形等
  const radius = new Paper.Size(30, 30); //圆角
  const path = new Paper.Path.Rectangle(rect2, radius); //将矩形通过path画出来
  path.fillColor = new Paper.Color("blue");
  path.position.set({
    x: 300,
    y: 300,
  });
  path.selected = true;
};

const drawImg = () => {
  const img = new Paper.Raster(Demo1);
  img.position.set(700, 600);
  img.scale(0.2);
};

const drawText = () => {
  const text = new Paper.PointText({
    position: [1600, 50], //文本位置
    fillColor: "black",
    justification: "center",
    fontSize: 20, //字体大小
    content: "下载",
    locked: false, //锁定
    name: "download",
  });
};

const drawGroup = () => {
  const group = new Paper.Group();
  const text = new Paper.PointText({
    position: [0, -50 - 10], //文本位置
    content: "圆",
    fillColor: "black",
    justification: "center",
    fontSize: 20, //字体大小
  });
  const circle = new Paper.Path.Circle({
    center: [0, 0], //中心点
    radius: 50, //半径
    fillColor: "red", //填充颜色
  });
  group.addChildren([text, circle]);
  group.position.set(1200, 800);
};

const drawCurve = () => {
  const group = new Paper.Group();
  const earth = new Paper.Path.Circle({
    center: [800, 200],
    radius: 50,
    fillColor: new Paper.Color("green"),
  });

  var firstPoint1 = calculatePointOnCircle(800, 200, 50, (Math.PI / 18) * 19);
  var secondPoint1 = calculatePointOnCircle(800, 200, 50, (Math.PI / 18) * 1);
  var handleOut1 = new Paper.Point(160, 60);
  var handleIn1 = new Paper.Point(-160, 20);
  var firstSegment = new Paper.Segment(firstPoint1, undefined, handleIn1);
  var secondSegment = new Paper.Segment(secondPoint1, handleOut1, undefined);
  const curve1 = new Paper.Path([firstSegment, secondSegment]);
  curve1.strokeColor = new Paper.Color("black");
  curve1.strokeWidth = 8;
  curve1.locked = true;
  curve1.selected = false;

  group.addChildren([earth, curve1]);
};

/**
 * @description 监听键盘事件
 */
const onKeyDown = () => {
  tool.onKeyDown = (event: any) => {
    console.log(event);
    if (event.event.key === "z" && event.event.ctrlKey) {
    }
  };
};

/**
 * @description 监听鼠标事件
 */
const onMouse = () => {
  const children = project?.activeLayer.children; //获取所有的item
  // 全局的鼠标事件
  tool.onMouseDown = (event: any) => {
    if (!event.item) {
      children?.forEach((item: any) => {
        item.selected = false;
      });
    } else {
      children?.forEach((item: any) => {
        item.selected = false;
      });
      event.item.selected = true;
    }
    // 下载
    const download = project?.getItem({
      name: "download",
    });
    if (download === event.item) {
      screenShot();
    }
  };
  console.log(children);
  // 单个item的事件
  children?.forEach((item: any) => {
    // 每个item添加按下鼠标事件
    item.onMouseDown = () => {
      project?.activeLayer.addChild(item); //提高层级
      item.selected = true; //选中样式
    };
    // 每个item添加鼠标拖动事件
    item.onMouseDrag = (event: paper.MouseEvent) => {
      console.log(event);
      item.position.set(
        item.position.x + event.delta.x,
        item.position.y + event.delta.y
      );
    };
  });
};

const screenShot = () => {
  // 获取svg元素,将整个canvas导出为svg
  const flash = project?.exportSVG();
  // 将SVG元素转换为字符串
  var serializer = new XMLSerializer();
  var xmlString = serializer.serializeToString(flash as SVGAElement);
  // 创建一个Blob对象
  var blob = new Blob([xmlString], { type: "image/svg+xml;charset=utf-8" });
  // 创建一个指向该Blob的URL
  var url = URL.createObjectURL(blob);
  // 创建一个a标签
  var a = document.createElement("a");
  a.href = url;
  a.download = "my-svg-file.svg";
  // 将a标签添加到文档中,触发点击事件,然后将其从文档中删除
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
};

const calculatePointOnCircle = (
  centerX: number,
  centerY: number,
  radius: number,
  angle: number
) => {
  var x = centerX + radius * Math.cos(angle);
  var y = centerY + radius * Math.sin(angle);
  console.log(x, y);
  return new Paper.Point(x, y);
};

onMounted(() => {
  paperInstance.setup(document.getElementById("myCanvas") as HTMLCanvasElement);
  project = new Paper.Project(
    document.getElementById("myCanvas") as HTMLCanvasElement
  );
  drawCircle();
  drawPointAndLine();
  drawRectangle();
  drawImg();
  drawText();
  drawGroup();
  drawCurve();
  tool.activate();
  onKeyDown();
  onMouse();
  drawAnimate();
});
</script>

<style lang="scss" scoped>
#myCanvas {
  width: 100%;
  height: 100%;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1548435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

arduino 2.0以上版本上传项目data目录内文件到ESP8266闪存中

开发测试环境&#xff1a; arduino IDE : 2.3.2 开发板 ESP8266 系统&#xff1a;WINDOWS 10 截止目前&#xff0c;arduino版本为2.3.2&#xff0c;在开发项目的时候&#xff0c;发现一个问题&#xff0c;就是项目目录中data内的文件没有办法和主文件.ino一同上传到ESP8266的f…

学习笔记:MYSQL数据库基础知识

MYSQL数据库基础知识学习笔记 MYSQL基础学习数据库相关概念现主流数据库排名数据模型SQL分类SQL数据库基础操作 2024/3/27 学习资料&#xff1a;黑马程序员:MYSQL MYSQL基础学习 数据库和数据库管理系统(DBMS) 数据库: 是存储数据的集合&#xff0c;包括表、视图、索引等对象…

面试八股文之JAVA基础

JAVA基础 DNS、CDN&#xff1f;如何实现对象克隆?父子类静态代码块, 非静态代码块, 构造方法执行顺序?String s new String("abc") 创建了几个对象, 分别放到哪里?OSI网络模型七层&#xff1f;应用层协议&#xff1f;http协议和https协议区别&#xff1f;传输层协…

STM32学习笔记(7_1)- ADC模数转换器

无人问津也好&#xff0c;技不如人也罢&#xff0c;都应静下心来&#xff0c;去做该做的事。 最近在学STM32&#xff0c;所以也开贴记录一下主要内容&#xff0c;省的过目即忘。视频教程为江科大&#xff08;改名江协科技&#xff09;&#xff0c;网站jiangxiekeji.com 本期开…

QGIS开发笔记(一):QGIS介绍、软件下载和加载shp地图数据Demo

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/136888334 红胖子网络科技博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬…

大学教材《C语言程序设计》(浙大版)课后习题解析 | 第三、四章

概述 本文主要提供《C语言程序设计》(浙大版) 第三、四章的课后习题解析&#xff0c;以方便同学们完成题目后作为参考对照。后续将更新第五、六章节课后习题解析&#xff0c;如想了解更多&#xff0c;请持续关注该专栏。 专栏直达链接&#xff1a;《C语言程序设计》(浙大版)_孟…

【Python】进阶学习:pandas--describe()函数的使用介绍

&#x1f40d;【Python】进阶学习&#xff1a;pandas——describe()函数的使用介绍 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&am…

抖音弹幕游戏开发:打造全新互动体验,引领潮流风尚

在数字科技迅猛发展的时代&#xff0c;抖音作为一款领先的短视频平台&#xff0c;始终走在创新的前沿。为了满足用户日益增长的互动需求&#xff0c;我们投入大量研发力量&#xff0c;成功推出了抖音弹幕游戏开发项目&#xff0c;旨在为用户带来一种全新的、沉浸式的互动体验。…

鸿蒙(HarmonyOS)Navigation如何实现多场景UI适配?

场景介绍 应用在不同屏幕大小的设备上运行时&#xff0c;往往有不同的UI适配&#xff0c;以聊天应用举例&#xff1a; 在窄屏设备上&#xff0c;联系人和聊天区在多窗口中体现。在宽屏设备上&#xff0c;联系人和聊天区在同一窗口体现。 要做好适配&#xff0c;往往需要开发…

Alpha律所管理系统,助力律师团队管理提效再升级

律师团队管理&#xff0c;是律所成长与发展经久不衰的议题。无论是律所的创办还是扩张&#xff0c;管理者首先要考虑的就是管理模式的选择与更新问题&#xff0c;这几乎成为一个律所能否长远发展的关键“七寸”。那么&#xff0c;到底为什么团队管理如此重要&#xff0c;做好管…

【实现100个unity特效之7】unity 3d实现各种粒子效果

文章目录 先看最终效果下雨效果萤火虫和火花四溅的效果 3d下雨粒子效果涟漪效果雨滴和涟漪效果结合水花效果雨滴涟漪水花结合问题雾气效果萤火虫火花效果萤火虫和火花效果结合其他特效爆炸、闪电、火焰、雷雨特效&#xff08;2023/7/5更新&#xff09;源码完结 先看最终效果 下…

冰岛人[天梯赛]

文章目录 题目描述思路AC代码 题目描述 输入样例 15 chris smithm adam smithm bob adamsson jack chrissson bill chrissson mike jacksson steve billsson tim mikesson april mikesdottir eric stevesson tracy timsdottir james ericsson patrick jacksson robin patrickss…

图片如何做成二维码?手机扫码看图的制作方法

现在用二维码来展示图片、照片时很常用的一种方式&#xff0c;通过扫秒二维码就能够在手机上预览图片&#xff0c;更加的方便快捷。在制作图片二维码的时候&#xff0c;有些情况下需要不定时的在二维码图案不变的情况经常性的修改内容&#xff0c;或者除了图片之外还要加入其它…

【数据结构】受限制的线性表——队列

&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;个人主页&#x1f388;&#x1f388;&#x1f388;&#x1f388;&#x1f388; &#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;数据结构专栏&#x1f388;&#x1f388;&#x1f388;&…

最新版CleanMyMac X4.15.2有哪些亮眼的更新?

CleanMyMac X是一款专为macOS系统设计的清理和优化工具&#xff0c;它集成了多种功能来帮助用户保持Mac系统的整洁、高效和安全。 首先&#xff0c;CleanMyMac X具备智能扫描和清理功能&#xff0c;能够自动识别并清理Mac上的各种垃圾文件&#xff0c;包括重复文件、无用的语言…

《AI绘画与修图实战:Photoshop+Firefly从入门到精通》

关键点 1.自学教程&#xff1a;内容安排由浅入深、循序渐进&#xff0c;130多个经典AI案例案例助你在实战中掌握技巧 2.技术手册&#xff1a;透彻讲解PSAI、Firefly&#xff0b;AI的绘画和修图实战技巧&#xff0c;高效率学习 3.老师讲解&#xff1a;赠送170分钟频教程和数百个…

企业内推平台招聘信息采集与分析在线项目实习

师傅带练 项目背景 为了实现有效的招聘&#xff0c;企业需要制定明确的招聘需求&#xff0c;根据业务发展需求和市场变化&#xff0c;精准定位所需人才的类型和层次&#xff0c;提高招聘效率和质量。而招聘网站需要积极满足企业的需求&#xff0c;提供针对性的服务&#xff0…

c语言--跳出continue、break

C 语言中的 continue 语句有点像 break 语句。但它不是强制终止&#xff0c;continue 会跳过当前循环中的代码&#xff0c;强迫开始下一次循环。 对于 for 循环&#xff0c;continue 语句执行后自增语句仍然会执行。对于 while 和 do…while 循环&#xff0c;continue 语句重新…

【面试题】数据底层原理:Elasticsearch写入流程解析

前言&#xff1a;本篇博客将介绍Elasticsearch的数据底层原理&#xff0c;涉及数据写入的过程以及相关概念。我们将深入探讨buffer、translog、refresh、commit、flush和merge等核心概念&#xff0c;帮助您更好地理解Elasticsearch的数据存储机制。 写入数据的基本过程 Elast…

【牛客】【刷题节】美团2024届秋招笔试第一场编程真题

1.小美的外卖订单【简单题】 题意理解&#xff1a; 这道题是简单题&#xff0c;主要是一个逻辑实现和判断的问题。但是简单题一般喜欢加一点小障碍&#xff0c;所以读题的时候就要比较注意一些约束条件。就比如这道题&#xff1a;过了15/20个测试用例&#xff0c;出现error, 当…