在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示

在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示

  • 参考文章
  • 源码下载地址
  • 一、SDL2的创建、初始化、退出
  • 二、系统基本Tick、彩屏刷新、按键事件
  • 三、彩屏获取与设置颜色
  • 四、彩屏填充颜色及清屏
  • 五、彩屏显示中文和英文字符串
  • 六、彩屏显示数字
  • 七、彩屏初始化
  • 八、主函数测试
  • 九、测试效果

参考文章

  • 在CodeBlocks下搭建SDL2开发工程
  • 在CodeBlocks搭建SDL2工程OLED液晶模拟器虚拟OLED单色液晶(128x64)



源码下载地址

在CodeBlocks搭建SDL2工程构建TFT彩屏模拟器虚拟TFT彩屏幕显示


一、SDL2的创建、初始化、退出


typedef struct
{SDL_Window   * MainWindow;  /* 窗口 */SDL_Renderer * MainRender;  /* 渲染器 */SDL_Texture  * MainTexture; /* 纹理 */u8             ExitWindow;  /* 退出窗口 */
}AppGlobal_TypeDef, * AppGlobal_TypeDef_t;static AppGlobal_TypeDef AppSystem = {0};
AppGlobal_TypeDef * pAppSystem = &AppSystem;/* 初始化SDL */
static u8 ubInit_SDL2(void)
{/* 初始化SDL */if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0){SDL_Log("SDL Init Fail......%s\r\n", SDL_GetError());return 1;}/* 创建窗口 */AppSystem.MainWindow = SDL_CreateWindow("Virtual TFT SDL2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_PHY_WIDTH, WINDOW_PHY_HEIGHT, SDL_WINDOW_SHOWN);if (AppSystem.MainWindow == NULL){SDL_Log("SDL Create Window Fail......%s\r\n", SDL_GetError());return 2;}/* 创建渲染器 */AppSystem.MainRender = SDL_CreateRenderer(AppSystem.MainWindow, -1, SDL_RENDERER_ACCELERATED);if (AppSystem.MainRender == NULL){SDL_Log("SDL Create Renderer Fail......%s", SDL_GetError());return 3;}/* 创建纹理 */AppSystem.MainTexture = SDL_CreateTexture(AppSystem.MainRender, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, TFT_LCD_PHY_XWIDTH, TFT_LCD_PHY_YHEIGHT);if (AppSystem.MainTexture == NULL){SDL_Log("SDL Create Texture Fail......%s", SDL_GetError());return 4;}/* 设置纹理模式 */SDL_SetTextureBlendMode(AppSystem.MainTexture, SDL_BLENDMODE_BLEND);memset(TFT_LCD_DIS_MEMORY, 0x99, TFT_LCD_PHY_XWIDTH * TFT_LCD_PHY_YHEIGHT * sizeof(u32));SDL_UpdateTexture(AppSystem.MainTexture, NULL, TFT_LCD_DIS_MEMORY, TFT_LCD_PHY_XWIDTH * sizeof(u32));SDL_RenderClear(AppSystem.MainRender);SDL_RenderCopy(AppSystem.MainRender, AppSystem.MainTexture, NULL, NULL);SDL_RenderPresent(AppSystem.MainRender);return 0;
}/* 退出SDL */
static void vQuit_SDL2(void)
{SDL_Log("Complier Date: %s  %s %d\r\n", __DATE__, __TIME__, ulSuperTimer_GetTick());/* 销毁纹理 */if (AppSystem.MainTexture != NULL) SDL_DestroyTexture(AppSystem.MainTexture);/* 销毁渲染器 */if (AppSystem.MainRender != NULL)  SDL_DestroyRenderer(AppSystem.MainRender);/* 销毁窗口 */if (AppSystem.MainWindow != NULL) SDL_DestroyWindow(AppSystem.MainWindow);/* 退出SDL */SDL_Quit();
}



二、系统基本Tick、彩屏刷新、按键事件


/* 系统基本Tick */
static void vSystem_BasicTick(void)
{static Uint64 oldTick = 0;Uint64 curTick = SDL_GetTicks64();if (oldTick == curTick) return;vSuperTimer_IncTick((u16)(curTick - oldTick));oldTick = curTick;
}/* 屏幕刷新+按键事件处理 */
static void vRefresh_KeyEvent_Handler(void)
{static Uint64 oldTick = 0;Uint64 curTick  = SDL_GetTicks64();SDL_Event event = {0};if ((curTick - oldTick) >= 20){SDL_UpdateTexture(AppSystem.MainTexture, NULL, TFT_LCD_DIS_MEMORY, TFT_LCD_PHY_XWIDTH * sizeof(u32));SDL_RenderClear(AppSystem.MainRender);SDL_RenderCopy(AppSystem.MainRender, AppSystem.MainTexture, NULL, NULL);SDL_RenderPresent(AppSystem.MainRender);oldTick = curTick;}while (SDL_PollEvent(&event)){switch (event.type){case SDL_QUIT: AppSystem.ExitWindow = EXIT_WINDOW_TYPE_QUIT; break;case SDL_KEYDOWN:{switch (event.key.keysym.sym){case SDLK_UP:    SDL_Log("SDLK_UP......\r\n");    break;case SDLK_DOWN:  SDL_Log("SDLK_DOWN......\r\n");  break;case SDLK_LEFT:  SDL_Log("SDLK_LEFT......\r\n");  break;case SDLK_RIGHT: SDL_Log("SDLK_RIGHT......\r\n"); break;default: break;}}break;default: break;}}
}



三、彩屏获取与设置颜色


/* 设置颜色 */
void vTFT_LCD_SetColor(u32 x, u32 y, ColorType color)
{/* 越界 */if (x > (AppDevTFT.xWidth  - 1)) return;if (y > (AppDevTFT.yHeight - 1)) return;AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x] = 0xFF000000 | DEV_RGB(color);
}/* 获取颜色 */
ColorType xTFT_LCD_GetColor(u32 x, u32 y)
{/* 越界 */if (x > (AppDevTFT.xWidth  - 1)) return 0;if (y > (AppDevTFT.yHeight - 1)) return 0;return RGB_DEV(AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x]);
}



四、彩屏填充颜色及清屏


/* 填充矩形(单色) */
void vTFT_LCD_FillRect_SinColor(u32 x1, u32 y1, u32 x2, u32 y2, ColorType color)
{u32 x = 0, y = 0;/* 越界 */if (x1 > (AppDevTFT.xWidth  - 1)) return;if (y1 > (AppDevTFT.yHeight - 1)) return;/* 最大范围 */if (x2 > (AppDevTFT.xWidth  - 1)) x2 = (AppDevTFT.xWidth - 1);if (y2 > (AppDevTFT.yHeight - 1)) y2 = (AppDevTFT.yHeight - 1);/* 填充颜色 */for (x = x1; x <= x2; x++){for (y = y1; y <= y2; ++y){AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x] = 0xFF000000 | DEV_RGB(color);}}
}/* 填充矩形(多色) */
void vTFT_LCD_FillRect_MultColor(u32 x1, u32 y1, u32 x2, u32 y2, ColorType * pColor)
{u32 x = 0, y = 0, ex = 0, ey = 0;/* 越界 */if (x1 > (AppDevTFT.xWidth  - 1)) return;if (y1 > (AppDevTFT.yHeight - 1)) return;/* 最大范围 */ex = (x2 > (AppDevTFT.xWidth  - 1)) ? (AppDevTFT.xWidth  - 1) : x2;ey = (y2 > (AppDevTFT.yHeight - 1)) ? (AppDevTFT.yHeight - 1) : y2;for (y = y1; y <= ey; y++){for (x = x1; x <= ex; ++x){AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x] = 0xFF000000 | DEV_RGB(*pColor);}pColor += (x2 - ex);}
}/* 清屏幕 */
void vTFT_LCD_ClearScreen(ColorType color)
{u32 x = 0, y = 0;for (x = 0; x <= (AppDevTFT.xWidth - 1); x++){for (y = 0; y <= (AppDevTFT.yHeight - 1); ++y){AppDevTFT.pDisMem[AppDevTFT.xWidth * y + x] = 0xFF000000 | DEV_RGB(color);}}
}



五、彩屏显示中文和英文字符串


/* 获取字符数据源地址 */
static void vGet_CharSrc(u8 chr, u8 charSize, u8 ** pSrc)
{switch (charSize){case ASCII_FONT_TYPE_1206 : *pSrc = (u8 *)(&ASCII_FONT_1206[chr - ' ']); break;case ASCII_FONT_TYPE_1608 : *pSrc = (u8 *)(&ASCII_FONT_1608[chr - ' ']); break;case ASCII_FONT_TYPE_2412 : *pSrc = (u8 *)(&ASCII_FONT_2412[chr - ' ']); break;default: *pSrc = NULL; break;}
}/* 显示字符 */
static void vTFT_LCD_DisplayChar(u32 x, u32 y, u8 chr, u8 charSize, ColorType backColor, ColorType foreColor)
{ColorType color = foreColor;u8 charByte = 0, k = 0, i = 0;u8 dat = 0, * pSrcDat = NULL;u32 y0 = y;//获取字符数据源地址vGet_CharSrc(chr, charSize, &pSrcDat);if (pSrcDat == NULL) return;// 字符点阵占用字节数charByte = ((charSize >> 3) + ((charSize & 0x07) ? 1 : 0)) * (charSize >> 1);// 遍历字符点阵数据for(k = 0; k < charByte; ++k){dat = pSrcDat[k];for(i = 0; i < 8; ++i){// 显示有效范围if ((x < AppDevTFT.xWidth) && (y < AppDevTFT.yHeight)){//低位在前if ((dat >> i) & 0x01) color = foreColor;else                   color = backColor;vTFT_LCD_SetColor(x, y, color);}y++;// 纵坐标自加if (XABS2(y , y0) >= charSize)//纵坐标偏移量等于字符点阵高度{y = y0;x++;break;}}}
}/* 显示字符串 */
void vTFT_LCD_DisplayString(u32 x, u32 y, u8 * pStr, u8 strSize, ColorType backColor, ColorType foreColor)
{//显示ASCII常规字符while ((*pStr >= ' ') && (*pStr <= '~')){/* 剩余的横纵小于字体宽度 换行显示 */if ((x + (strSize >> 1)) >= AppDevTFT.xWidth){y += strSize;x  = 0;}/* 剩余纵轴小于字体高度 */// if ((y + strSize) >= AppDevTFT.yHeight)if (y >= AppDevTFT.yHeight){return;}vTFT_LCD_DisplayChar(x, y, *pStr, strSize, backColor, foreColor);x += (strSize >> 1);pStr++;}
}/* 显示中文字符 */
static void vTFT_LCD_Display_ChineseChar(u32 x, u32 y, u32 xWidth, u32 yHeight, const u8 * pData, ColorType backColor, ColorType foreColor)
{ColorType color = foreColor;u16 k = 0, j = 0, n = 0, i = 0;u32 y0 = y, yMax = 0;u8 dat = 0;yMax = (yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0); //高度y0   = y; //原始纵坐标for(k = 0; k < xWidth; k++){for(j = 0; j < yMax; j++){dat = pData[n++];for(i = 0; i < 8; i++){if ((y < AppDevTFT.yHeight) && (x < AppDevTFT.xWidth)){//低位在前if ((dat >> i) & 0x01) color = foreColor;else                   color = backColor;vTFT_LCD_SetColor(x, y, color);}y++;//纵坐标处理if (XABS2(y , y0) >= yHeight){y = y0;x++;//横坐标处理break;}}}}
}/* 显示中文字符串 */
void vTFT_LCD_Display_ChineseString(u32 x, u32 y, u32 xWidth, u32 yHeight, u8 * pData, u16 num, ColorType backColor, ColorType foreColor)
{u16 i = 0;u8 charByte = 0;u8 * pMem = pData;/* 异常 */if ((!num) || (pData == NULL)) return;// 字符点阵占用字节数charByte = ((yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0)) * xWidth;for (i = 0; i < num; ++i){/* 剩余的横纵小于字体宽度 换行显示 */if ((x + xWidth) > AppDevTFT.xWidth){y += yHeight;x  = 0;}/* 剩余纵轴小于字体高度 */// if ((y + yHeight) >= AppDevTFT.yHeight)if (y >= AppDevTFT.yHeight){return;}pMem = pData + (charByte * i);vTFT_LCD_Display_ChineseChar(x, y, xWidth, yHeight, pMem, backColor, foreColor);x += xWidth;}
}



六、彩屏显示数字


static u8 ubGet_EveryBit_Digit(u8 * pDat, u32 num)
{u8 i = 0;while (1){pDat[i++] = num % 10;num = num / 10;if (!num){break;}}u8 temp = 0;for (num = 0; num < (i >> 1); ++num){temp = pDat[num];pDat[num] = pDat[i - num - 1];pDat[i - num - 1] = temp;}return i;
}/* 显示数字 */
void vTFT_LCD_DisplayNumber(u32 x, u32 y, u32 num, u8 charSize, ColorType backColor, ColorType foreColor)
{u8 mem[20] = {0};u8 chr = 0, i = 0, len = ubGet_EveryBit_Digit(mem, num);for (i = 0; i < len; ++i){/* 剩余的横纵小于字体宽度 换行显示 */if ((x + (charSize >> 1)) >= AppDevTFT.xWidth){y += charSize;x  = 0;}/* 剩余纵轴小于字体高度 */// if ((y + charSize) >= AppDevTFT.yHeight)if (y >= AppDevTFT.yHeight){return;}chr = mem[i] + 0x30;vTFT_LCD_DisplayChar(x, y, chr, charSize, backColor, foreColor);x += (charSize >> 1);}
}



七、彩屏初始化


/* 初始化TFT */
void vTFT_Init(void)
{AppDevTFT.xWidth  = TFT_LCD_PHY_XWIDTH;AppDevTFT.yHeight = TFT_LCD_PHY_YHEIGHT;AppDevTFT.pDisMem = TFT_LCD_DIS_MEMORY;AppDevTFT.BackColor = 0xDCDCDC;AppDevTFT.ForeColor = 0xFFFFFF;vTFT_LCD_ClearScreen(AppDevTFT.BackColor);vTFT_LCD_DisplayString(10,  10, (const u8 *)"Compiler: ", ASCII_FONT_TYPE_1608, 0, 0x00FF00);vTFT_LCD_DisplayString(90,  10, (const u8 *)__DATE__,     ASCII_FONT_TYPE_1608, 0, 0x00FF00);vTFT_LCD_DisplayString(178, 10, (const u8 *)"  ",         ASCII_FONT_TYPE_1608, 0, 0x00FF00);vTFT_LCD_DisplayString(194, 10, (const u8 *)__TIME__,     ASCII_FONT_TYPE_1608, 0, 0x00FF00);vTFT_LCD_DisplayString(10, 50,  (const u8 *)"xDemo TFT1...123ABC~!@#$%^&*()-=", ASCII_FONT_TYPE_1206, 0, 0xFFFF00);vTFT_LCD_DisplayString(10, 70,  (const u8 *)"xDemo TFT2...123ABC", ASCII_FONT_TYPE_1608, 0xFFFFFF, 0x0000FF);vTFT_LCD_DisplayString(10, 100, (const u8 *)"xDemo TFT3...123ABC", ASCII_FONT_TYPE_2412, 0, 0xF59A23);vTFT_LCD_Display_ChineseString(10, 140, 18, 18, (u8 *)&ChineseDemo[1], 9, 0, 0xFF0000);vTFT_LCD_DisplayNumber(10, 200, 985, ASCII_FONT_TYPE_2412, 0xDCDCDC, 0xFF0000);
}



八、主函数测试


int main( int argc, char * argv[] )
{if (ubInit_SDL2()){SDL_Log("Init SDL Fail......%s\r\n", SDL_GetError());vQuit_SDL2();return -1;}vTFT_Init();xSuperTimer_Init();AppSystem.ExitWindow = EXIT_WINDOW_TYPE_RUN;ubSuperTimer_Start(xDemo, 1000);while (AppSystem.ExitWindow){vRefresh_KeyEvent_Handler();vSystem_BasicTick();vSuperTimer_RunHandler();}vQuit_SDL2();return 0;
}



九、测试效果

在这里插入图片描述

在这里插入图片描述

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

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

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

相关文章

ESP8266+STM32+阿里云保姆级教程(AT指令+MQTT)

前言&#xff1a;在开发过程中&#xff0c;几乎踩便了所有大坑小坑总结出的文章&#xff0c;我是把坑踩满了&#xff0c;帮助更过小白快速上手&#xff0c;如有错误之处&#xff0c;还麻烦各位大佬帮忙指正、 目录 一、ESP-01s介绍 1、ESP-01s管脚功能&#xff1a; 模组启动模…

美的空气净化器好用吗?拾梧、美的、戴森空气净化器除烟哪个好?

说到二手烟&#xff0c;这可真是个让人头疼的问题&#xff01;它里面含有超过7000种化学物质&#xff0c;形式多样&#xff0c;处理起来比甲醛这些传统污染物难多了。在市场上那么多空气净化器里&#xff0c;要挑一个能真正对付二手烟的&#xff0c;简直就像大海捞针一样难。不…

【机器学习】穷理至极,观微知著:微积分的哲思之旅与算法之道

文章目录 微积分基础&#xff1a;理解变化与累积的数学前言一、多重积分的高级应用1.1 高维概率分布的期望值计算1.1.1 多维期望值的定义1.1.2 Python代码实现1.1.3 运行结果1.1.4 结果解读 1.2 特征空间的体积计算1.2.1 单位球体的体积计算1.2.2 Python代码实现1.2.3 运行结果…

Ae:合成设置 - 3D 渲染器

Ae菜单&#xff1a;合成/合成设置 Composition/Composition Settings 快捷键&#xff1a;Ctrl K After Effects “合成设置”对话框中的3D 渲染器 3D Renderer选项卡用于选择和配置合成的 3D 渲染器类型&#xff0c;所选渲染器决定了合成中的 3D 图层可以使用的功能&#xff0…

Zookeeper是如何解决脑裂问题的?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper是如何解决脑裂问题的?】面试题。希望对大家有帮助&#xff1b; Zookeeper是如何解决脑裂问题的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper 通过一系列的机制来防止和解决脑裂&#xff08;sp…

【python因果库实战15】因果生存分析4

这里写目录标题 加权标准化生存分析总结个体层面的生存曲线 加权标准化生存分析 我们还可以将加权与标准化结合起来&#xff0c;使用 WeightedStandardizedSurvival 模块。在这里&#xff0c;我们将逆倾向得分加权模型&#xff08;根据基线协变量重新加权人群&#xff09;与加…

windows中硬件加速gpu计划开启cpu的使用率居高不下

1.加速gpu计划开启在任务管理器的gpu选项中看不到cuda选项&#xff0c;这给我们进行深度学习训练和推理带来很大影响。 2.开启硬件加速CPU的占用率明显增高&#xff0c;特别用GPU进行实时视频流解码时就不会分配给GPU解码&#xff0c;造成cpu占用居高不下。不利于深度学习训练…

OpenGL入门最后一章观察矩阵(照相机)

前面的一篇文章笔者向大家介绍了模型变化矩阵&#xff0c;投影矩阵。现在只剩下最后一个观察矩阵没有和大家讲了。此片文章就为大家介绍OpenGL入门篇的最后一个内容。 观察矩阵 前面的篇章当中&#xff0c;我们看到了即使没有观察矩阵&#xff0c;我们也能对绘制出来的模型有一…

java.lang.Error: FFmpegKit failed to start on brand:

如果你使用FFmpegKit的时候遇到了这个问题&#xff1a; java.lang.Error: FFmpegKit failed to start on brand: Xiaomi, model: MI 8, device: dipper, api level: 29, abis: arm64-v8a armeabi-v7a armeabi, 32bit abis: armeabi-v7a armeabi, 64bit abis: arm64-v8a.at c…

KAGGLE竞赛实战2-捷信金融违约预测竞赛-part1-数据探索及baseline建立

竞赛链接&#xff1a;https://www.kaggle.com/competitions/home-credit-default-risk/ 认识数据集&#xff1a;application的两张表是申请人信息 通过id关联bureau&#xff1a;过去的借款、previous_application两张表 而bureau_balance则代表对应的还款信息 表之间的关系…

【软考网工笔记】计算机基础理论与安全——网络安全

病毒 Melissa 宏病毒 1. 是一种快速传播的能够感染那些使用MS Word 97 和MS Office 2000 的计算机宏病毒。 2. 前面有**Macro** 表示这是宏病毒&#xff1b; 3. 宏病毒可以感染后缀为.xls的文件&#xff1b;Worm 蠕虫病毒 1. 通常是通过网络或者系统漏洞进行传播。 2. 利用信…

Java虚拟机(Java Virtual Machine,JVM)

一、Java 虚拟机 Java 虚拟机&#xff08;Java Virtual Machine, JVM&#xff09;是运行 Java 字节码的虚拟机。它是Java平台的核心组件之一&#xff0c;使得Java程序具有 一次编写&#xff0c;到处运行&#xff08;Write Once, Run Anywhere&#xff09; 的特性。 JVM 有针对…

ChatGPT 主流模型GPT-4/GPT-4o mini的参数规模是多大?

微软论文又把 OpenAI 的机密泄露了&#xff1f;&#xff1f;在论文中明晃晃写着&#xff1a; o1-preview 约 300B&#xff1b;o1-mini 约 100BGPT-4o 约 200B&#xff1b;GPT-4o-mini 约 8BClaude 3.5 Sonnet 2024-10-22 版本约 175B微软自己的 Phi-3-7B&#xff0c;这个不用约…

GESP202406 二级【计数】题解(AC)

》》》点我查看「视频」详解》》》 [GESP202406 二级] 计数 题目描述 小杨认为自己的幸运数是正整数 k k k&#xff08;注&#xff1a;保证 1 ≤ k ≤ 9 1 \le k\le 9 1≤k≤9&#xff09;。小杨想知道&#xff0c;对于从 1 1 1 到 n n n 的所有正整数中&#xff0c; k…

SpringMVC(六)拦截器

目录 1.什么是拦截器 2.拦截器和过滤器有哪些区别 3.拦截器方法 4.单个拦截器的执行流程 5.使用拦截器实现用户登录权限验证&#xff08;实例&#xff09; 1.先在html目录下写一个login.html文件 2.在controller包下写一个LoginController文件 3.加拦截器 1.创建一个conf…

基于Arduino的FPV头部追踪相机系统

构建FPV头部追踪相机&#xff1a;让你置身于遥控车辆之中&#xff01; 在遥控车辆和模型飞行器的世界中&#xff0c;第一人称视角&#xff08;FPV&#xff09;体验一直是爱好者们追求的目标。通过FPV头部追踪相机&#xff0c;你可以像坐在车辆或飞行器内部一样&#xff0c;自由…

jQuery get 方法内操控vue变量(异步ajax请求方法中操控双向绑定的响应式变量)实现异步请求函数内完成变量的双向响应式绑定

// 首先&#xff0c;创建一个Vue实例 new Vue({ el: #app, data: { message: Hello, Vue! }, mounted: function() { var self this; // 使用jQuery发起get请求 $.get(your/api/url, function(data) { // 当请求成功完成后&#xff0c;更新Vue实…

Spring boot接入xxl-job

Spring boot接入xxl-job 导入maven包加入配置增加配置类创建执行器类&#xff08;写job的业务逻辑&#xff09;去控制台中配置job 导入maven包 <dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>…

【超详细】React SSR 服务端渲染实战

前言 这篇文章和大家一起来聊一聊 React SSR&#xff0c;本文更偏向于实战。你可以从中学到&#xff1a; 从 0 到 1 搭建 React SSR 服务端渲染需要注意什么 react 18 的流式渲染如何使用 文章如有误&#xff0c;欢迎指出&#xff0c;大家一起学习交流&#xff5e;。 &…

25年对AI产业的25点预测以及展望思考

| 2025 大宝同学对于AI 产业 25点预测&#xff0c;他自嘲道&#xff1a;“做不做 250 不重要&#xff0c;重要的是不违背自己的良知&#xff0c;以及对自身物种的坚信。”&#x1f600;ps&#xff1a;因大宝的这篇文章基文涉猎太过于广泛&#xff0c;考虑到某些原因&#xff0c…