图片标注编辑平台搭建系列教程(4)——fabric几何定制渲染

背景

标注的几何,有时需要一些定制化的渲染样式,例如,线中间展示箭头,表示方向。本期教程教大家如何实现fabric几何定制化渲染。

带箭头的线

fabric提供了一些原生的几何,例如Point、Polyline、Polygon。同时提供了一些抽象的实体,如Object、Path。

如果使用原生的几何,可配置的样式是有限的。

比如Point的配置是:

{radius: 5,stroke: 'rgba(0,0,0,1)',strokeWidth: 2,fill: 'rgba(255,0,0,1)'
}

Polyline的配置是:

{stroke: 'rgba(0,0,0,1)',strokeWidth: 5
}

Polygon的配置是:

{fill: 'rgba(255,0,0,0,3)',strokeWidth: 1
}

可见这些线宽、线颜色、填充色等并不能实现箭头样式,需要对这些类进行扩展。

fabric提供了方法,可以扩展原生几何,代码如下:

export const NewPolyline = fabric.util.createClass(fabric.Polyline, {type: 'NewPolyline',initialize: function (points: any = [], options: any = {}) {this.callSuper('initialize', points, { ...options }); // 调用Polyline的初始化方法},_render: function (ctx: any) {// 自定义渲染,每次canvas.renderAll()都会触发该方法。this.callSuper('_render', ctx);}
}

此时我们得到了一个新的fabric几何类型:NewPolyline。其初始化参数和Polyline一致,points是点序,options里设置其样式。

而箭头样式,需要在_render方法里实现。_render方法可以拿到ctx,即canvas的实例,我们可以利用ctx进行各种绘制操作。

注意:在_render这个步骤,每个几何都有自己的坐标系,其坐标系原点是几何的外接矩形的中心点。

因此,我们每个坐标都需要减去当前几何的width/2和height/2,进行原点平移。

举个例子,比如我们有一条线,其参数如下:

{left: 10,top: 10,points: [{x: 0, y: 0}, {x: 5, y: 0}, {x: 5, y: 5}],
}

在坐标系中,如图,

left和top将要素的坐标系从O移动到了O',在此基础上,绘制折线[[0,0],[5,0],[5,5]]。

在渲染时,fabric又将坐标原点O'平移到外接矩形的中心点O''。

知道坐标系后,我们先来求线段的中点:

const points = this.get('points');
const width = this.get('width');
const height = this.get('height');for (let i = 0; i < points.length; i++) {const midX = (points[i].x + points[i + 1].x) / 2 - width / 2;const midY = (points[i].y + points[i + 1].y) / 2 - height / 2;console.log(midX, midY);
}// 结果:
// -2.5, -2.5
// 2.5, -2.5
// 2.5, 2.5

看懂上面的代码,你就可以以线段中心点为中心,画沿着线段的三角形了,代码如下:

for (let i = 0; i < points.length - 1; i++) {const midX = (points[i].x + points[i + 1].x) / 2 - width / 2;const midY = (points[i].y + points[i + 1].y) / 2 - height / 2;const rotate = Math.atan2(points[i + 1].y - points[i].y, points[i + 1].x - points[i].x);ctx.moveTo(midX, midY);const firstX = midX - (arrowWidth / 2) * Math.sin(rotate);const firstY = midY + (arrowWidth / 2) * Math.cos(rotate);ctx.lineTo(firstX, firstY);const secondX = midX + (arrowWidth / 2) * Math.sqrt(3) * Math.cos(rotate);const secondY = midY + (arrowWidth / 2) * Math.sqrt(3) * Math.sin(rotate);ctx.lineTo(secondX, secondY);const thirdX = midX + (arrowWidth / 2) * Math.sin(rotate);const thirdY = midY - (arrowWidth / 2) * Math.cos(rotate);ctx.lineTo(thirdX, thirdY);ctx.closePath();ctx.fill();}

效果图如下:

了解这个原理,你就可以利用canvas的绘制操作实现任何的自定义样式。

缩放控制线宽等宽

上一章我们讲到了,画布是可以拖拽和缩放的,本质上是修改canvas的transform。

在每次缩放后,canvas会调用renderAll方法,从而调用每个几何的_render方法。在_render内,我们需要重新计算strokeWidth:

const strokeWidth = 5;
const zoom = canvas.getZoom();
this.set({strokeWidth: strokeWidth / zoom
});

这样可以保证每次缩放后,线宽依然维持一个固定值。如果我们不修改线宽,则会被同样得缩放。

预告

下一章,我们详细聊一个极其隐蔽的问题:线居中渲染。

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

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

相关文章

前端学习<三>CSS进阶——03-网页设计和开发中,那些困扰大神的关于字体的知识

前言 我周围的码农当中&#xff0c;有很多是技术大神&#xff0c;却常常被字体这种简单的东西所困扰。 这篇文章&#xff0c;我们来讲一讲关于字体的常识。这些常识所涉及到的问题&#xff0c;有很强的可操作性&#xff0c;都是在实际业务中真实遇到的&#xff0c;都是需要开…

软件资源分享六:EPLAN Electric P8 2024 | Eplan 2024 中文版软件介绍+保姆级安装教程

原文链接&#xff1a;安装激活教程 EPLAN Electric P8 2024 | Eplan 2024 中文版软件介绍安装教程 EPLAN 2024是一款电气设计软件&#xff0c;它可以用于自动化系统的设计、文档编制和维护。EPLAN可以对电气设计的各个方面进行完整的支持&#xff0c;包括电气控制系统、机械设…

Spring 整合 Log4j2日志框架

1. Log4j2日志概述 在项目开发中&#xff0c;日志十分的重要&#xff0c;不管是记录运行情况还是定位线上问题&#xff0c;都离不开对日志的分析。日志记录了系统行为的时间、地点、状态等相关信息&#xff0c;能够帮助我们了解并监控系统状态&#xff0c;在发生错误或者接近某…

【JavaSE】一维数组和二维数组详解

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 一维数组 基本语法 初始化 遍历和打印 数组是引用型变量 基本类型变量与引用类型变量的区别 null 数组传参和返回 总结 二维数组 基本语法 初始化 遍历和打印 一维数组…

论文精读--GPT4

现有的所有模型都无法做到在线学习&#xff0c;能力有限&#xff0c;而让大模型拥有一个tools工具库&#xff0c;则可以使大模型变成一个交互式的工具去协调调用API完成任务&#xff0c;同时GPT4还联网了&#xff0c;可以不断地更新自己的知识库 多模态模型&#xff0c;接受文…

单V及多V感知在自动驾驶在恶劣环境条件下的感知提升方案

单V及多V感知在自动驾驶在恶劣环境条件下的感知提升方案 附赠自动驾驶学习资料和量产经验&#xff1a;链接 自动驾驶中的视觉感知是车辆在不同交通条件下安全、可持续地行驶的关键部分。然而&#xff0c;在大雨和雾霾等恶劣天气下&#xff0c;视觉感知性能受到多种降级效应的极…

Pygame基础9-射击

简介 玩家用鼠标控制飞机&#xff08;白色方块&#xff09;移动&#xff0c;按下鼠标后&#xff0c;玩家所在位置出现子弹&#xff0c;子弹匀速向右飞行。 代码 没有什么新的东西&#xff0c;使用两个精灵类表示玩家和子弹。 有一个细节需要注意&#xff0c;当子弹飞出屏幕…

RK3568 学习笔记 : 独立修改与编译 u-boot

前言 开发板&#xff1a;【正点原子】ATomPi-CA1 开发板&#xff0c;配置&#xff1a;RK3568&#xff0c;4GB DDRAM 64GB emmc 开发板资料给了 u-boot 与 Linux kernel 源码&#xff0c;尝试手动编译。 本篇记录 收到编译 RK3568 平台 u-boot 的方法 环境搭建 由于 RK 平台…

椋鸟数据结构笔记#5:树、二叉树基础

文章目录 树树的相关概念树的表示 二叉树基础二叉树分类满二叉树完全二叉树 二叉树的性质二叉树的存储结构顺序存储链式存储 萌新的学习笔记&#xff0c;写错了恳请斧正。 树 树是一种非线性的数据结构&#xff0c;它是由 n 个节点组成的一个具有层次关系的数据集合。其大概结…

新手学python还是c?

考虑到个人情况和职业规划是非常重要的。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我在后台发给你。 Python作为初学者入门语言…

基于three-mesh-bvh实现第一人称及第三人称的漫游

基于three-mesh-bvh实现第一人称及第三人称的漫游 简介 这篇文章主要介绍在3d场景中实现第一人称与第三人称切换以及碰撞监测的漫游方案。 人称视角的场景漫游主要需要解决两个问题&#xff0c;人物在场景中的移动和碰撞检测。移动与碰撞功能是所有三维场景首先需要解决的基…

ObjectiveC-03-XCode的使用和基础数据类型

本节做为Objective-C的入门课程&#xff0c;笔者会从零基础开始介绍这种程序设计语言的各个方面。 术语 ObjeC&#xff1a;Objective-C的简称&#xff0c;因为完整的名称过长&#xff0c;后续会经缩写来代替&#xff1b;项目/工程&#xff1a;也称工程&#xff0c;指的是一个A…

【现代控制】倒立摆模型

基础公式 转动惯量&#xff1a; 欧拉拉格朗日等式 倒立摆模型建立 由拉格朗日等式推导出微分方程&#xff1a; 也就是 将zdot移到等式左边&#xff0c;化简得到 展开就是&#xff1a; 系统线性化 法一&#xff1a;雅可比矩阵 法二&#xff1a;小角度假设 化简最终得…

基于8086贪吃蛇游戏系统方恨设计

**单片机设计介绍&#xff0c;基于8086贪吃蛇游戏系统方恨设计 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于8086的贪吃蛇游戏系统设计是一个结合了微处理器控制、游戏逻辑以及图形显示技术的综合性项目。该系统旨在通过8086微处理器…

学习使用echats因xAxis值过多,可以滚动的柱状图解决方案

学习使用echats因xAxis值过多&#xff0c;可以滚动的柱状图解决方案 效果图柱状图代码关键代码 效果图 柱状图代码 function echarts() {// 基于准备好的dom&#xff0c;初始化echarts实例var myChart echarts.init(document.getElementById(echart4));let xaxisData [1, 2,…

篮球竞赛预约平台的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读300套最新项目持续更新中..... 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含ja…

LabelConvert: 目标检测和图像分割数据集格式转换工具

LabelConvert LabelConvert是一个目标检测和图像分割的数据集格式转换工具&#xff0c;支持labelme、labelImg与YOLO、VOC和COCO 数据集格式之间的相互转换。 支持的转换格式 安装 pip install label_convert具体使用方法 由于文章篇幅所限&#xff0c;请移步LabelConvert官…

idea 报错 Could not list the contents of folder “ftps

idea 报错 Could not list the contents of folder "ftps 解决方案 这里看到了网上的解决方案&#xff0c;顺便再记录一下。打开 【高级】菜单 - 取消勾选 被动模式。然后点击测试连接&#xff0c;显示连接成功&#xff01; ftp中的主动模式和被动模式 主动模式&…

GS1-全球分类标准

GS1 GS1是一个中立的全球合作平台&#xff0c;汇集行业领袖、政府、监管机构、学术界和协会&#xff0c;共同开发基于标准的解决方案&#xff0c;以应对数据交换的挑战。我们的规模和影响力——遍布 116 个国家/地区的当地会员组织、超过 200 万家用户公司和每天 100 亿笔交易—…

Python中os.environ基本介绍及使用方法

文章目录 python中os.environos.environ简介os.environ进行环境变量的增删改查 python中os.environ的使用详解1. 简介2. key 字段详解2.1 常见 key 字段 3. os.environ.get() 用法4. 环境变量的增删改查和判断是否存在4.1 新增环境变量4.2 更新环境变量4.3 获取环境变量4.4 删除…