手把手教你使用Express框架在Node服务端实现图片渲染

news2024/11/15 11:04:40

手把手教你使用Express框架在Node服务端实现图片渲染

  • 1.前言
  • 2.node-canvas库
  • 3.搭建node服务端环境
    • 3.1 初始化项目
    • 3.2 使用内置http模块创建服务
    • 3.3 使用Express创建服务
  • 4.服务端渲染图片
    • 4.1 创建Express路由
    • 4.2 绘制三角形
    • 4.3 静态资源中间件
    • 4.4 写入图片文件
    • 4.5 渲染Echarts图表

1.前言

大家知道前端如何绘制出下面这个三角形吗?

在这里插入图片描述

相信很多人的答案都是canvas,使用canvas确实很容易就能实现上面的效果,代码如下:

<canvas id="canvas" width="400" height="400"></canvas>
<script>
    var canvas = document.getElementById('canvas');// 获取canvas元素
    var ctx = canvas.getContext('2d');// 获取绘图上下文
    //绘制一个三角形
    ctx.moveTo(100, 100);
    ctx.lineTo(200, 200);
    ctx.lineTo(50, 100);
    ctx.lineTo(100, 100);
    ctx.stroke();
</script>

对canvas不了解的可以去看我的这篇文章,那你知道在Node.js服务端中如何使用canvas绘图吗,本文就来聊聊node服务端渲染图片。

2.node-canvas库

node中是没有DOM的,怎么绘图呢?这就得用到node-canvas这个库,来实现在node中进行canvas渲染。

不过,使用node-canvas这个库,不同的系统需要安装对应的依赖环境,如下图所示:
在这里插入图片描述
具体环境配置可以参考node-canvas官网

3.搭建node服务端环境

3.1 初始化项目

创建一个文件夹draw,执行npm init命令,该命令的作用就是初始化一个 package.json 文件,将项目变成一个npm项目:

npm init

接着可以一路回车下去,就会发现 package.json 文件已经创建好了。

  • 安装node-canvas

安装node-canvas库,执行如下命令:

npm install canvas
  • 安装nodemon

nodemon是一个流行的开发服务器,能够检测工作区代码的变化,并自动重启。执行下面命令进行安装 :

npm install nodemon --save-dev

这里将nodemon安装为开发依赖 devDependencies,因为仅仅只有在开发时才需要用到。同时可以配置start命令,package.json文件如下:

{
  "name": "draw",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon server.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^3.0.1"
  },
  "dependencies": {
    "canvas": "^2.11.2"
  }
}

3.2 使用内置http模块创建服务

在文件夹下新建一个server.js文件,代码如下:

//server.js
//1.导入 http 模块
const http = require('http');

const hostname = 'localhost';
const port = 3000;
//2.创建 HTTP 服务器
const server = http.createServer((req, res) => {
  res.end('Hello World');
});
//3.监听端口, 启动服务
server.listen(port, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

运行npm start开启服务器:

npm start

浏览器打开http://localhost:3000/,可以看到如下效果:

在这里插入图片描述

直接用内置的 http 模块搭建服务器有个明显的缺点,就是没有专门的路由机制,即不能根据客户端不同URL及HTTP方法来返回相应内容。

因此,我们可以对上述代码进行改进,使用Express来开发Web服务器。

3.3 使用Express创建服务

Express是一个基于Node.js的快速、极简的流行Web开发框架,封装了很多功能,如路由和中间件等,可以更加方便的进行开发。

安装Express

npm install express

改写上述server.js代码,如下:

//server.js
//1.导入 express
const express = require('express');

const hostname = 'localhost';
const port = 3000;
//2.创建应用对象
const app = express();
//3.创建路由规则
app.get('/', (req, res) => {
  res.send('Hello World');
});
//4.监听端口 启动服务
app.listen(port, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

运行npm start开启服务器,同样可以看到如下效果:

在这里插入图片描述
到这里,环境就基本搭建好了,下面正式开始绘图。

4.服务端渲染图片

4.1 创建Express路由

Express路由的官方定义:确定应用程序如何响应客户端对特定端点的请求,端点是 URI(路径)和HTTP请求方法(GET、POST 等)。

通俗来讲就是服务器根据客户端访问的端点选择相应处理逻辑的机制。一个路由的组成有请求方法,路径和回调函数,如下所示:

app.METHOD(PATH, HANDLER)

因此,我们可以创建一个用于绘图的路由:

app.get('/drawTriangle', (req, res) => {
  //在这里写代码逻辑
});

4.2 绘制三角形

这里我们先来实现一下上面这个三角形的例子。

首先需要通过node-canvas提供的createCanvas方法创建画布,代码如下:

//引入createCanvas创建画布方法
const { createCanvas } = require("canvas");
//创建一个400 * 400的canvas
const canvas = createCanvas(400, 400);

其实node中绘图和前端绘图最主要的区别就在这里,node中需要通过node-canvas来创建canvas元素,接下来的绘图就和前端一致了:

...
//获取渲染上下文
const ctx = canvas.getContext("2d");
//绘制三角形
ctx.moveTo(100, 100);
ctx.lineTo(200, 200);
ctx.lineTo(50, 100);
ctx.lineTo(100, 100);
ctx.stroke();

完成绘图后,接下来就是把绘制结果返回给前端。

4.3 静态资源中间件

Express内置了处理静态资源的中间件函数express.static,可以提供图片、CSS 文件、JS 文件这类静态文件的服务。

  • 什么是中间件?

中间件本质就是一个回调函数,作用就是使用函数封装能够适用多个应用场景、可复用性良好的代码。

通过如下代码就可以设置一个静态文件中间件,指定当前文件夹下的public目录作为静态资源根目录:

app.use(express.static('./public'));

这样我们就可以访问public目录中的所有文件了,如:

http://localhost:3000/images/bg.png
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js

4.4 写入图片文件

接下来我们只需要把绘制好的图片写入到public目录下即可,我们可以通过fs模块来实现。fs模块是Node.js中的内置模块,可以对计算机中的磁盘进行操作,如文件写入、读取、删除等。

文件写入可以使用fs.writeFileSync或fs.writeFile,两者区别:前者是同步写入,js主线程会等待其他线程的执行结果,然后再继续执行主线程的代码,效率较低;后者是异步写入,js主线程不会等待其他线程的执行结果,直接执行后续的主线程代码,效率较好。

这里我们使用fs.writeFile异步写入,其语法格式为:

fs.writeFile(file, data[, options], callback)

参数说明:

  • file 文件名
  • data 待写入的数据
  • options 选项设置(可选)
  • callback 写入回调

具体可以参考node官网。绘制的完整代码如下:

const express = require("express");
//引入创建画布方法
const { createCanvas } = require("canvas");
//引入fs模块
const fs = require('fs');

const hostname = "localhost";
const port = 3000;

const app = express();
//静态资源中间件的设置
app.use(express.static("./public"));

//创建绘图路由
app.get("/drawTriangle", (req, res) => {
  //创建画布
  const canvas = createCanvas(400, 400);
  //获取渲染上下文
  const ctx = canvas.getContext("2d");
  //绘制三角形
  ctx.moveTo(100, 100);
  ctx.lineTo(200, 200);
  ctx.lineTo(50, 100);
  ctx.lineTo(100, 100);
  ctx.stroke();
  //定义写入的目录和文件名
  const imagePath = "./public/images";
  const imageName = "triangle.png";
  //如果不存在images图片目录就创建一个
  if (!fs.existsSync(imagePath)) {
    fs.mkdirSync(imagePath);
  }
  //将绘制结果写入指定文件,这里toBuffer创建一个Buffer表示画布中包含的图像对象,Buffer对象专门用来处理二进制数据
  fs.writeFile(`${imagePath}/${imageName}`, canvas.toBuffer(), function (err) {
    if (err) {
      console.log("写入失败");
    } else {
      console.log("写入成功");
    }
  });
});

app.listen(port, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

当请求http://localhost:3000/drawTriangle时,就会进行三角形的绘制,并写入public静态资源目录:

在这里插入图片描述

然后浏览器就可以访问这个图片,如下所示:
在这里插入图片描述
到这你以为结束了吗?绘图怎么能少得了Echarts呢,下面就来讲讲Echarts的渲染。

4.5 渲染Echarts图表

安装echarts库

npm install echarts

引入echarts库

const echarts = require("echarts");

渲染Echarts图表,代码如下:

//server.js
...
const options = {
  title: {
    text: "第一个 ECharts 实例",
  },
  tooltip: {},
  legend: {
    data: ["销量"],
  },
  xAxis: {
    data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"],
  },
  yAxis: {},
  series: [
    {
      name: "销量",
      type: "bar",
      data: [5, 20, 36, 10, 10, 20],
    },
  ],
};
app.get("/drawChart", (req, res) => {
  const canvas = createCanvas(400, 400);
  const imagePath = "./public/images";
  const imageName = "chart.png";
  //初始化echarts,使用创建的canvas作为初始化容器
  const chart = echarts.init(canvas);
  chart.setOption(options);
  //写入文件,chart.getDom()即获取绘制好的canvas
  fs.writeFile(`${imagePath}/${imageName}`, chart.getDom().toBuffer(), function (err) {
    if (err) {
      console.log("写入失败");
    } else {
      console.log("写入成功");
    }
  });
});
...

当请求http://localhost:3000/drawTriangle时,就会进行图表的渲染:

在这里插入图片描述
浏览器访问:

在这里插入图片描述
好了,以上就是本文的全部内容,如有问题,欢迎指出,如有帮助,点个赞,鼓励一下作者吧。

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

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

相关文章

STM32,我想看单片机上的外设时钟,我怎么看?

一&#xff1a;在工程中加入rcc文件 首先需要加载我们的时钟函数的文件 stm32f10x_rcc.h 和 stm32f10x_rcc.c 文件 二&#xff1a;查看文件 在h头文件 尾部&#xff0c;有我们这个总线的函数 在函数体内&#xff0c;有我们这个宏定义的 外设时钟&#xff0c;我们拿就行了 APB2_…

【C++】C++11新特性之右值引用与移动语义

文章目录 一、左值与左值引用二、右值与右值引用三、 左值引用与右值引用比较四、右值引用使用场景和意义1.左值引用的短板2.移动构造和移动赋值3.STL中右值引用的使用 五、万能引用与完美转发1.万能引用2.完美转发 一、左值与左值引用 在C11之前&#xff0c;我们把数据分为常…

win10专业版驱动开发

我使用的系统版本如何下&#xff1a; 使用的visual studio为VS2019,使用的SDK,WDK如下&#xff1a; 在visual studio单个组件里选择SDK10.0.018362.0 在WDK里面选择版本为&#xff1a; 下载链接如下&#xff1a; 以前的 WDK 版本和其他下载 - Windows drivers | Microsoft Le…

计算机算法分析与设计(16)---Dijkstra算法(含C++代码)

文章目录 一、知识概述1.1 算法描述1.2 例题分析 二、代码编写 一、知识概述 1.1 算法描述 1.2 例题分析 二、代码编写 输入&#xff1a;  第一行&#xff1a;图的顶点数n  第二行&#xff1a;图的边数k  第三行&#xff1a;算法起点begin&#xff0c;算法终点end  接下来…

设计模式-责任链设计模式

核心思想 客户端发出一个请求&#xff0c;链上的对象都有机会来处理这一请求&#xff0c;而客户端不需要知道谁是具体的处理对象让多个对象都有机会处理请求&#xff0c;避免请求的发送者和接收者之间的耦合关系&#xff0c;将这个对象连成一条调用链&#xff0c;并沿着这条链…

Java面试(基础篇)——解构Java常见的基础面试题 结合Java源码分析

fail-safe 和fail-fast机制 Fail-fast&#xff1a;快速失败 Fail-fast &#xff1a; 表示快速失败&#xff0c;在集合遍历过程中&#xff0c;一旦发现容器中的数据被修改了&#xff0c;会立刻抛出ConcurrentModificationException 异常&#xff0c;从而导致遍历失败 package …

经典链表问题:解析链表中的关键挑战

这里写目录标题 公共子节点采用集合或者哈希采用栈拼接两个字符串差和双指针 旋转链表 公共子节点 例如这样一道题&#xff1a;给定两个链表&#xff0c;找出它们的第一个公共节点。 具体的题目描述我们来看看牛客的一道题&#xff1a; 这里我们有四种解决办法&#xff1a; …

Tomcat启动控制台乱码问题

修改Tomcat/conf/logging.properties

[C++] C++入门

☃️个人主页&#xff1a;fighting小泽 &#x1f338;作者简介&#xff1a;目前正在学习C和Linux &#x1f33c;博客专栏&#xff1a;C入门 &#x1f3f5;️欢迎关注&#xff1a;评论&#x1f44a;&#x1f3fb;点赞&#x1f44d;&#x1f3fb;留言&#x1f4aa;&#x1f3fb; …

【Mysql】B+树索引的使用(七)

前言 每个索引都对应一棵 B 树&#xff0c; B 树分为多层&#xff0c;最下边一层是叶子节点&#xff0c;其余的是内节点&#xff08;非叶子节点&#xff09;。所有用户记录都存储在 B 树的叶子节点&#xff0c;所有目录项记录都存储在内节点。 InnoDB 存储引擎会自动为主键&am…

Spring Cloud Alibaba Seata 实现分布式事物

Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案 Seata 官网&#xff1a;https://seata.io/zh-cn/ Spring Cloud Alibaba 官…

信息检索与数据挖掘 | (五)文档评分、词项权重计算及向量空间模型

目录 &#x1f4da;词项频率及权重计算 &#x1f407;词项频率 &#x1f407;逆文档频率 &#x1f407;tf-idf权重计算 &#x1f4da;向量空间模型 &#x1f407;余弦相似度 &#x1f407;查询向量 &#x1f407;向量相似度计算 &#x1f4da;其他tf-idf权值计算方法 …

【OpenGL】五、光照

OpenGL Lighting 文章目录 OpenGL Lighting一、 冯氏光照模型(Phong Lighting Model)环境光&#xff08;Ambient lighting&#xff09;漫反射光照&#xff08;Diffuse lighting&#xff09;漫反射光照&#xff08;Specular Lighting&#xff09; 二、 材质(Materials)光照贴图(…

JUC并发编程笔记2

省流&#xff1a; 自己笔记&#xff0c;划走~~~~ 缓存更新策略

vue3里面vant组件的标签页使用?

一、绑一个v-model事件 二、让activeName的初始为0也就是默认是显示第一个标签页的下标 三、给标签页下面的东西进行一个判断 想让哪个优先显示就把哪个判断作为初始值存入

【试题040】多个逻辑或例题2

1.题目&#xff1a;设int n0;&#xff0c;执行表达式n ||(n-1) ||(n0)||(n1)||(n2)后n的值是 &#xff1f; 2.代码解析&#xff1a; 逻辑或 || 运算符是一个短路运算符&#xff0c;它从左到右依次计算表达式&#xff0c;如果遇到一个为真&#xff08;非零&#xff09;的值&am…

No171.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

第一章概述

一、学习目的与要求 本章对软件测试作了概括性的介绍&#xff0c;目的是使学生对软件测试有个初步的认识。通过本章的学习&#xff0c;应使学生掌握软件测试的基本概念&#xff0c;了解软件测试的发展历程和行业现状&#xff0c;掌握软件测试技术的分类&#xff0c;理解软件测试…

【JAVA-Day49】Java LinkedList集合详解

Java LinkedList集合详解 摘要引言Java LinkedList集合详解一、什么是LinkedList集合1.1 链表数据结构1.2 双向链表1.3 动态大小1.4 插入和删除元素1.5 适用场景 二、LinkedList集合的使用2.1 创建 LinkedList 集合、添加元素、遍历元素2.2 在指定位置插入元素2.3 获取指定位置…