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

canvas-绘图库fabric.js简介

一般情况下简单的绘制,其实canvas原生方法也可以满足,比如画个线,绘制个圆形、正方形、加个文案。

  let canvas = document.getElementById('canvas');canvas.width = 1200;canvas.height = 600;canvas.style.width = '1200px';canvas.style.height = '600px';let ctx = canvas.getContext('2d');ctx.moveTo(400, 100);ctx.lineTo(400, 200);ctx.lineTo(500, 200);ctx.strokeStyle = "#00F";ctx.stroke();ctx.beginPath();ctx.arc(150, 150, 100, 0, 2 * Math.PI, true);ctx.fillStyle = '#ccc';ctx.fill();ctx.beginPath();let str1 = '苟利国家生死以,';let str2 = '岂因祸福避趋之!';ctx.font = '50px Microsoft Yahei';ctx.strokeStyle = 'red';ctx.textAlign = 'center';ctx.strokeText(str1, 800, 50);ctx.font = '50px SimHei';ctx.fillStyle = 'blue';ctx.textAlign = 'center';ctx.fillText(str2, 800, 100);//获取文本的宽度,以便以后能动态的使文本居中。let strWidth = ctx.measureText(str2).width;console.log(strWidth);

看效果图
在这里插入图片描述
如果真的只是这点需求,原生方法也很好,省的加载一个js库。不过现实往往还是很残酷的,怎么可能这么简单,这里都没有交互,比如在现有的图形上做位移、拖拽等等,复杂度就上来了,这时一个好的canvas js库就很有必要了。
fabric.js 算是我用到过的比较全面且好用的一个canvas js库;
先上代码:

const data = {line: ['1648.607594936709', '654.1772151898734', '2100.253164556962', '1290.126582278481'],area: ["1604.0506329113923", "607.5949367088607", "1648.607594936709", "654.1772151898734", "2100.253164556962", "1290.126582278481"
, "2211.645569620253", "1429.873417721519", "285.56962025316454" , "1429.873417721519" , "617.7215189873417" , "662.2784810126582"]
};
// 可以看出上面数据一个是画线,一个是画不规则区域,这是实际项目中用到的数据,拿到这里自有妙处,后面会说

fabric.js使用

import { fabric } from ‘fabric’;

// canvasDraw是canvas的 id
const canvasBox = new fabric.StaticCanvas('canvasDraw', {backgroundColor: "transparent"});// 这个是设置// canvas.style.width 和 canvas.width// canvas.style.height 和 canvas.height
canvasBox.setDimensions({width: 600,height: 300
});
// 下面方法等同于 setDimensions
// canvasBox.setWidth(width);
// canvasBox.setHeight(height);// 这个是设置的 canvas.style.width 和 canvas.style.height
canvasBox._setCssDimension('width', 2400);
canvasBox._setCssDimension('height', 1500);

到此fabric初始化就算完成了,这里有个很重要的点,官方文档和几乎所有写fabric教学的博客都没有讲,那就是如何将canvas.style.width 和 canvas.width 赋予不同的数值,这是个很实用的点,因为坐标点是按canvas.width来的,但是我们的canvas.style.width必须和设计保持一致
比如说:我们需要在一张图片上做绘制,那坐标点是从图片原图上标注的,而设计不可能按原图大小展示,这时就会出现坐标点和canvas.style.width不一致,有两个方法解决这个问题:
1、坐标点根据 canvas.style.width / img.width 的比率做调整
2、canvas.width 和 img.width保持一致,canvas.style.width 和 设计稿 width一致
很显然第二个方案更简单且实用
既然官网没提供方法那我们就看源码都做了什么,因为canvas.width是必然要设置的
我们发现setDimensions时调用了 _setBackstoreDimension 和 _setCssDimension
在这里插入图片描述
很明显这里是canvas.width
在这里插入图片描述
而这里是canvas.style.width
在这里插入图片描述
今天先简单点,只看画线和画不规则图形

function drawLine(arr, color, opacity) {// [x1, y1, x2, y2]const line =  new fabric.Line(arr, {strokeWidth: 10, //线宽stroke: color, //线的颜色selectable: false,opacity: opacity});this.canvasBox.add(line);
}
function drawPolygon(arr, color, opacity) {const newArr = formatData(arr);const polygon = new fabric.Polygon(newArr,{fill: color,strokeWidth: 1,stroke: "#000",opacity: opacity});this.canvasBox.add(polygon);
}
function formatData(arr) {// 将 [100,50,200,40] 坐标点转为 {x: 100, y: 50}let newArr = [];arr.forEach((val, i) => {i = i + 1;// 偶数不操作if ((i % 2) !== 0) {newArr.push({x: parseInt(val),y: parseInt(arr[i])});}});return newArr;
}

这时大家就会看到 我有个 parseInt的操作,因为当我使用原数据绘制时,线可以出来但Polygon却没有,搞得很郁闷,查了很长时间,最后当我盯着数据发呆时,看着长长的小数位 突发奇想,于是parseInt诞生了,页面也能看到区域了,真的是坑,这个点不做项目是绝无可能发现的。
也是我今天冒着延期项目也要搞这么一篇文章的原因,虽然fabric知识点不多但绝对满满的干货,更是告诉大家遇到问题后不要怕、更不能放弃,永远都能找到解题的方法,条条大路通罗马,一条不行就换一条,总会解决的!!!

相关文章:

canvas-绘图库fabric.js简介

一般情况下简单的绘制,其实canvas原生方法也可以满足,比如画个线,绘制个圆形、正方形、加个文案。 let canvas document.getElementById(canvas);canvas.width 1200;canvas.height 600;canvas.style.width 1200px;canvas.style.height 6…...

代码审计——任意文件下载详解(二)

为方便您的阅读,可点击下方蓝色字体,进行跳转↓↓↓ 01 漏洞描述02 审计要点03 漏洞特征04 漏洞案例05 修复方案 01 漏洞描述 网站可能提供文件查看或下载的功能,如果对用户查看或下载的文件不做限制,就能够查看或下载任意的文件&…...

19异常的学习笔记

异常 很重要,有利于我们平时处理问题 异常就是代表程序出现了问题 常见的异常比如说 数组越界除法除0 异常的体系是什么 java.lang.Throwable Error Exception RuntimeException 其他异常 Error 代表的是系统级别的错误,也就是一旦系统出现问题&…...

Jenkins学习笔记4

配置构建流程: Jenkins任务创建: 1)创建新任务: 把这个Accept first connection改成 No Validation。问题得到解决。 构建触发器这块暂时没有需要配置的。 传输文件到nginx-server这个web服务器中。 将文件上传到/usr/share/n…...

自学 Java 需要具备哪些基本条件或技能?

新手初学者在自己学习Java时,需要注意两个方面,一个是学习方面,一个是知识点方面! 学习方面: 1、做学习计划并保持自律 在我们学习Java的过程中,尽量减少干扰,把自己的全部注意力集中在Java上…...

[激光原理与应用-68]:如何消除50Hz工频干扰和差分信号应对工频干扰

目录 一、什么工频干扰 1.1 什么工频干扰 1.2 工频干扰的幅度 1.3 工频干扰如何进入设备 1.4 工频干扰的负面影响 二、如何消除工频干扰 2.1 要消除工频干扰,可以考虑以下方法: 2.2 要具体消除工频干扰,可以采取以下措施 2.3 使用差…...

【力扣-每日一题】LCP 06. 拿硬币

class Solution { public:int minCount(vector<int>& coins) {int res0;for(auto i:coins){resi/2;res(i%2)?1:0;}return res;} };...

【JAVA-Day32】精通Java函数:定义、调用和主函数的完整指南

精通Java函数&#xff1a;定义、调用和主函数的完整指南 精通Java函数&#xff1a;定义、调用和主函数的完整指南摘要引言1. Java函数基础什么是Java函数&#xff1f;函数的定义和命名规则参数和返回值的概念 2. 函数的定义与语法如何声明和定义函数&#xff1f;函数的参数和参…...

springboot相关操作学习汇总

IDEAMAVEN apache maven 3.6.3 的安装及配置IntelliJ IDEA 安装及配置详细教程Maven下载安装及IDEA配置Maven的超详细教程 GIT 版本控制工具 - git的安装与使用gitlab上传新项目全过程 SPRINGBOOT IDEAmavenSpringboot工程创建超详细过程示例SpingBoot&#xff1a;整合Myb…...

如何在微信上制作自己的小程序卖东西

在当今的数字化时代&#xff0c;微信小程序已成为电商行业的重要平台。本文将详细解析电商微信小程序的制作流程&#xff0c;帮助你了解从零到上线的过程。 一、前期准备 1. 确定商城定位和目标群体&#xff1a;在制作电商微信小程序前&#xff0c;你需要明确商城的定位&#x…...

24.Xaml ListView控件-----显示数据

1.运行效果 2.运行源码 a.Xaml源码 <Window x:Class="testView.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic…...

YoloV5改进实战:使用MPDIoU改进YoloV5

文章目录 摘要论文:揭秘精准高效的MPDIoU损失函数摘要1、简介2、相关工作2.1、目标检测和实例分割2.2. 场景文本识别2.3、边界框回归的损失函数3、点距最小的并集交点4、实验结果4.1、 实验设置4.2、数据集4.3、 评估协议4.4、 目标检测的实验结果4.5、 字符级场景文本识别的实…...

从电大搜题到上海开放大学,广播电视大学引领学习新风尚

近年来&#xff0c;随着信息技术的飞速发展&#xff0c;互联网的普及和应用成为了我们生活中不可或缺的一部分。而在大学学习领域&#xff0c;电大搜题微信公众号应运而生&#xff0c;为广大学子提供了便捷的学习资源和交流平台。在这个信息高速发展的时代&#xff0c;上海开放…...

DC/DC开关电源学习笔记(九)Buck降压拓扑原理

(九)Buck降压拓扑原理 1.概述2. Buck降压原理3. Buck电路的三种工作模式3.1 CCM:3.2 BCM3.3 DCM4. 伏秒法则1.概述 Buck电路属于非隔离的直流变换器,在开关电源中广泛应用,BUCK电路是一种基于电感储能原理的DC-DC变换器,其涉及到物理中的电磁感应和电能转换的基本原理。…...

【浏览器】主流浏览器伪元素一览

不同浏览器对于伪元素的支持程度可能会有所差异。以下是各主流浏览器对一些常见伪元素的支持情况&#xff1a; WebKit&#xff08;Chrome、Safari、新版Edge&#xff09;&#xff1a; ::-webkit-scrollbar&#xff1a;用于自定义滚动条样式的伪元素。::-webkit-outer-spin-butt…...

国内首个潮玩行业沉浸式IP主题乐园,泡泡玛特城市乐园即将开园

近年来&#xff0c;泡泡玛特以潮玩IP为核心&#xff0c;不断拓展业务版图&#xff0c;推进国际化布局同时实现集团化运营&#xff0c;而泡泡玛特首个城市乐园将于9月下旬开业。据了解&#xff0c;泡泡玛特城市乐园是由泡泡玛特精心打造的沉浸式IP主题乐园&#xff0c;占地约4万…...

编译工具:CMake(八) | cmake 常用指令

编译工具&#xff1a;CMake&#xff08;八&#xff09; | cmake 常用指令 基本指令 基本指令 ADD_DEFINITIONS向 C/C编译器添加-D 定义&#xff0c;比如:ADD_DEFINITIONS(-DENABLE_DEBUG-DABC)&#xff0c;参数之间用空格分割。 如果你的代码中定义了#ifdef ENABLE_DEBUG #end…...

什么是GPT磁盘?介绍GPT(GUID 分区表)磁盘及其优势!

GPT概述 GPT磁盘是什么意思&#xff1f;GPT是全局唯一标识符分区表&#xff08;GUID Partition Table&#xff09;的简称&#xff0c;它是硬盘分区表结构的一个标准模式。在我们深入了解GPT磁盘的特性之前须知&#xff0c;MBR磁盘的分区信息直接保存在主引导记录&#xff0…...

直播视频处理过程

视频其实就是快速播放一连串连续的图片。 每一张图片&#xff0c;我们称为一帧。只要每秒钟帧的数据足够多&#xff0c;也即播放得足够快。比如每秒 30 帧&#xff0c;以人的眼睛的敏感程度&#xff0c;是看不出这是一张张独立的图片的&#xff0c;这就是我们常说的帧率&#…...

CGI与FastCGI的区别在哪里,FastCGI的应用场景讲解

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...