图形系统开发实战课程:进阶篇(上)——7.图形交互操作: 视点控制与动画


[

图形开发学院|GraphAnyWhere

  • 课程名称:图形系统开发实战课程:进阶篇(上)
  • 课程章节:“图形交互操作: 视点控制与动画”
  • 原文地址:https://www.graphanywhere.com/graph/advanced/2-7.html

第七章 图形交互操作: 视点控制与动画

\quad 视点控制是指在图形系统中,通过调整视点的位置和角度,来改变用户观察图形的范围。本章我们讲述如何在图形初始化时控制图形视点,以及通过API控制图形视点。

1. 视图对象

\quad 在第二章 图形管理类(Graph)中讲述过图形管理对象相关的类包括:Graph类、Layer类、View类、GraphRenderer类,其中Graph类是这几个类的核心,负责构建另外几个类,并提供外部访问api接口;GraphRenderer类是负责图形的渲染过程、Layer类负责图层属性、图层数据和图层的渲染、View类负责图形的视点控制。

\quad 本节我们来讲述视图控制类 View,这几个类的关系如下图所示:

Graph
name:String
layers:Array
addLayer(layer)
removeLayer(layer)
render()
setView(view)
getCoordinateFromPixel(pixel)
getPixelFromCoordinate(coordinate)
GraphRenderer
mainCanvas:Canvas
getSize()
prepareFrame()
composeBuffer(frameState)
renderFrame()
filter()
View
center: [float,float]
resolutions:float
zoom: int
fill()
calculateCenterZoom()
getState()
Layer
source: Source
renderer: LayerRenderer
setStyle(style)
getVisible()
visibleAtResolution()
setOffset(x, y)

\quad 视图对象主要用于控制图形的显示范围。下图显示的是某个图形的全图,而红色框内的是当前屏幕中显示的内容,称之为当前视点范围或图形显示范围。

在这里插入图片描述

\quad 在第五章 图形交互操作:平移和缩放中,我们讲述过,实现图形的缩放与平移其核心思路是改变图形的显示范围,而不是改变图形中各图形对象的坐标值。图形显示范围(Extent) 是指图形在屏幕或窗口中的可视区域,是一个由显示的图形中最小坐标值(min)和最大坐标值(max)确定的矩形区域,图形显示范围采用图形坐标来表达,可记录为[minX, minY, maxX, maxY]

\quad 在SVG图形中,当前图形视点范围称之为 ViewBox,在SVG文件中由根节点的 viewBox 属性指定,例如 viewBox='40 20 300 200' ;此外还有一个 ViewPort 属性,指的是当前图形在浏览器中显示的宽度和高度,在SVG文件中由根节点的 widthheight 属性指定。

\quad anyGraph 中,也存在上述两个概念,图形显示范围 对应的就是 viewBox ,而 Canvas 画布大小对应的就是 viewPort。而 视图对象 除了包含图形显示范围这些属性之外,还提供了 视图约束 方面的属性。

1.1 属性

名称说明
center当前的中心点坐标
resolution当前的分辨率
viewPortSizeviewPort大小
resolutions图形分辨率数组
minResolution最小分辨率
maxResolution最大分辨率
extentConstrain允许显示的最大图形范围

说明:

  • center 和 resolution 这两个属性是View类中最常用的两个属性,表达的是当前图形显示范围的中心点坐标和分辨率;
  • viewPortSize viewPort大小,本质上就是Canvas尺寸;
  • resolutions 分辨率数组,常用于分级缩放的图形系统中,表达的是每一个缩放级别的分辨率;
  • minResolution 最小分辨率,是指在图形缩放时所允许的最小分辨率;
  • maxResolution 最大分辨率,是指在图形缩放时所允许的最大分辨率;
  • extentConstrain 属性用于约束图形移动的范围;

1.2 方法

名称说明
setCenter(center)设置中心点坐标
setResolution(resolution)设置当前分辨率
calculateCenterZoom(resolution, anchor)根据锚点和分辨率计算中心点
fill(extent, size)改变视图位置,根据四角坐标和窗口像素宽高
getExtent()获取图形显示范围
getCenter()获取中心点坐标
getResolution()返回当前的分辨率
getZoom()返还当前的zoom level

说明:

  • setCenter(center) 设置中心点坐标,该坐标将限制在 extentConstrain 范围内;
  • setResolution(resolution) 设置当前分辨率,分辨率也将限制在 minResolution 和 maxResolution的范围内;

2. 图形初始化时控制视点

\quad anyGraph 通过 视图对象(View) 控制图形的显示。在初始化 Graph 对象的时候如果指定了 view 属性,则按照 view 属性指定的信息显示图形。如果没有指定 view 属性,则默认按照图形坐标与 Canvas坐标 1:1 的方式显示图形,此外还提供了 fullView 属性,设置为 true 时可在初始化的时候显示全图。

\quad 下面我们通过几个示例来熟悉视图控制方面的功能。

2.1 显示默认图形

\quad 在初始化Graph对象时,如果没有指定任何显示相关的属性,图形初始化之后将按照图形坐标与Canvas坐标1:1的方式(即 resolution=1 )显示图形。如果图形的内容较多,这种方式只会显示图形的一部分。

\quad 下面这段代码在初始化时没有指定任何显示相关的属性,源代码如下:

<script type="module">import { Graph, VectorSource, Layer, debug } from "../../../src/index.js";// 初始化graph对象let graph = new Graph({"target": "graphWrapper","layers": [new Layer({source: new VectorSource({"fileUrl": "../../../data/geom.json"}),zIndex: 10010,name: "数据层"})]});// 显示辅助网格debug.generateGrid(Object.assign({ "interval": 10, "graph": graph }, graph.getSize()));// 图形渲染graph.render();
</script>

\quad 运行效果如下图所示:

在这里插入图片描述

2.2 显示全图

\quad 下面这个示例,在初始化 Graph 对象时,通过 fullView=true 属性,指定图形初始化之后显示全图,如果图形内容较少,则会放大图形充满整个Canvas画布,如果图形内容较多,则会缩小图形至Canvas画布中。

<script type="module">import { Graph, VectorSource, Layer, debug } from "../../../src/index.js";// 初始化graph对象let graph = new Graph({"target": "graphWrapper","fullView": true,"layers": [new Layer({source: new VectorSource({"fileUrl": "../../../data/geom.json"}),zIndex: 10010,name: "数据层"})]});// 显示辅助网格debug.generateGrid(Object.assign({ "interval": 10, "graph": graph }, graph.getSize()));// 图形渲染graph.render();
</script>

\quad 运行效果如下图所示:

在这里插入图片描述

2.3 显示指定位置

\quad 下面这个示例,在初始化Graph对象时,设置 view 属性,在该属性中指定了初始视图的中心点坐标 center 和分辨率 resolutionGraph 对象初始完成之后将按照这两个信息显示图形位置。

<script type="module">import { Graph, View, VectorSource, Layer, debug } from "../../../src/index.js";// 初始化graph对象let graph = new Graph({"target": "graphWrapper","fullView": true,"layers": [new Layer({source: new VectorSource({"fileUrl": "../../../data/geom.json"}),zIndex: 10010,name: "数据层"})],"view": new View({center: [220, 240],   // 初始中心点resolution: 0.5       // 初始分辨率})});// 显示辅助网格debug.generateGrid(Object.assign({ "interval": 10, "graph": graph }, graph.getSize()));// 图形渲染graph.render();
</script>

\quad 运行效果如下图所示:

在这里插入图片描述

3. 使用API控制视点

\quad Graph 类中包含了对 视图对象的实例,可通过 setView()getView() 方法设置和获取 视图对象,同时还提供了以下几个方法通过修改视图对象属性而控制图形的当前视点。

名称说明
showExtent(extent)设置图形显示范围,并重绘图形
setView(view)设置中心点和密度,并重绘图形
getFullExtent()根据各图层的数据计算当前图形的最大范围

3.1 显示全图

\quad 下面这段代码,可将当前图形的显示范围改变为显示全图。

let maxExtent = graph.getFullExtent();
graph.showExtent(maxExtent);

3.2 显示指定坐标

\quad 下面这段代码,可将当前图形的显示范围改变为显示指定坐标位置,并按指定分辨率控制图形大小。

let center = [280, 200];
let resolution = 0.25;
if (graph.getView().setResolution(resolution)) {graph.getView().setCenter(center);
}
graph.render();

3.3 显示指定范围

\quad 下面这段代码,可将当前图形的显示范围改变为显示指定的图形范围。

let extent = [200, 120, 400, 220];
graph.showExtent(extent);

4. 动画

\quad 在图形系统中,动画是由一系列叫做“帧(frame)”的图形组成的,通过一系列连续的画面来展示物体或场景的运动和变化。它们以一定的帧率(即每秒显示的帧数)进行播放,从而在视觉上呈现出连续的运动效果。

\quad 一帧即对应了一幅图形,在1秒内如果能够重复绘制15帧以上,图形看起来就不卡了,通常所说的60帧是指每秒重绘60次,这已经超过了人眼的极限,可以达到非常流畅的效果。

\quad 在图形系统开发实战课程-第八章动画 中讲述了在浏览器中实现动画功能的几种方法,分别是setInterval()setTimeout()requestAnimationFrame() 。从对动画的精确控制和节省计算机资源等角度,推荐在浏览器中使用requestAnimationFrame() 实现动画。

\quad 图形系统中通常按以下几个步骤实现动画:

  1. 清空Canvas
  2. 绘制当前帧图形
  3. 计算下一帧图形数据
  4. 循环,重复上述过程

\quad 直接使用 requestAnimationFrame() 实现动画时,需要在每一帧绘制完成后再次调用 requestAnimationFrame() 且需要自己编程实现帧率的控制,或是自己编码实现动画持续的时间等功能。anyGraph 中提供了一个 Animation 工具类,封装了这几个功能。

4.1 Animation 工具类

Animation 工具类提供了以下几个方法:

名称说明
start(callback, duration, frameRate)开始动画
stop(animationId)停止动画
frame(callback)显示一帧动画
start()

下表为该方法的参数:

名称说明
callback回调函数
duration持续时间
frameRate帧率

\quad 该方法用于开始一段动画,callback 参数用于指定回调函数,对于图形系统而言,我们在该回调方法中重绘图形。 duration 用于指定动画持续的时间,如果没有指定该参数,则动画一直重复下去,直至通过 stop 方法来停止该动画。 frameRate 用于指定帧率,即每秒执行的次数,对于某些不需要在1秒内频繁刷新的动画(例如时钟),我们可通过该参数来降低系统运行资源。

\quad 由于采用了 window.requestAnimationFrame(frame) 动画技术,该方式为根据屏幕刷新率控制帧率,因此屏幕刷新率即为最大帧率。

stop()

\quad 在执行 star() 方法开始一段动画时,star() 方法会返回一个整数类型的 “动画ID”,调用stop()方法时通过该 “动画ID” 结束该动画。

Animation源代码

\quad 以下为Animation的源代码:

/*** 动画工具类*/
const Animation = (function (window) {// 缺省帧率60帧/秒let TIME = Math.floor(1000 / 60);let stop, frame;let frames = {};let lastFrameTime = 0;let counter = 0;let loops = {};if (typeof window.requestAnimationFrame === 'function' && typeof window.cancelAnimationFrame === 'function') {frame = function (callback) {let id = Math.random();frames[id] = requestAnimationFrame(function onFrame(time) {if (lastFrameTime === time || lastFrameTime + TIME - 1 < time) {lastFrameTime = time;delete frames[id];callback();} else {frames[id] = requestAnimationFrame(onFrame);}});return id;};stop = function (id) {if (frames[id]) {cancelAnimationFrame(frames[id]);}delete loops[id];};} else {frame = function (callback) {return setTimeout(callback, TIME);};stop = function (timer) {delete loops[timer];return clearTimeout(timer);};}/*** 开始动画* @param {*} callback 绘制帧函数* @param {*} duration 持续时间(动画执行时长(秒))* @param {*} frameRate 帧率(每秒执行多少次)* @returns */function start(callback, duration=0, frameRate=0) {duration = duration > 0 ? duration : Number.POSITIVE_INFINITY;if(frameRate > 0) {TIME = Math.floor(1000 / frameRate);}let id = ++counter;let start = Date.now();loops[id] = function () {if (loops[id] && Date.now() - start <= duration) {callback();if (loops[id]) {frame(loops[id]);}} else {delete loops[id];}};frame(loops[id]);return id;}return { frame,     // 执行一次 callbackstart,     // 开始循环执行 callbackstop       // 停止动画};
}(window));

4.2 缓动功能

\quad 现实生活中,物体并不是突然启动或者停止, 当然也不可能一直保持匀速移动。就像我们 打开抽屉的过程那样,刚开始拉的那一下动作很快, 但是当抽屉被拉出来之后我们会不自觉的放慢动作。 或是掉落在地板上的物体,一开始下降的速度很快, 接着就会在地板上来回反弹直到停止。

\quad 缓动动画,指带有一定缓冲的动画,物体在一定时间内渐进加速或者减速,从而使动画更加的真实和自然。我们先感受一下使用缓动动画实现小球平移功能的示例。

在这里插入图片描述

\quad 在这个示例中,easeIn的小球刚开始启动很缓慢,然后逐渐加速,最终与其他小球同时到达终点;而 linear 行的小球则始终保持匀速移动。easeOut小球刚开始启动很快,然后逐渐减速,也是同时到达终点。

\quad 上述小球运动的缓动动画包括以下几个要点:

  1. 确定起点位置和终点位置,由于小球做的是水平运动,因此小球在运动前的X坐标均为50,结束时的坐标是800,Y坐标保持不变;
  2. 确定运动的时间或次数;在该示例中,小球在两秒内移动了10次到达了终点;
  3. 通过缓动函数计算每一次移动的距离;
  4. 绘制帧图形;

\quad 下面代码为一个水平运动的小球,源码如下:

<script type="module">import { Graph, Circle, debug, Animation, Easing } from "../../../src/index.js";// 初始化graph对象let graph = new Graph({"target": "graphWrapper"});// 增加数据层let layer = graph.addLayer({ "name": "数据层" });let ball = layer.getSource().add(new Circle({"x": 50,"y": 100,"radius": 20,"style": { "color": "none", "fillStyle": 1, "fillColor": "#FF0000" }}))// 动画相关变量let minX = 50, maxX = 800;let totalTimes = 10;let times = 0;let rafId = -1;// 绘制帧图形function frame() {// 计算小球移动的距离let dx = (maxX - minX) * Easing.easeIn(times / totalTimes);ball.moveTo(minX + dx, 100);// 图形渲染graph.render();// 动画停止条件if (times < totalTimes) {times++;} else {times = 0;Animation.stop(rafId);}}$("#btnStart").on("click", function () {times = 0;rafId = Animation.start(frame, 0, 5);});$("#btnStop").on("click", function () {Animation.stop(rafId);})
</script>

\quad anyGraph 将缓动函数封装到了工具类 Easing 中,Easing.easeIn()为缓入动画函数,该函数开始启动很缓慢然后逐渐加速,将该函数换成其他缓动函数就可以实现不同的动画效果。

\quad 缓动函数的实现比较多,有关这部分的内容请参见:缓动函数速查表。下面介绍几个最常见的缓动效果。

缓慢加速 easeIn

在这里插入图片描述

/*** 启动缓慢,后期加速快(加速曲线)* @param {number} t 输入参数(0至1之间). (0.1,   0.2,   0.3,   0.4,   0.5,   0.6,   0.7,   0.8,   0.9,   1.0)* @return {number}  返回参数(0至1之间). (0.001, 0.008, 0.026, 0.064, 0.125, 0.215, 0.343, 0.512, 0.729, 1.0)*/
function easeIn(t) {return Math.pow(t, 3);
}
缓慢减速 easeOut

在这里插入图片描述

/*** 启动加速快,结束缓慢(减速曲线)* @param {number} t 输入参数(0至1之间). (0.1,   0.2,   0.3,   0.4,   0.5,   0.6,   0.7,   0.8,   0.9,   1.0)* @return {number}  返回参数(0至1之间). (0.270, 0.488, 0.657, 0.784, 0.875, 0.936, 0.973, 0.992, 0.999, 1.0)*/
function easeOut(t) {return 1 - easeIn(1 - t);
}
匀速 linear

在这里插入图片描述

/*** 随着时间的推移保持恒定的速度(匀速)* @param {number} t 输入参数(0至1之间). (0.1,   0.2,   0.3,   0.4,   0.5,   0.6,   0.7,   0.8,   0.9,   1.0)* @return {number}  返回参数(0至1之间). (0.1,   0.2,   0.3,   0.4,   0.5,   0.6,   0.7,   0.8,   0.9,   1.0)*/
function linear(t) {return t;
}
先缓慢加速后缓慢减速 inAndOut

在这里插入图片描述

/*** 先缓慢加速后缓慢减速(加速减速曲线)* @param {number} t 输入参数(0至1之间). (0.1,   0.2,   0.3,   0.4,   0.5,   0.6,   0.7,   0.8,   0.9,   1.0)* @return {number}  返回参数(0至1之间). (0.028, 0.104, 0.215, 0.352, 0.5,   0.648, 0.784, 0.896, 0.972, 1.0)*/
function inAndOut(t) {return 3 * t * t - 2 * t * t * t;
}
来回运动 upAndDown

在这里插入图片描述

/*** 来回运动* @param {number} t 输入参数(0至1之间). (0.1,   0.2,   0.3,   0.4,   0.5,   0.6,   0.7,   0.8,   0.9,   1.0)* @return {number}  返回参数(0至1之间). (0.104, 0.352, 0.648, 0.896, 1.0,   0.896, 0.648, 0.352, 0.104, 0.0)*/
function upAndDown(t) {if (t < 0.5) {return inAndOut(2 * t);} else {return 1 - inAndOut(2 * (t - 0.5));}
}

5. 视图动画

\quad 在本章第三节中讲述了通过访问API控制视点,Graph类还提供了两个api用于进行视点控制,这两个方法在执行的时候应用了缓动的动画效果,使得在进行图形缩放和平移时可以产生更好的视觉效果。

名称说明
animailMove(center, resolution, duration)具有动画效果的图形移动
animailZoom(scale, anchor, duration)具有动画效果的图形缩放

5.1 平移动画

\quad animailMove() 方法中,通过使用 Animation 类和 Easing.easeOut() 减速缓动功能,实现了动画效果的图形移动,其源码如下:

/*** 具有动画效果的图形移动* @param {Coord} center 中心点坐标* @param {Number} resolution 新的分辨率,如果为空则不改变分辨率 * @param {int} duration 延时时间*/
animailMove(center, resolution, duration = 500) {let start = Date.now();let that = this;let originalCenter = this.getView().getCenter();let originalRes = this.getView().getResolution();// 开始动画Animation.start(function () {let drawTime = Date.now() - 1;let delta = Easing.easeOut((drawTime - start) / duration);let centerX = originalCenter[0] + delta * (center[0] - originalCenter[0]);let centerY = originalCenter[1] + delta * (center[1] - originalCenter[1]);that.getView().setCenter([centerX, centerY]);if (resolution != null && resolution > 0) {let res = originalRes + delta * (resolution - originalRes);that.getView().setResolution(res);}that.renderSync();}, duration);
}

\quad 在这个方法中,我们先记录当前的中心点坐标和分辨率,根据缓动方法计算当前中心点和目标点坐标之间的线性差值,计算当前分辨率和目标分辨率之间的线性差值,逐帧进行图形重绘,从而实现移动的动画效果。缺省动画时间为500毫秒,如果按照每秒60帧计算,这个过程共绘制了30次图形。

\quad 其调用示例如下:

let center = [280, 200];
let resolution = 0.25;
graph.animailMove(center, resolution, 600);

\quad 运行效果如下:

在这里插入图片描述

5.2 缩放动画

\quad animailZoom() 方法中,通过使用 Animation 类和 Easing.easeOut() 减速缓动功能,实现了动画效果的图形缩放,其源码如下:

/*** 具有动画效果的图形缩放* @param {Number} scale 缩放倍率 * @param {Coord} anchor 锚点坐标 */
animailZoom(scale = 1.5, anchor, duration = 500) {let originalRes = this.getView().getResolution();let targetRes = this.getView().getResolution() * scale;let start = Date.now();let that = this;// 缺省锚点为中心点if(anchor == null) {anchor = Extent.getCenter(this.getExtent());}// 开始动画Animation.start(function () {let drawTime = Date.now() - 1;let delta = Easing.easeOut((drawTime - start) / duration);let res = originalRes + delta * (targetRes - originalRes);let center = that.getView().calculateCenterZoom(res, anchor);that.getView().setCenter(center);that.getView().setResolution(res);that.renderSync();}, duration);
}

\quad 在这个方法中,我们先获取当前分辨率和计算目标分辨率,根据缓动方法计算当前分辨率和目标分辨率之间的线性差值,逐帧进行图形重绘,从而实现图形缩放的动画效果。缺省动画时间为500毫秒,如果按照每秒60帧计算,这个过程共绘制了30次图形。

\quad 其调用示例如下:

let scale = 1.5;  // 放大
// let scale = 0.67;  // 缩小
graph.animailZoom(scale);

\quad 运行效果如下:

在这里插入图片描述


\quad “图形系统实战开发-进阶篇 第七章 图形交互操作:视点控制与动画” 的内容讲解到这里就结束了,如果觉得对你有帮助有收获,可以关注我们的官方账号,持续关注更多精彩内容。

相关资料

▶ 系列教程及代码资料:https://GraphAnyWhere.com
▶ 图形系统开发实战课程:进阶篇(上)——前言
▶ 图形系统开发实战课程:进阶篇(上)——1.基础知识
▶ 图形系统开发实战课程:进阶篇(上)——2.图形管理类(Graph)
▶ 图形系统开发实战课程:进阶篇(上)——3.图层类(Layer)
▶ 图形系统开发实战课程:进阶篇(上)——4.图形基本形状
▶ 图形系统开发实战课程:进阶篇(上)——5.图形交互操作:平移和缩放
▶ 图形系统开发实战课程:进阶篇(上)——6.图形交互操作:拾取


作者信息

作者 : 图形开发学院
CSDN: https://blog.csdn.net/2301_81340430?type=blog
官网:https://graphanywhere.com

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

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

相关文章

【精品】OnlyOffice 8.0 版本深度测评

引言 官网链接&#xff1a; ONLYOFFICE 官方网址 OnlyOffice 是一套全面的开源办公协作软件&#xff0c;旨在为用户提供强大、便捷和安全的文档处理和协作环境。最新发布的 OnlyOffice 8.0 版本带来了一系列引人瞩目的新特性和功能改进&#xff0c;进一步提升了其在功能丰富性…

BIO实战、NIO编程与直接内存、零拷贝深入辨析

BIO实战、NIO编程与直接内存、零拷贝深入辨析 长连接、短连接 长连接 socket连接后不管是否使用都会保持连接状态多用于操作频繁&#xff0c;点对点的通讯&#xff0c;避免频繁socket创建造成资源浪费&#xff0c;比如TCP 短连接 socket连接后发送完数据后就断开早期的http服…

prometheus+grafana监控nginx的简单实现

1.编译安装NGINX 加入编译安装nginx-module-vts模块,目的是为了获取更多的监控数据(虚拟主机&#xff0c;upstream等) nginx下载 http://nginx.org/download/nginx-1.20.2.tar.gz nginx-module-vts下载 https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v0.2…

自动驾驶---行业发展及就业环境杂谈

进入21世纪以来&#xff0c;自动驾驶行业有着飞速的发展&#xff0c;自动驾驶技术&#xff08;L2---L3&#xff09;也逐渐落地量产到寻常百姓家。虽然最早期量产FSD的特斯拉有着深厚的技术积累&#xff0c;但是进入2010年以后&#xff0c;国内的公司也逐渐发展起来自己的自动驾…

WebSocket实现聊天

基于webSocket通信的库主要有 socket.io&#xff0c;SockJS&#xff0c;这次用的是 SockJS。 这里我们使用sockjs-client、stomjs这两个模块&#xff0c;要实现webSocket通信&#xff0c;需要后台配合&#xff0c;也使用相应的模块。 WebSocket 1、http&#xff1a;http超文…

2024-2-26-进程线程通信作业

课上代码&#xff1a; sem.h #ifndef _SEM_H_ #define _SEM_H_int open_sem(int semcount); int P(int semid,int semno); int V(int semid,int semno); int del_sem(int semid);#endif sem.c #include <myhead.h> union semun {int val;struct semid_ds *buf;unsign…

【web APIs】1、(学习笔记)有案例!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、概念二、使用步骤1.获取DOM对象2.操作元素内容3.属性修改3.1.常用属性修改3.2.控制样式属性3.3.操作类名(className) 操作CSS3.4.操作表单元素属性3.5.自定…

【深入理解设计模式】建造者设计模式

建造者设计模式 建造者设计模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;旨在通过将复杂对象的构建过程拆分成多个简单的步骤&#xff0c;使得相同的构建过程可以创建不同的表示。该模式允许您使用相同的构建过程来创建不同的对象表示。 概述…

Leetcode刷题笔记题解(C++):6. Z 字形变换

思路&#xff1a;遍历时候需要更新步进长度 到达0行的时候步进长度为1&#xff1b;到达最后一行numRows-1行的时候步进长度为-1&#xff1b;代码如下所示&#xff1a; class Solution { public:string convert(string s, int numRows) {//如果字符串长度为1或者所给行数为1 …

[c++] char * 和 std::string

1 char * 和 std::string 的区别 char * 字符串是常量字符串&#xff0c;不能修改&#xff1b;std::string 指向的字符串可以修改 实例代码如下图所示&#xff0c;s1 和 s2 均是常量字符串&#xff0c;字符串常量保存在只读数据区&#xff0c;是只读的&#xff0c;不能写&…

Unity类银河恶魔城学习记录7-9 P75 Saw spin sword源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Sword_Skill_Controller.cs using System.Collections; using System.Col…

QT信号槽实现分析

1.宏定义 qt中引入了MOC来反射&#xff0c;编译阶段变成 MOC–>预处理–>编译–>汇编–>链接 1-1、Q_OBJECT 这个宏定义了一系列代码&#xff0c;包括元对象和处理的函数 #define Q_OBJECT \public: \QT_WARNING_PUSH \Q_OBJECT_NO_OVERRIDE_WARNING \static c…