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

本文主要是介绍图形系统开发实战课程:进阶篇(上)——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

这篇关于图形系统开发实战课程:进阶篇(上)——7.图形交互操作: 视点控制与动画的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/750206

相关文章

Python与DeepSeek的深度融合实战

《Python与DeepSeek的深度融合实战》Python作为最受欢迎的编程语言之一,以其简洁易读的语法、丰富的库和广泛的应用场景,成为了无数开发者的首选,而DeepSeek,作为人工智能领域的新星... 目录一、python与DeepSeek的结合优势二、模型训练1. 数据准备2. 模型架构与参数设置3

Java实战之利用POI生成Excel图表

《Java实战之利用POI生成Excel图表》ApachePOI是Java生态中处理Office文档的核心工具,这篇文章主要为大家详细介绍了如何在Excel中创建折线图,柱状图,饼图等常见图表,需要的... 目录一、环境配置与依赖管理二、数据源准备与工作表构建三、图表生成核心步骤1. 折线图(Line Ch

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

使用Go语言开发一个命令行文件管理工具

《使用Go语言开发一个命令行文件管理工具》这篇文章主要为大家详细介绍了如何使用Go语言开发一款命令行文件管理工具,支持批量重命名,删除,创建,移动文件,需要的小伙伴可以了解下... 目录一、工具功能一览二、核心代码解析1. 主程序结构2. 批量重命名3. 批量删除4. 创建文件/目录5. 批量移动三、如何安

Java使用Tesseract-OCR实战教程

《Java使用Tesseract-OCR实战教程》本文介绍了如何在Java中使用Tesseract-OCR进行文本提取,包括Tesseract-OCR的安装、中文训练库的配置、依赖库的引入以及具体的代... 目录Java使用Tesseract-OCRTesseract-OCR安装配置中文训练库引入依赖代码实

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应