微信小程序 - 龙骨图集拆分

微信小程序 - 龙骨图集拆分

  • 注意
  • 目录结构
  • 演示动画
  • 废话一下
    • 业务逻辑
    • 注意点
    • 龙骨JSON图集结构
  • 源码分享
    • dragonbones-split.js
    • dragonbones-split.json
    • dragonbones-split.wxml
    • dragonbones-split.wxss
    • imgUtil.js
  • 参考资料

注意

只支持了JSON版本

目录结构

在这里插入图片描述

演示动画

Spine播放器1.5.0_PC端

Spine播放器1.5.1_移动端

废话一下

这是 SpinePlayer 2D骨骼动画播放器 - 微信小程序版 工具箱中的一个功能。
功能很简单,80% 的代码都在处理交互逻辑,以及移动端PC端兼容方面的问题。

业务逻辑

  1. 读取JSON文件和PNG图片。
  2. 解析JSON得到所有小图在图集(PNG图片)中的 x,y 坐标和高宽。
  3. 将PNG图集绘制到2d画布,然后使用 canvasToTempFilePath 逐个截取区域,保存为小图。
  4. 最后将所有小图打包为 zip 供用户保存即可。

注意点

  1. 为了保证截取图片的清晰度,画布尺寸需要用图片大小乘以设备像素比
  2. 图片填充完整,再截图。否则会空白。所以会成两步操作比较稳妥。当然也可以自己控制延时自动调用,一气呵成。
  3. 因为 2d 画布不便于直接显示,所以使用一个 image 组件来实现预览。
    3.1. 方法是将 PNG 读取为 base64 赋给 image 组件 <image src="{{textureBase64}}" />
    3.2. 读取 PNGbase64 就这句 fs.readFileSync(‘临时图片路径’, 'base64') 当然用的时候还要拼接一下头,详情看源码吧。

龙骨JSON图集结构

可以看出结构非常简单,直接读 SubTexture 数组,遍历它进行截取就可以了。

{"imagePath": "body_tex.png","width": 1024,"SubTexture": [{"height": 472,"y": 1,"width": 295,"name": "body/a_arm_L","x": 720}略。。。],"name": "body","height": 1024
}

源码分享

dragonbones-split.js

// packageTools/pages/dragonbones-split/dragonbones-split.js
const fileUtil = require('../../../utils/fileUtil.js');
const imgUtil = require('./imgUtil.js');
const pixelRatio = wx.getSystemInfoSync().pixelRatio; // 设备像素比
let canvas, ctx;
let globalData = getApp().globalData;
let dbsplit = globalData.PATH.dbsplit;
Page({/*** 页面的初始数据*/data: {canvasWidth: 300,                     // 画布宽canvasHeight: 150,                    // 画布高texture: {},                          // 龙骨图集PNG图片信息 { path, width, height, orientation, type }textureBase64: '',                    // 龙骨图集PNG图片的 Base64 编码subTextureList:[],                    // 龙骨图集JSON数据。包含拆分出的小图地址 tempFilePathshareZipFile: { name: '', path: ''},  // 最终生成的ZIPjsonValue: '',                        // 文本框内容(PC 端用于获取 JSON)// parseInt('0011', 2) === 3status: 0,                            // 工作状态:0000 初始,0001 有图,0010 有JSON,0100 已拆图,1000 已ZIPisPC: false,},/*** 生命周期函数--监听页面加载*/onLoad(options) {// 获取画布wx.createSelectorQuery().select('#myCanvas') // 在 WXML 中填入的 id.fields({ node: true, size: true }).exec((res) => {canvas = res[0].node;           // Canvas 对象ctx = canvas.getContext('2d');  // 渲染上下文});// 创建工作目录fileUtil.mkdir(dbsplit); this.setData({ isPC: globalData.systemInfo.isPC });// 清理场地fileUtil.clearDirSync(globalData.PATH.dbsplit);},/*** 粘贴龙骨图集 JSON 的文本框发生变化*/onChange(event) {try {if(event.detail.value === undefined){return;}let json = imgUtil.parseJSON(event.detail.value);this.data.shareZipFile = { name: `${json.name}.zip`, path: `${dbsplit}/${json.name}.zip`}; // zip路径打包时用this.setData({ jsonValue: event.detail.value,status: 2,subTextureList: json.SubTexture,});} catch (err) {console.log(err);this.setData({ jsonValue: '',status: 1, // this.data.status & 13, // parseInt('1101', 2)subTextureList: [],});wx.showToast({ title: 'JSON格式有误', icon: 'error' })}},/*** 选择龙骨图集PNG、JSON*/async choosePNGJSON(e){console.log('选择龙骨图集PNG、JSON');wx.showLoading({ title: '选择图集' });imgUtil.chooseAtlas({ count: 2}).then(res => {if(res.length != 2){wx.showToast({ title: '文件数量异常!', icon: 'error' });return;}let texture, json;if(res[0].type === 'png'){[texture, json] = res;}else{[json, texture] = res;}wx.showLoading({ title: '解析图集' });this.data.texture = texture; // 更新图集PNG的相关信息。点击预览时会用到它的 paththis.data.shareZipFile = { name: `${json.name}.zip`, path: `${dbsplit}/${json.name}.zip`}; // zip路径打包时用// 图集PNG填充画布this.fillCanvasWithImage(texture).then(()=>{// 填充完成后,在下一个时间片段更新数据this.setData({textureBase64: imgUtil.imageToBase64(texture.path, texture.type), // 更新 image 组件 srcsubTextureList: json.SubTexture,                                  // 更新页面上的 subTexture 列表status: 2,                                                        // 已选图,JSON完成解析},()=>{wx.hideLoading();});})}).catch(err => {console.log(err);wx.showToast({ title: '图集选择失败', icon: 'error' });this.setData({textureBase64: '',              // 更新 image 组件 srcsubTextureList: [],             // 更新页面上的 subTexture 列表status: 0,});}).finally(()=>{wx.hideLoading() })},/*** 选择龙骨图集PNG文件*/async choosePNG(e){console.log('选择龙骨图集PNG文件');let whereFrom = globalData.systemInfo.isPC ? 'media' : 'message';let promises = imgUtil.chooseImg({ count: 1, whereFrom }); // media messageawait promises.then(res => {let texture = res[0];console.log(texture);this.setData({ texture , textureBase64: imgUtil.imageToBase64(texture.path, texture.type),status: 1,// 重选图片后,清空已选的JSONjsonValue: '',        // 清除 JSON 数据subTextureList: []    // 清除 解析后的 JSON 数据}, res => {this.fillCanvasWithImage(texture); // 填充画布});}).catch(err => {console.log(err);wx.showToast({ title: '选择图片失败', icon: 'error' });this.setData({ texture: {} , textureBase64: '',status: 0, // this.data.status & 14,});});},/*** 将图片绘制到画布*/fillCanvasWithImage(imageInfo){let { path, width, height, orientation, type } = imageInfo;// 按图片大小更新画布尺寸canvas.width = width * pixelRatio;canvas.height = height * pixelRatio;ctx.scale(pixelRatio, pixelRatio);return new Promise((resolve, reject)=>{// 更新画布 渲染宽高。完成后,绘制图片到画布this.setData({ canvasWidth: width, canvasHeight: height}, res=> {const image = canvas.createImage(); // 创建图片对象image.onload = () => ctx.drawImage(image, 0, 0); // 图片加载完成,在回调中将其绘制到画布image.src = path; // 设置图片 srcresolve();});});},/*** 解析JSON并拆分图集*/async parseJsonAndSplitIMG(e){console.log('解析JSON并拆分图集');if(this.data.status < 1){wx.showToast({ title: '请选择图片', icon: 'error'});return;}if(this.data.status < 2){wx.showToast({ title: '请提供JSON', icon: 'error'});return;}this.splitIMG();},/*** 拆分龙骨图集PNG文件*/async splitIMG(e){console.log('拆分龙骨图集PNG文件');let pArr = this.data.subTextureList.map(subTexture => {return new Promise((resolve, reject)=> {let { x, y, width, height, } = subTexture;wx.canvasToTempFilePath({x, y, width, height, canvas,destWidth: width,destHeight: height,fileType: 'png',success: res => {console.log(res.tempFilePath);subTexture.tempFilePath = res.tempFilePath;resolve(subTexture);},fail: reject});});});Promise.all(pArr).then(async res => {await this.creatZip(res);this.setData({ status: 3, }); // 更新状态,完成拆图}).catch(err => {this.setData({ status: 2, });});},/*** 将拆好的小图打包为 ZIP*/async creatZip(subTextureList){console.log('将拆好的小图打包为 ZIP');try {// 图片列表let fileList = subTextureList.map(subTexture => ({ name: subTexture.name, path: subTexture.tempFilePath}));// 创建压缩包await fileUtil.zip(fileList, this.data.shareZipFile.path, progress => { wx.showLoading({ title: progress.msg, });if(progress.percent == 100){setTimeout(wx.hideLoading, 200);}});// 更新状态console.log(this.data.shareZipFile.path);this.setData({subTextureList});} catch (err) {console.error(err)wx.showToast({ icon: 'error', title: '打包失败' });this.setData({shareZipFile: {}});} finally {wx.hideLoading();}},/*** 将拆分后的文件打包导出*/saveIMG(e){console.log('将拆分后的文件打包导出');console.log(this.data.subTextureList);if(this.data.status < 3){wx.showToast({ title: '尚未拆图', icon: 'error' });return;}// 如果是电脑端,否则是手机端if(globalData.systemInfo.platform == 'windows' || globalData.systemInfo.platform == 'mac'// || globalData.systemInfo.platform == 'devtools'){wx.saveFileToDisk({filePath: this.data.shareZipFile.path,success: console.log,fail: console.error});} else {wx.shareFileMessage({filePath: this.data.shareZipFile.path,fileName: this.data.shareZipFile.name,success: console.log,fail: console.error,complete: console.log});}},async previewTexture(e){if(!!this.data.texture.path == false && globalData.systemInfo.isPC){await this.choosePNG();return;}wx.previewImage({urls: [this.data.texture.path],success: (res) => {},fail: (res) => {},complete: (res) => {},})},previewSubTexture(e){if(this.data.status < 3){wx.showToast({ title: '尚未拆分', icon:"error" });return;}wx.previewImage({urls: this.data.subTextureList.map(obj => obj.tempFilePath),current: e.currentTarget.dataset.texturePath,showmenu: true,success: (res) => {},fail: (res) => {},complete: (res) => {},})}
})

dragonbones-split.json

{"usingComponents": {}
}

dragonbones-split.wxml

<!--packageTools/pages/dragonbones-split/dragonbones-split.wxml-->
<!-- 大家好我是笨笨,笨笨的笨,笨笨的笨,谢谢!https://blog.csdn.net/jx520/ -->
<view class="main-container bg-60" ><view class="top-container poem-container poem-h bg-24" style="min-height: 200rpx;"><view></view><view>无根翡翠顺江涛, 有尾鱼虾逆水潮。</view><view>行宿天涯本无路, 去留飘渺也逍遥。</view></view><view class="top-container scroll-y home-top" disabled><image class="texture chessboard" src="{{textureBase64}}" bind:tap="previewTexture"/><view wx:for="{{subTextureList}}" wx:key="name"bindtap="previewSubTexture" data-texture-name="{{item.name}}" data-texture-path="{{item.tempFilePath}}"class="sub-texture-list {{status < 3 ? 'disabled' : 'splited'}}"><view class="sub-texture-row"> <view>{{item.name}}</view><view>{{item.width}} x {{item.height}}</view></view></view><view class="sub-texture-list" wx:if="{{isPC}}"><textarea class="json-area" auto-height	maxlength="-1" placeholder="请在此处粘贴龙骨图集的 JSON 内容" value="{{jsonValue}}"bindblur="onChange" bindlinechange="onChange" bindconfirm="onChange" bindinput="onChange" /></view><canvas id="myCanvas" type="2d" class="canvas2d" style="width: {{canvasWidth}}px; height: {{canvasHeight}}px;" /></view><view class="bottom-container"><!-- 移动端 --><view wx:if="{{isPC == false}}"><view class="but-row"><view class="button button-large" bindtap="choosePNGJSON"><view>选择龙骨PNGJSON</view></view><view class="button button-large {{status < 2 ? 'disabled' : ''}}" bindtap="parseJsonAndSplitIMG"><view>拆分图集</view></view></view><view class="but-row"><view class="button button-large {{status < 3 ? 'disabled' : ''}}" bindtap="saveIMG"><view>转发到聊天</view></view></view></view><!-- PC--><view wx:if="{{isPC}}"><view class="but-row"><view class="button button-large" bindtap="choosePNG"><view wx:if="{{textureBase64 === ''}}">选择图片</view><view wx:if="{{textureBase64 != ''}}">重选图片</view></view><view class="button button-large {{status < 2 ? 'disabled' : ''}}" bindtap="parseJsonAndSplitIMG"><view>拆分图集</view></view></view><view class="but-row"><view class="button button-large {{status < 3 ? 'disabled' : ''}}" bindtap="saveIMG"><view>保存</view></view></view></view><view class="gb-img"></view></view>
</view>

dragonbones-split.wxss

/* packageTools/pages/dragonbones-split/dragonbones-split.wxss */
@import '/common/wxss/player-page-common.wxss';.button{display: flex;flex-direction: column;justify-content: center;align-items: center;margin: 10rpx;padding: 10rpx;color: rgb(236, 236, 236);box-sizing: border-box;
}
.button-large{display: flex;justify-content: center;text-align: center;font-size: large;width: auto;height: 100%;max-height: 50%;box-sizing: border-box;flex-grow: 1;border-radius: 10px;background-color: rgb(102, 102, 102);border-top: 1px solid rgb(112, 112, 112);border-bottom: 2px solid rgb(90, 90, 90);
}.but-row {display: flex;
}
.sub-texture-row {display: flex;align-items: center;padding: 0 20rpx;border-bottom: rgb(102, 102, 102) solid 1px;box-sizing: border-box;
}
.sub-texture-row>view {margin: 4px;
}
.sub-texture-row :nth-child(1) {width: 70%;word-wrap: break-word;border-right: #666 solid 1px;
}
.sub-texture-row :nth-child(2) {margin-left: 5px;width: 30%;height: 100%;
}.texture {padding: 6px;width: 100%;border: rgb(63, 63, 63) solid 2px;box-sizing: border-box;
}
.canvas2d {position: absolute;right: 100vw;
}
.sub-texture-list {display: flex;flex-direction: column;padding: 5rpx 20rpx;
}
.json-area {background-color: #000;border-radius: 10rpx;width: 100%;padding: 20rpx;box-sizing: border-box;font-size: x-small;min-height: 430rpx;
}.splited {color: chartreuse;
}

imgUtil.js

const fs = wx.getFileSystemManager();/*** 选择图集(PNG和JSON一对)* @param {object} options */
function chooseAtlas(_options = {}){const defaultOptions = { count: 2 };let options = { ...defaultOptions, ..._options };// 选择 PNG、JSONlet promise = wx.chooseMessageFile(options).then(res => res.tempFiles) .then(tempFiles => {return tempFiles.map(tempFilePath => {if(tempFilePath.type === 'image'){ // 图片return wx.getImageInfo({ src: tempFilePath.path }).then(res => {let { path, width, height, orientation, type } =  res;let imageInfo = { path, width, height, orientation, type };return imageInfo;});}else if(tempFilePath.type === 'file' && tempFilePath.path.toLowerCase().endsWith('.json')){ // JSONreturn parseJSON(fs.readFileSync(tempFilePath.path, 'utf-8'));}else{return null;}}).filter(obj => obj != null);}).catch(err=> {console.log(err);return [];});// 全部完成再返回return promise.then(promiseArr => {return Promise.all(promiseArr).then(res => res);})
}/*** 选择图片* @param {object} options */
function chooseImg(_options = {}){const defaultOptions = {count: 9, mediaType: ['image'],whereFrom: 'message' , // 从何处选取。合法值:message media};let options = { ...defaultOptions, ..._options };let promise;// 根据参数中给的选择方式,调用对应方法。switch (options.whereFrom) {case 'media':promise = wx.chooseMedia(options).then(res => res.tempFiles.map( data => data.tempFilePath) ).catch(err=> {console.log(err);return [];});break;default:promise = wx.chooseMessageFile(options).then(res => res.tempFiles.map( data => data.path) ).catch(err=> {console.log(err);return [];});break;}// 对选择的图片,获取信息。构建好对象返回return promise.then(tempFiles => {return tempFiles.map(tempFilePath => {return wx.getImageInfo({ src: tempFilePath }).then(res => {let { path, width, height, orientation, type } =  res;let imageInfo = { path, width, height, orientation, type };return imageInfo;});});}).then(promiseArr => { // 全部完成再返回return Promise.all(promiseArr).then(res => res);});
}/*** 从 tempFilePath 以 base64 格式读取文件内容* @param {*} tempFilePath * @param {*} type 图片类型是提前通过 getImageInfo 获取的*/
function imageToBase64(tempFilePath, type) {let data = fs.readFileSync(tempFilePath, 'base64');return `data:image/${type};base64,${data}`;
}/*** 解析龙骨图集的JSON* @param {string} dbJsonTxt 龙骨图集的JSON*/
function parseJSON(dbJsonTxt){// 解析JSONlet json = JSON.parse(dbJsonTxt);// 从 SubTexture 中取出图片名// 判断是否有重复,如果重复就用完整路径名,否则:就直接用图片名let arr = json.SubTexture.map(st => st.name.substr(st.name.lastIndexOf('/')+1));// { "x": 2, "y": 2, "width": 554, "height": 140, "name": "weapon_hand_r"}arr = json.SubTexture.map(subTexture => {if(arr.length !== new Set(arr).size){subTexture.name = `${subTexture.name.replace(/\//g, '-')}.png`;}else{subTexture.name = `${subTexture.name.substr(subTexture.name.lastIndexOf('/')+1)}.png`;}return subTexture;});console.log(arr);json.SubTexture = arr;json.type = 'json';return json;
}// /**
//  * 选择JSON。(PC端的弹窗竟然不支持输入功能。此方法没用上)
//  * @param {object} options 
//  */
// function chooseJSON(_options = {}){
//   const defaultOptions = {
//     count: 1,
//     whereFrom: 'modal' , // 从何处选取。合法值: modal message
//   };
//   let options = { ...defaultOptions, ..._options };
//   let promise;
//   // 根据参数中给的选择方式,调用对应方法。
//   switch (options.whereFrom) {
//     case 'modal':
//       promise = wx.showModal({
//           title: '龙骨图集JSON',
//           placeholderText: '请输入龙骨图集JSON内容',
//           confirmText: '解析',
//           editable: true,
//         }).then(res => {
//           if (res.confirm && res.errMsg === "showModal:ok" ) {
//             console.log(res.content);
//             return res.content;
//           } else if (res.cancel) {
//             console.log('用户点击取消')
//             return Promise.reject();
//           }
//         });
//       break;
//     default:
//       promise = wx.chooseMessageFile(options)
//         .then(res => res.tempFiles.map( data => fs.readFileSync(data.path, 'utf-8')))
//         .catch(err=> {
//           console.log(err);
//           return '';
//         });
//       break;
//   }
//   return promise;
// }module.exports = {chooseAtlas,chooseImg,imageToBase64,parseJSON,
}

参考资料

笑虾:微信小程序 - 创建 ZIP 压缩包
笑虾:微信小程序 - 文件工具类 fileUtil.js

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

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

相关文章

C语言-数组指针笔试题讲解(1)-干货满满!!!

文章目录 ▶️1.sizeof和strlen的对比&#x1f4af;➡️1.1 sizeof是什么&#xff1f;&#x1f4af;➡️1.2sizeof用法举例&#x1f4af;▶️1.3strlen是什么&#xff1f;&#x1f4af;▶️1.4 strlen函数用法举例&#xff1a;&#x1f4af;▶️1.5 strlen和sizeof的对比&#…

栈(C语言版)

一.栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。 栈中的数据元素遵守 后进先出 LIFO &#xff08; Last In First Out &#xff09;的原则。…

人工智能数据挖掘:发掘信息的新境界

导言 人工智能数据挖掘作为信息时代的利器&#xff0c;通过智能算法和大数据技术的结合&#xff0c;为企业、学术研究和社会决策提供了前所未有的洞察力。本文将深入探讨人工智能在数据挖掘领域的应用、技术挑战以及对未来的影响。 1. 人工智能数据挖掘的基本原理 数…

回归预测 | MATLAB实现SABO-LSTM基于减法平均优化器优化长短期记忆神经网络的多输入单输出数据回归预测模型 (多指标,多图)

回归预测 | MATLAB实现SABO-LSTM基于减法平均优化器优化长短期记忆神经网络的多输入单输出数据回归预测模型 &#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现SABO-LSTM基于减法平均优化器优化长短期记忆神经网络的多输入单输出数据回归预测模型 &a…

CSS3 2D变形 过渡 动画

​​​​​ transform(2D变形)概述translate()平移scale()缩放skew()倾斜rotate()旋转transform-origin中心原点 CSS3 2D变形 3D变形 过渡 动画 在CSS3中&#xff0c;动画效果包括4个部分&#xff1a;变形&#xff08;transform&#xff09;、3D变形、过渡&#xff08;transit…

数据结构(Chapter Two -02)—顺序表基本操作实现

在前一部分我们了解线性表和顺序表概念&#xff0c;如果有不清楚可以参考下面的博客&#xff1a; 数据结构(Chapter Two -01)—线性表及顺序表-CSDN博客 首先列出线性表的数据结构&#xff1a; #define MaxSize 50 //定义顺序表最大长度 typedef struct{ElemType data…

数据可视化---双Y轴折线图比较

内容导航 类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统…

<软考高项备考>《论文专题 - 15 资源管理(一) 》

1 写作要点 过程定义、作用写作要点、思路规划资源管理是定义如何估算、获取、管理和利用团队以及实物资源的过程。作用:根据项目类型和复杂程度确定适用于项目资源的管理方法和管理程度。资源管理计划的内容、编写的原则&#xff08;考虑资源竞争、稀缺资源、争取资源等&…

SQL进阶理论篇(十二):InnoDB中的MVCC是如何实现的?

文章目录 简介事务版本号行记录的隐藏列Undo LogRead View的工作流程总结参考文献 简介 在不同的DBMS里&#xff0c;MVCC的实现机制是不同的。本节我们会以InnoDB举例&#xff0c;讲解InnoDB里MVCC的实现机制。 我们需要掌握这么几个概念&#xff1a; 事务版本号行记录的隐藏…

TrustZone之其他设备及可信基础系统架构

一、其他设备 最后,我们将查看系统中的其他设备,如下图所示: 我们的示例TrustZone启用的系统包括一些尚未涵盖的设备,但我们需要这些设备来构建一个实际的系统。 • 一次性可编程存储器(OTP)或保险丝 这些是一旦写入就无法更改的存储器。与每个芯片上都包含相同…

基础算法(3):排序(3)插入排序

1.插入排序实现 插入排序的工作原理是&#xff1a;通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已经排序的序列从后向前扫描&#xff0c;找到位置并插入&#xff0c;类似于平时打扑克牌时&#xff0c;将牌从大到小排列&#xff0c;每次摸到一张牌就插入到正确的位…

202352读书笔记|踪迹——在繁星般的黄的交错里,秦淮河仿佛笼上了一团光雾

《踪迹》朱自清&#xff0c;因为春&#xff0c;匆匆&#xff0c;背影&#xff0c;疯狂入坑。学生时代&#xff0c;我的语文并不好&#xff0c;可害怕写作文了。对于文章/古文/诗都是比较浅显的学习&#xff0c;从未探究深意&#xff0c;可以说并没有学明白。是比较跳脱而表面的…

Docker 的基本概念、优势、及在程序开发中的应用

Docker 是一种容器化平台,它通过使用容器化技术,将应用程序及其依赖性打包到一个独立的、可移植的容器中,从而实现应用程序的快速部署、可靠性和可扩展性。 下面是 Docker 的一些基本概念和优势: 容器:Docker 使用容器化技术,将应用程序及其依赖性打包到一个可移植的容器…

不做数据采集,不碰行业应用,专注数字孪生PaaS平台,飞渡科技三轮融资成功秘诀

12月15日&#xff0c;飞渡科技在北京举行2023年度投资人媒体见面会&#xff0c;全面分享其产品技术理念与融资之路。北京大兴经开区党委书记、管委会主任常学智、大兴经开区副总经理梁萌、北京和聚百川投资管理有限公司&#xff08;以下简称“和聚百川”&#xff09;投资总监严…

ChatGPT使用:一个发包机器人的提示词

发包机器人&#xff1a; 设想&#xff1a;目前项目组有n条打包线会输出多个包&#xff0c;用户想获取最新的包是比较困难的&#xff0c;难点在于 1. 分支多&#xff1a;trunk&#xff0c;release&#xff0c;outer等&#xff0c;至少有3个分支&#xff1b; 2. 多平台&#x…

分布式理论 | RPC | Spring Boot 整合 Dubbo + ZooKeeper

一、基础 分布式理论 什么是分布式系统&#xff1f; 在《分布式系统原理与范型》一书中有如下定义&#xff1a;“分布式系统是若干独立计算机的集合&#xff0c;这些计算机对于用户来说就像单个相关系统”&#xff1b; 分布式系统是由一组通过网络进行通信、为了完成共同的…

入侵检测系统HIDS_wazuh使用及部署

文章目录 wazuh简介wazuh在线文档及下载资源虚拟机默认用户是&#xff1a; 访问页面登录&#xff0c;默认是用户&#xff1a;admin&#xff0c;密码&#xff1a;admin进入系统后页面点击代理总数选择需要添加的主机需要检测的主机测试是否ping通wazuh服务机测试访问通后&#x…

搭建动态网站之——基于Redhat8.6搭建Discuz论坛

一、动态网站与静态网站区别 动态网站并不是指具有动画功能的网站&#xff0c;而是指网站内容可根据不同情况动态变更的网站&#xff0c;一般情况下动态网站通过数据库进行架构。 动态网站除了要设计网页外&#xff0c;还要通过数据库和编程序来使网站具有更多自动的和高级的功…

数据仓库与数据挖掘c5-c7基础知识

chapter5 分类 内容 分类的基本概念 分类 数据对象 元组(x,y) X 属性集合 Y 类标签 任务 基于有标签的数据&#xff0c;学习一个分类模型&#xff0c;通过这个分类模型&#xff0c;可以把一组属性x映射到一个特定的类别y上 类别y 提前设定好的--如&#xff1a;学生…

机器学习---推荐系统案例(一)

一、推荐系统-数据处理流程 推荐系统数据处理首先是将Hive中的用户app历史下载表与app浏览信息表按照设备id进行关联&#xff0c;然后将关联数据使用python文件进行处理&#xff0c;将数据预处理为label和feature两列的临时数据&#xff0c;后期经过处理转换成逻辑回归 模型的…