前端使用 Konva 实现可视化设计器(22)- 绘制图形(矩形、直线、折线)

本章分享一下如何使用 Konva 绘制基础图形:矩形、直线、折线,希望大家继续关注和支持哈!

请大家动动小手,给我一个免费的 Star 吧~

大家如果发现了 Bug,欢迎来提 Issue 哟~

github源码

gitee源码

示例地址

矩形

先上效果!

在这里插入图片描述
在这里插入图片描述

实现方式基本和《前端使用 Konva 实现可视化设计器(21)- 绘制图形(椭圆)》是一致的,主要区别矩形的大小和椭圆形的大小设置方式不一样,特别是矩形无需设置 offset。其它就不再赘述了哈。

直线、折线

先上效果!

在这里插入图片描述
在这里插入图片描述

简单描述一下上面的交互:

首先,绘制一条直线,淡出画一条直线还是比较简单的,根据记录鼠标按下的位置和鼠标释放的位置,就很容易得到 Konva.Line 的 points 应该设定的值了。

然后,沿用绘制 椭圆形、矩形 的思路,它只有特定的 2 个“调整点”,分别代表 起点 和 终点。

// src/Render/graphs/Line.ts// 略/*** 直线、折线*/
export class Line extends BaseGraph {// 略constructor(render: Types.Render, dropPoint: Konva.Vector2d) {super(render, dropPoint, {type: Types.GraphType.Line,// 定义了 2 个 调整点anchors: [{ adjustType: 'start' }, { adjustType: 'end' }].map((o) => ({adjustType: o.adjustType // 调整点 类型定义})),linkAnchors: [{ x: 0, y: 0, alias: 'start' },{ x: 0, y: 0, alias: 'end' }] as Types.AssetInfoPoint[]})// 新建 直线、折线this.line = new Konva.Line({name: 'graph',x: 0,y: 0,stroke: 'black',strokeWidth: 1,hitStrokeWidth: render.toStageValue(5)})// 给予 1 像素,防止导出图片 toDataURL 失败this.group.size({width: 1,height: 1})// 加入this.group.add(this.line)// 鼠标按下位置 作为起点this.group.position(this.dropPoint)}// 实现:拖动进行时override drawMove(point: Konva.Vector2d): void {// 鼠标拖动偏移量const offsetX = point.x - this.dropPoint.x,offsetY = point.y - this.dropPoint.y// 起点、终点const linkPoints = [[this.line.x(), this.line.y()],[this.line.x() + offsetX, this.line.y() + offsetY]]// 直线、折线 路径this.line.points(_.flatten(linkPoints))// 更新 图形 的 调整点 的 锚点位置Line.updateAnchorShadows(this.group, this.anchorShadows, this.line)// 更新 图形 的 连接点 的 锚点位置Line.updateLinkAnchorShadows(this.group, this.linkAnchorShadows, this.line)// 重绘this.render.redraw([Draws.GraphDraw.name, Draws.LinkDraw.name, Draws.PreviewDraw.name])}// 实现:拖动结束override drawEnd(): void {if (this.line.width() <= 1 && this.line.height() <= 1) {// 加入只点击,无拖动// 默认大小const width = Line.size,height = width// 起点、终点const linkPoints = [[this.line.x(), this.line.y()],[this.line.x() + width, this.line.y() + height]]// 直线、折线 位置大小this.line.points(_.flatten(linkPoints))}// 更新 调整点(拐点)Line.updateAnchor(this.render, this.group)// 更新 图形 的 调整点 的 锚点位置Line.updateAnchorShadows(this.group, this.anchorShadows, this.line)// 更新 图形 的 连接点 的 锚点位置Line.updateLinkAnchorShadows(this.group, this.linkAnchorShadows, this.line)// 对齐线清除this.render.attractTool.alignLinesClear()// 更新历史this.render.updateHistory()// 重绘this.render.redraw([Draws.GraphDraw.name, Draws.LinkDraw.name, Draws.PreviewDraw.name])}// 略
}

调整点,可以改变 直线、折线 的 起点、终点。

// 略/*** 直线、折线*/
export class Line extends BaseGraph {// 实现:更新 图形 的 调整点 的 锚点位置static override updateAnchorShadows(graph: Konva.Group,anchorShadows: Konva.Circle[],shape?: Konva.Line): void {if (shape) {const points = shape.points()//for (const shadow of anchorShadows) {switch (shadow.attrs.adjustType) {case 'start':shadow.position({x: points[0],y: points[1]})breakcase 'end':shadow.position({x: points[points.length - 2],y: points[points.length - 1]})break}}}}// 略// 实现:生成 调整点static override createAnchorShapes(render: Types.Render,graph: Konva.Group,anchorAndShadows: {anchor: Types.GraphAnchoranchorShadow: Konva.Circleshape?: Konva.Shape}[],adjustAnchor?: Types.GraphAnchor): {anchorAndShadows: {anchor: Types.GraphAnchoranchorShadow: Konva.Circleshape?: Konva.Shape | undefined}[]} {// stage 状态const stageState = render.getStageState()const graphShape = graph.findOne('.graph') as Konva.Lineif (graphShape) {const points = graphShape.points()for (const anchorAndShadow of anchorAndShadows) {let rotate = 0const { anchor, anchorShadow } = anchorAndShadowconst x = render.toStageValue(anchorShadow.getAbsolutePosition().x - stageState.x),y = render.toStageValue(anchorShadow.getAbsolutePosition().y - stageState.y)if (anchor.adjustType === 'manual') {// 略} else {if (anchor.adjustType === 'start') {rotate = Line.calculateAngle(points[2] - points[0], points[3] - points[1])} else if (anchor.adjustType === 'end') {rotate = Line.calculateAngle(points[points.length - 2] - points[points.length - 4],points[points.length - 1] - points[points.length - 3])}const cos = Math.cos((rotate * Math.PI) / 180)const sin = Math.sin((rotate * Math.PI) / 180)const offset = render.toStageValue(render.pointSize + 5)const offsetX = offset * sinconst offsetY = offset * cosconst anchorShape = new Konva.Circle({name: 'anchor',anchor: anchor,//fill:adjustAnchor?.adjustType === anchor.adjustType && adjustAnchor?.groupId === graph.id()? 'rgba(0,0,255,0.8)': 'rgba(0,0,255,0.2)',radius: render.toStageValue(3),strokeWidth: 0,// 位置x: x,y: y,offsetX:anchor.adjustType === 'start' ? offsetX : anchor.adjustType === 'end' ? -offsetX : 0,offsetY:anchor.adjustType === 'start' ? offsetY : anchor.adjustType === 'end' ? -offsetY : 0,// 旋转角度rotation: graph.getAbsoluteRotation()})anchorShape.on('mouseenter', () => {anchorShape.fill('rgba(0,0,255,0.8)')document.body.style.cursor = 'move'})anchorShape.on('mouseleave', () => {anchorShape.fill(anchorShape.attrs.adjusting ? 'rgba(0,0,255,0.8)' : 'rgba(0,0,255,0.2)')document.body.style.cursor = anchorShape.attrs.adjusting ? 'move' : 'default'})anchorAndShadow.shape = anchorShape}}}return { anchorAndShadows }}// 略// 实现:调整 图形static override adjust(render: Types.Render,graph: Konva.Group,graphSnap: Konva.Group,adjustShape: Konva.Shape,anchorAndShadows: {anchor: Types.GraphAnchoranchorShadow: Konva.Circleshape?: Konva.Shape | undefined}[],startPoint: Konva.Vector2d,endPoint: Konva.Vector2d) {// 目标 直线、折线const line = graph.findOne('.graph') as Konva.Line// 镜像const lineSnap = graphSnap.findOne('.graph') as Konva.Line// 调整点 锚点const anchors = (graph.find('.anchor') ?? []) as Konva.Circle[]// 镜像const anchorsSnap = (graphSnap.find('.anchor') ?? []) as Konva.Circle[]// 连接点 锚点const linkAnchors = (graph.find('.link-anchor') ?? []) as Konva.Circle[]if (line && lineSnap) {// stage 状态const stageState = render.getStageState(){const [graphRotation, adjustType, ex, ey] = [Math.round(graph.rotation()),adjustShape.attrs.anchor?.adjustType,endPoint.x,endPoint.y]const { x: cx, y: cy, width: cw, height: ch } = graphSnap.getClientRect()const { x, y } = graph.position()const [centerX, centerY] = [cx + cw / 2, cy + ch / 2]const { x: sx, y: sy } = Line.rotatePoint(ex, ey, centerX, centerY, -graphRotation)const { x: rx, y: ry } = Line.rotatePoint(x, y, centerX, centerY, -graphRotation)const points = line.points()const manualPoints = (line.attrs.manualPoints ?? []) as Types.LineManualPoint[]if (adjustType === 'manual') {// 略} else {const anchor = anchors.find((o) => o.attrs.adjustType === adjustType)const anchorShadow = anchorsSnap.find((o) => o.attrs.adjustType === adjustType)if (anchor && anchorShadow) {{const linkPoints = [[points[0], points[1]],...manualPoints.sort((a, b) => a.index - b.index).map((o) => [o.x, o.y]),[points[points.length - 2], points[points.length - 1]]]switch (adjustType) {case 'start':{linkPoints[0] = [sx - rx, sy - ry]line.points(_.flatten(linkPoints))}breakcase 'end':{linkPoints[linkPoints.length - 1] = [sx - rx, sy - ry]line.points(_.flatten(linkPoints))}break}}}}}// 更新 调整点(拐点)Line.updateAnchor(render, graph)// 更新 调整点 的 锚点 位置Line.updateAnchorShadows(graph, anchors, line)// 更新 图形 的 连接点 的 锚点位置Line.updateLinkAnchorShadows(graph, linkAnchors, line)// 更新 调整点 位置for (const anchor of anchors) {for (const { shape } of anchorAndShadows) {if (shape) {if (shape.attrs.anchor?.adjustType === anchor.attrs.adjustType) {const anchorShadow = graph.find(`.anchor`).find((o) => o.attrs.adjustType === anchor.attrs.adjustType)if (anchorShadow) {shape.position({x: render.toStageValue(anchorShadow.getAbsolutePosition().x - stageState.x),y: render.toStageValue(anchorShadow.getAbsolutePosition().y - stageState.y)})shape.rotation(graph.getAbsoluteRotation())}}}}}// 重绘render.redraw([Draws.GraphDraw.name, Draws.LinkDraw.name, Draws.PreviewDraw.name])}}// 略
}

折线

相比绘制 椭圆形、矩形 比较不一样的地方在于,椭圆形、矩形 的“调整点”是固定的,而绘制 折线 不一样,没调整一个新的拐点,就会新增 2 个新调整点,整体交互与 手动连接线 类似。

在这里插入图片描述

// src/Render/draws/GraphDraw.ts// 略export interface GraphDrawState {// 略/*** 调整中 调整点*/adjustAnchor?: Types.GraphAnchor/*** 鼠标按下 调整点 位置*/startPointCurrent: Konva.Vector2d/*** 图形 group*/graphCurrent?: Konva.Group/*** 图形 group 镜像,用于计算位置、大小的偏移*/graphCurrentSnap?: Konva.Group
}// 略export class GraphDraw extends Types.BaseDraw implements Types.Draw {// 略state: GraphDrawState = {adjusting: false,adjustGroupId: '',startPointCurrent: { x: 0, y: 0 }}// 略override draw() {this.clear()// 所有图形const graphs = this.render.layer.find('.asset').filter((o) => o.attrs.assetType === Types.AssetType.Graph) as Konva.Group[]for (const graph of graphs) {// 非选中状态才显示 调整点if (!graph.attrs.selected) {// 略for (const anchorAndShadow of anchorAndShadows) {const { shape } = anchorAndShadowif (shape) {// 鼠标按下shape.on('mousedown', () => {const pos = this.getStagePoint()if (pos) {this.state.adjusting = truethis.state.adjustAnchor = shape.attrs.anchorthis.state.adjustGroupId = graph.id()this.state.startPointCurrent = posthis.state.graphCurrent = graphthis.state.graphCurrentSnap = graph.clone()shape.setAttr('adjusting', true)if (this.state.adjustAnchor) {switch (shape.attrs.anchor?.type) {case Types.GraphType.Line:// 使用 直线、折线 静态处理方法Graphs.Line.adjustStart(this.render, graph, this.state.adjustAnchor, pos)break}}}})// 略// 调整结束this.render.stage.on('mouseup', () => {// 略this.state.adjusting = falsethis.state.adjustAnchor = undefinedthis.state.adjustGroupId = ''// 恢复显示所有 调整点for (const { shape } of anchorAndShadows) {if (shape) {shape.opacity(1)shape.setAttr('adjusting', false)if (shape.attrs.anchor?.type === Types.GraphType.Line) {if (shape.attrs.anchor.adjusted) {shape.fill('rgba(0,0,0,0.4)')} else {shape.fill('rgba(0,0,255,0.2)')}} else {shape.stroke('rgba(0,0,255,0.2)')}}// 略}// 略})// 略}}}}}
}

上面除了需要更多的状态记录 调整 信息,还需要定义 Line 特有的 adjustStart 方法:

// src/Render/graphs/Line.ts// 略/*** 直线、折线*/
export class Line extends BaseGraph {// 略/*** 调整之前*/static adjustStart(render: Types.Render,graph: Konva.Group,adjustAnchor: Types.GraphAnchor & { manualIndex?: number; adjusted?: boolean },endPoint: Konva.Vector2d) {const { x: gx, y: gy } = graph.position()const shape = graph.findOne('.graph') as Konva.Lineif (shape && typeof adjustAnchor.manualIndex === 'number') {const manualPoints = (shape.attrs.manualPoints ?? []) as Types.LineManualPoint[]if (adjustAnchor.adjusted) {//} else {manualPoints.push({x: endPoint.x - gx,y: endPoint.y - gy,index: adjustAnchor.manualIndex})shape.setAttr('manualPoints', manualPoints)}// 更新 调整点(拐点)Line.updateAnchor(render, graph)}}
}// 略

动态的调整点,会记录在 line 的 attrs 中 manualPoints,每次首次调整一处 拐点,就会新增一个 新 拐点,主要应用在:

// 略/*** 直线、折线*/
export class Line extends BaseGraph {// 略// 实现:调整 图形static override adjust(render: Types.Render,graph: Konva.Group,graphSnap: Konva.Group,adjustShape: Konva.Shape,anchorAndShadows: {anchor: Types.GraphAnchoranchorShadow: Konva.Circleshape?: Konva.Shape | undefined}[],startPoint: Konva.Vector2d,endPoint: Konva.Vector2d) {// 目标 直线、折线const line = graph.findOne('.graph') as Konva.Line// 镜像const lineSnap = graphSnap.findOne('.graph') as Konva.Line// 调整点 锚点const anchors = (graph.find('.anchor') ?? []) as Konva.Circle[]// 镜像const anchorsSnap = (graphSnap.find('.anchor') ?? []) as Konva.Circle[]// 连接点 锚点const linkAnchors = (graph.find('.link-anchor') ?? []) as Konva.Circle[]if (line && lineSnap) {// stage 状态const stageState = render.getStageState(){const [graphRotation, adjustType, ex, ey] = [Math.round(graph.rotation()),adjustShape.attrs.anchor?.adjustType,endPoint.x,endPoint.y]const { x: cx, y: cy, width: cw, height: ch } = graphSnap.getClientRect()const { x, y } = graph.position()const [centerX, centerY] = [cx + cw / 2, cy + ch / 2]const { x: sx, y: sy } = Line.rotatePoint(ex, ey, centerX, centerY, -graphRotation)const { x: rx, y: ry } = Line.rotatePoint(x, y, centerX, centerY, -graphRotation)const points = line.points()const manualPoints = (line.attrs.manualPoints ?? []) as Types.LineManualPoint[]if (adjustType === 'manual') {if (adjustShape.attrs.anchor?.manualIndex !== void 0) {const index = adjustShape.attrs.anchor?.adjusted? adjustShape.attrs.anchor?.manualIndex: adjustShape.attrs.anchor?.manualIndex + 1const manualPointIndex = manualPoints.findIndex((o) => o.index === index)if (manualPointIndex > -1) {manualPoints[manualPointIndex].x = sx - rxmanualPoints[manualPointIndex].y = sy - ry}const linkPoints = [[points[0], points[1]],...manualPoints.sort((a, b) => a.index - b.index).map((o) => [o.x, o.y]),[points[points.length - 2], points[points.length - 1]]]line.setAttr('manualPoints', manualPoints)line.points(_.flatten(linkPoints))//const adjustAnchorShadow = anchors.find((o) => o.attrs.adjustType === 'manual' && o.attrs.manualIndex === index)if (adjustAnchorShadow) {adjustAnchorShadow.position({x: sx - rx,y: sy - ry})}}} else {// 略}}// 略}}// 略/*** 更新 调整点(拐点)* @param render* @param graph*/static updateAnchor(render: Types.Render, graph: Konva.Group) {const anchors = graph.attrs.anchors ?? []const anchorShadows = graph.find('.anchor') ?? []const shape = graph.findOne('.graph') as Konva.Lineif (shape) {// 已拐let manualPoints = (shape.attrs.manualPoints ?? []) as Types.LineManualPoint[]const points = shape.points()// 调整点 + 拐点const linkPoints = [[points[0], points[1]],...manualPoints.sort((a, b) => a.index - b.index).map((o) => [o.x, o.y]),[points[points.length - 2], points[points.length - 1]]]// 清空 调整点(拐点),保留 start endanchors.splice(2)const shadows = anchorShadows.splice(2)for (const shadow of shadows) {shadow.remove()shadow.destroy()}manualPoints = []for (let i = linkPoints.length - 1; i > 0; i--) {linkPoints.splice(i, 0, [])}// 调整点(拐点)for (let i = 1; i < linkPoints.length - 1; i++) {const anchor = {type: graph.attrs.graphType,adjustType: 'manual',//name: 'anchor',groupId: graph.id(),//manualIndex: i,adjusted: false}if (linkPoints[i].length === 0) {anchor.adjusted = false// 新增const prev = linkPoints[i - 1]const next = linkPoints[i + 1]const circle = new Konva.Circle({adjustType: anchor.adjustType,anchorType: anchor.type,name: anchor.name,manualIndex: anchor.manualIndex,radius: 0,// radius: render.toStageValue(2),// fill: 'red',//x: (prev[0] + next[0]) / 2,y: (prev[1] + next[1]) / 2,anchor})graph.add(circle)} else {anchor.adjusted = true// 已拐const circle = new Konva.Circle({adjustType: anchor.adjustType,anchorType: anchor.type,name: anchor.name,manualIndex: anchor.manualIndex,adjusted: true,radius: 0,// radius: render.toStageValue(2),// fill: 'red',//x: linkPoints[i][0],y: linkPoints[i][1],anchor})graph.add(circle)manualPoints.push({x: linkPoints[i][0],y: linkPoints[i][1],index: anchor.manualIndex})}anchors.push(anchor)}shape.setAttr('manualPoints', manualPoints)graph.setAttr('anchors', anchors)}}// 略
}

上面简单的说,就是处理 manualPoints 的算法,负责控制新增拐点,然后把“点”们插入到 起点、终点 之间,最后处理成 Konva.Line 的 points 的值。

顺带一说。区分 起点、终点 和 拐点 是通过 attrs 中的 adjustType 字段;区分 拐点 是否已经操作过 是通过 attrs 中的 adjusted 字段;拐点是存在明确的顺序的,会记录在 attrs 的 manualIndex 字段中。

个人觉得,目前,绘制图形的 代码结构 和 变量命名 容易产生歧义,后面尽量抽出时间重构一下,大家支持支持 👇!

Thanks watching~

More Stars please!勾勾手指~

源码

gitee源码

示例地址

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

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

相关文章

实现C程序绑定TCP端口

实现C程序绑定TCP端口 步骤概述伪代码C代码实现解释在网络编程中,TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。绑定TCP端口是服务器端应用程序在网络通信中的一个关键步骤,它允许服务器监听来自客户端的连接请求。 本文将介绍如何使用C语言…

Caffenie配合Redis做两级缓存

一、什么是两级缓存 在项目中。一级缓存用Caffeine&#xff0c;二级缓存用Redis&#xff0c;查询数据时首先查本地的Caffeine缓存&#xff0c;没有命中再通过网络去访问Redis缓存&#xff0c;还是没有命中再查数据库。具体流程如下 二、简单的二级缓存实现-v1 目录结构 2…

基于SpringBoot+Vue+MySQL的房屋租赁管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 二十一世纪互联网的出现&#xff0c;改变了几千年以来人们的生活&#xff0c;不仅仅是生活物资的丰富&#xff0c;还有精神层次的丰富。在互联网诞生之前&#xff0c;地域位置往往是人们思想上不可跨域的鸿沟&#xff0c;信息的…

uniapp 携带网址跳转webview页面报错解决

然后红框中的代码正常执行的 解决方案&#xff1a; 向webview页面携带参数时做以下处理&#xff1a; 接参后做以下处理&#xff1a; 效果展示&#xff1a;

谷歌怎么导入egd书签

https://support.google.com/chrome/answer/96816?hlzh-Hans

0906作业+思维导图梳理

一、作业&#xff1a; 1、创捷一个类似于qq登录的界面 1&#xff09;源代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//QPushbutton:登录、退出this-…

代码随想录训练营 Day56打卡 图论part06 108. 冗余连接 109. 冗余连接II

代码随想录训练营 Day56打卡 图论part06 一、卡码108. 冗余连接 题目描述 有一个图&#xff0c;它是一棵树&#xff0c;他是拥有 n 个节点&#xff08;节点编号1到n&#xff09;和 n - 1 条边的连通无环无向图&#xff08;其实就是一个线形图&#xff09;&#xff0c;如图&…

二、Android Studio集成ffmpeg so

目录 1、前言 2、新建AS工程 2.1 选择Native C 2.2 按图编辑和编辑 2.3 选择C标准 2.4 最初工程目录展示 3、拷贝so库到AS 4、编辑CMakeLists.txt 5、修改build.gradle 6、编辑Native-lib.cpp 7、修改MainActivity.java 8、效果展示 1、前言 本文章之前也是参考了…

HTML5中IndexedDB前端本地数据库

一、indexedDB为何替代了Web SQL Database&#xff1f; 跟小朋友的教育从来没有什么“赢在起跑线”这种说法一样&#xff0c;在前端领域&#xff0c;也不是哪来先出来哪个就在日后引领风骚的。 HTML5 indexedDB和Web SQL Database都是本地数据库数据存储&#xff0c;Web SQL Da…

DX-5009N 10G交换机 SFP接口+猫棒 代替运营商光猫 【注册状态O5但是无法PPPoe拨号踩坑——交换机VLAN配置】

买了个诺基亚 猫棒&#xff0c;准备代替光猫&#xff0c;还弱电箱一个清净 参数填完一切正常&#xff0c;注册状态O5 但是openwrt拨号死活上不去。windows拨号也是651 网络架构 SPF口与网口8为同一vlan&#xff0c;做光电转换&#xff0c;交给路由器wan口 路由器PPPoe拨号 1-7网…

『功能项目』播放动画时禁止点击移动【40】

我们打开上一篇39GameObject对象池 - 第三职业的项目&#xff0c; 本章要做的事情是在第三职业播放续航攻击动画时禁止点击时触发的移动函数&#xff0c;换句话说是在播放攻击动画时禁止移动 修改脚本&#xff1a;PlayerRayClickNavigation.cs 运行项目 - 播放第三职业续航技能…

(十四)、为 SpringCloud 项目生成 Docker 镜像

文章目录 1、原理2、最佳实践2.1、获得 SpringCloud 微服务启动模块的 jar 文件2.2、准备文件夹和 Dockerfile 文件2.3、 Dockerfile 文件的内容2.4、通过命令行构件新镜像 3、异常情况和处理&#xff1a;failed to create LLB definition3.1、现象3.2、解决配置国内镜像仓库清…

OpenGL——着色器画一个点

一、 绘制 在窗口中间画一个像素点&#xff1a; #include <GL/glew.h> #include <GLFW/glfw3.h> #include <iostream>using namespace std;#define numVAOs 1GLuint renderingProgram; GLuint vao[numVAOs];GLuint createShaderProgram () {const char *v…

SQL的增删改查CRUD练习知识点(day27)

1 学习目标 重点掌握插入单条记录的语法了解全表插入记录的语法重点掌握修改记录的语法重点掌握删除记录的语法重点掌握主键约束、外键约束了解检查约束、非空约束、唯一约束 2 数据类型 MySQL支持多种数据类型&#xff0c;大致可以分类三类&#xff1a;数值、日期和字符串。…

【Maven】Maven 下载安装教程(超详细)(day30)

1 学习目标 了解Spring了解SpringBoot重点掌握创建SpringBoot项目重点掌握聚合项目的创建了解Spring基于XML方法进行IOC和依赖注入了解Maven的概念重点掌握使用Maven构建项目重点掌握使用Maven进行依赖引入 2 Maven 2.1 概述 Maven是跨平台的项目管理工具。作为Apache组织中…

Python(一)-快速入门

第一个入门实例 print(hello python) 注释 #:单行注释""" """:多行注释 # 这是单行注释 # 输出一个喜欢读的课外书 print("我最喜欢读 追风筝的人")print("----------------------------")"""这是多…

Python爱心射线

系列目录 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3Python无限弹窗满屏表白代码4Python李峋同款可写字版跳动的爱心5Python流星雨代码6Python漂浮爱心代码7Python爱心光波代码8Python普通的玫瑰花代码9Python炫酷的玫瑰花代码10Python多…

004——双向链表和循环链表

目录 双向链表 双向链表的初始化&#xff08;与单链表类似&#xff09; 增&#xff1a; Ⅰ&#xff09;头插法 Ⅱ&#xff09;尾插法 Ⅲ&#xff09;中间插入 删 改 查 整体代码示例&#xff1a; 循环链表 循环单链表 ​编辑 循环双链表 双向链表 不同于单链表&…

2024年录屏神器大盘点,轻松捕捉屏幕精彩

现在讲解一些操作越来越便捷了&#xff0c;我 一般都是用录屏工具来边录制操作边讲解&#xff0c;这样可以更方便对方了解操作步骤。这次我就分享几款免费录屏工具一起来试试吧。 1.福晰录屏软件 链接&#xff1a;www.foxitsoftware.cn/REC/ 对于初次尝试录屏的新手来说&…

每天五分钟玩转深度学习框架PyTorch:获取神经网络模型的参数

本文重点 当我们定义好神经网络之后,这个网络是由多个网络层构成的,每层都有参数,我们如何才能获取到这些参数呢?我们将再下面介绍几个方法来获取神经网络的模型参数,此文我们是为了学习第6步(优化器)。 获取所有参数Parameters from torch import nn net=nn.Sequent…