canvas画图,画矩形、圆形、直线可拖拽移动,可拖拽更改尺寸大小

提示:canvas画图,画矩形,圆形,直线,曲线可拖拽移动

文章目录

  • 前言
  • 一、画矩形,圆形,直线,曲线可拖拽移动
  • 总结


前言

一、画矩形,圆形,直线,曲线可拖拽移动

test.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>canvas跟随鼠标移动画透明线</title><style>div,canvas,img{user-select: none;}.my_canvas,.bg_img{position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);}.cf{content: '';display: block;overflow: hidden;clear: both;}.fl{float: left;}.fr{float: right;}.bg_img{width: 674px;height: 495px;background: #ddd;}.img_tools{position: absolute;top: 20px;left: 50%;transform: translateX(-50%);border: 1px solid #eee;border-radius: 64px;height: 64px;line-height: 64px;box-sizing: border-box;padding: 15px 20px 0;}.img_tool{height: 32px;line-height: 32px;color: #000;font-size: 14px;text-align: center;width: 80px;border: 1px solid #ddd;border-radius: 32px;margin-right: 10px;cursor: pointer;position: relative;}.img_tool_active{color: #409EFF;border: 1px solid #409EFF;}.show_history{position: absolute;bottom:0;left: 50%;transform: translateX(-50%);}.show_history>img{width: 120px;margin-right: 10px;border: 1px solid #eee;border-radius: 4px;}.canvas_text{width: 120px;height: 32px;line-height: 32px;position: absolute;top: 0;left: 0;border: 1px solid #c0c0c0;border-radius: 4px;font-size: 16px;outline: none;background: none;display: none;font-family: Arial, Helvetica, sans-serif;padding-left: 0;letter-spacing: 0;}</style>
</head>
<body><div class="bg_img"></div><canvas id="myCanvasBot" class="my_canvas" width="674" height="495"></canvas><canvas id="myCanvasTop" class="my_canvas" width="674" height="495"></canvas><div class="img_tools cf"><div class="img_tool fl" onclick="changeType('curve',this)">涂鸦</div><div class="img_tool fl" onclick="changeType('line',this)">直线</div><div class="img_tool fl img_tool_active" onclick="changeType('rect',this)">矩形</div><div class="img_tool fl" onclick="changeType('ellipse',this)">圆形</div><!-- <div class="img_tool fl" onclick="changeType('eraser',this)">橡皮擦</div> --><!-- <div class="img_tool fl" onclick="changeType('text',this)">文字</div> --><!-- <div class="img_tool fl" onclick="changeType('revoke',this)">撤销</div> --><!-- <div class="img_tool fl" onclick="changeType('restore',this)">恢复</div> --></div><input id="canvasText" autofocus class="canvas_text" type="text"><div id="showHistory" class="show_history"></div><script>const canvasWidth = 674;const canvasHeight = 495;//底层canvasconst botCan = document.getElementById('myCanvasBot');//顶层canvasconst topCan = document.getElementById('myCanvasTop');//底层画布const botCtx = botCan.getContext('2d');//顶层画布const topCtx = topCan.getContext('2d');//鼠标是否按下  是否移动let isDown = false,isMove = false;//鼠标是否在canvas上抬起let isCanUp = false;//需要画图的轨迹let drawPoints = [];//起始点x,ylet startPoint = {x:0,y:0};//图片历史let historyList = [];//空历史historyList.push(new Image())//当前绘画历史indexlet historyIndex = -1;//icon历史// let partHistory = [];//操作类型let drawType = 'rect';//画线宽度const lineWidth = 10;//文字大小const fontSize = 16;//画线颜色let strokeStyle = 'rgba(255,0,0,0.6)';//path2D图形列表let pathList = [];//path2D单个图形let pathObj = null;//path2D的唯一标识let pathId = 0;//当前被激活的path2Dlet activePath = null;//是否为拖拽行为let isDrag = false;//拖拽是否移动let isDragMove = false;//是否为改变尺寸行为isResize = false;//改变尺寸点list let pointsList = [];//拖拽修改尺寸的点let activePoint = null;//resize是否移动let isResizeMove = false;//改变尺寸点let resizePath = null;//改变尺寸点Listlet resizePointList = [];//文字输入框initconst canvasText = document.getElementById('canvasText');canvasText.style.display = 'none';canvasText.style.lineHeight = '32px';canvasText.style.height = '32px';canvasText.style.display = 'none';canvasText.style.color = 'none';canvasText.addEventListener('blur',()=>{topCtx.font = fontSize + 'px Arial, Helvetica, sans-serif';let h = parseFloat(canvasText.style.height);topCtx.fillText(canvasText.value, startPoint.x+1, startPoint.y+h/2+fontSize/2-1);canvasText.style.display = 'none';canvasText.value = '';topToBot();})//起始点x,ylet textPoint = {x:0,y:0};//鼠标按下const mousedown = (e)=>{isDown = true;let x = (e||window.event).offsetX;let y = (e||window.event).offsetY;if(canvasText.style.display == 'none')startPoint = {x,y};//检查是否点击到resize的点activePoint = isResizePointInPath(x,y);if(activePoint){isResize = true;activePath = activePoint.activePath;//原有path,需要清除//可resize,清除resize点topCtx.clearRect(0,0,canvasWidth,canvasHeight);switch (activePoint.type){case 'rect':makePathActive();break;case 'ellipse':makePathActive();break;case 'line':makePathActive();break;}return}//检测是否点击到图形activePath = isPointInPath(x,y);if(activePath){createResizePoint(activePath); //只有点击到图形的时候,才添加图形resize的点isDrag = true;topCtx.strokeStyle = topCtx.fillStyle = botCtx.strokeStyle = botCtx.fillStyle = activePath.strokeStyle||strokeStyle;topCtx.lineWidth = botCtx.lineWidth = activePath.lineWidth||lineWidth;topCtx.clearRect(0,0,canvasWidth,canvasHeight);switch (activePath.type){case 'rect':makePathActive();break;case 'ellipse':makePathActive();break;case 'line':makePathActive();break;case 'curve':makePathActive();break;}return;}if(drawType == 'text'){textPoint = {x:x+topCan.offsetLeft-canvasWidth/2,y:y+topCan.offsetTop-canvasHeight/2};// canvasText.style.height = 32 + 'px';canvasText.style.top = textPoint.y+'px';canvasText.style.left = textPoint.x+'px';canvasText.style.display = 'block';canvasText.style.fontSize = fontSize + 'px';canvasText.style.color = strokeStyle;setTimeout(()=>{canvasText.focus();},100)}if(drawType == 'curve'){drawPoints = [];drawPoints.push({x,y});}topCtx.strokeStyle = topCtx.fillStyle = botCtx.strokeStyle = botCtx.fillStyle = strokeStyle;topCtx.lineWidth = botCtx.lineWidth = lineWidth;topCtx.lineCap = topCtx.lineJoin = botCtx.lineCap = botCtx.lineJoin = 'round';}//鼠标移动const mousemove = (e)=>{let x = (e||window.event).offsetX;let y = (e||window.event).offsetY;let distanceX = 0;let distanceY = 0;if(isDown){isMove = true;if(isResize){isResizeMove = true;if(activePoint&&activePoint.resizeFun){activePoint.resizeFun(x,y);}return}if(isDrag){isDragMove = true;switch(activePath.type){case 'curve':distanceX = x - startPoint.x;distanceY = y - startPoint.y;let newPoints = [];for(let i=0;i<activePath.drawPoints.length;i++){let drawPoint = activePath.drawPoints[i];newPoints.push({x:drawPoint.x + distanceX,y:drawPoint.y + distanceY});}drawCurve(newPoints);break;case 'line':distanceX = x - startPoint.x;distanceY = y - startPoint.y;drawLine(activePath.startX + distanceX,activePath.startY + distanceY,activePath.x + distanceX,activePath.y + distanceY,);break;case 'eraser':// drawEraser(x,y);break;case 'rect':// xy 为当前point的坐标// startPoint为点击的矩形上点   查看当前point.x点距离startPoint.x移动了多少  point.y点距离startPoint.y移动了多少drawRect(activePath.x + (x - startPoint.x),activePath.y + (y - startPoint.y),activePath.width,activePath.height);break;case 'ellipse':// drawEllipse(x,y);drawEllipse(activePath.x + (x - startPoint.x),activePath.y + (y - startPoint.y),activePath.radiusX,activePath.radiusY);break;}return;}switch(drawType){case 'curve':drawPoints.push({x,y});drawCurve(drawPoints);break;case 'line':drawLine(startPoint.x,startPoint.y,x,y);break;case 'eraser':drawEraser(x,y);break;case 'rect':// drawRect(x,y);drawRect(startPoint.x, startPoint.y, x-startPoint.x, y - startPoint.y);break;case 'ellipse':drawEllipse((x+startPoint.x)/2, (y+startPoint.y)/2, Math.abs((x-startPoint.x)/2), Math.abs((y-startPoint.y)/2),0,0, Math.PI*2,true);break;}}}//鼠标抬起const mouseup = (e)=>{isCanUp = true;if(isDown){isDown = false;// topCan内容画到botCan上if(isResize){isResize = false;activePath = null;resizePointList = [];if(isResizeMove){isResizeMove = false;pathList.pop();}else{pathObj = pathList.pop();}topToBot();return;}if(isDrag){isDrag = false;activePath = null;if(isDragMove){isDragMove = false;pathList.pop();}else{pathObj = pathList.pop();}topToBot();return}if(drawType!='text')topToBot();}}//topCan内容画到botCan上const topToBot = ()=>{if(pathObj){pathObj.id = pathId++;pathList.push(pathObj);topCtx.clearRect(0,0,canvasWidth,canvasHeight);if(isCanUp)isCanUp=false;botCtx[pathObj.shape](pathObj.path);//如果有resizePointsif(pathObj.points&&pathObj.points.length>0){drawResizePoint(pathObj.points);}pathObj.points = [];pathObj = null;}drawPoints = [];isDown = false;isMove = false;}//判断是否点击到图形const isPointInPath = (x,y)=>{let PointInPath = null;for(let i=0;i<pathList.length;i++){let path = pathList[i];if(botCtx.isPointInStroke(path.path,x,y)){PointInPath = path;break;}}return PointInPath;}//判断是否点击到图形const isResizePointInPath = (x,y)=>{let point = null;for(let i=0;i<resizePointList.length;i++){let resizePoint = resizePointList[i];if(botCtx.isPointInStroke(resizePoint.path,x,y)){point = resizePoint;break;}}return point;}//激活rect图形轮廓  botCtx删除activePath  topCtx添加activePathconst makePathActive = ()=>{botCtx.clearRect(0,0,canvasWidth,canvasHeight);let arr = [];for(let i=0;i<pathList.length;i++){let path = pathList[i] if(activePath.id != path.id){botCtx[path.shape](path.path);arr.push(path);}else{topCtx.strokeStyle = path.strokeStyle;topCtx[path.shape](path.path);//创建可拖动的点}   }arr.push(activePath);pathList = arr;}//创建resize的点const createResizePoint = ()=>{activePath.points = [];let ponitFillStyle = 'rgba(0,0,0,0.8)';let pointWidth = 10;let pointHeight = 10;switch(activePath.type){case 'rect':activePath.points = [{ x:activePath.x-pointWidth/2,                y:activePath.y-pointHeight/2,                   width:10,height:10,ponitFillStyle,type:activePath.type,id:0,activePath:activePath, //用于删除原activePathresizeFun:(x,y)=>{ drawRect(x,y,activePath.x + activePath.width-x,activePath.y + activePath.height-y); },},{x:activePath.x+activePath.width/2-pointWidth/2,   y:activePath.y-pointHeight/2,                         width:10,height:10,ponitFillStyle,type:activePath.type,id:1,activePath:activePath,resizeFun:(x,y)=>{drawRect(activePath.x,y,activePath.width,activePath.height+activePath.y-y);}},{x:activePath.x+activePath.width-pointWidth/2,     y:activePath.y-pointHeight/2,                         width:10,height:10,ponitFillStyle,type:activePath.type,id:2,activePath:activePath,resizeFun:(x,y)=>{drawRect(activePath.x, y ,x-activePath.x, activePath.height+ activePath.y - y);}},{x:activePath.x+activePath.width-pointWidth/2,     y:activePath.y+activePath.height/2-pointHeight/2,     width:10,height:10,ponitFillStyle,type:activePath.type,id:3,activePath:activePath,resizeFun:(x,y)=>{drawRect(activePath.x, activePath.y ,x-activePath.x, activePath.height);}},{x:activePath.x+activePath.width-pointWidth/2,     y:activePath.y+activePath.height-pointHeight/2,       width:10,height:10,ponitFillStyle,type:activePath.type,id:4,activePath:activePath,resizeFun:(x,y)=>{drawRect(activePath.x, activePath.y ,x-activePath.x, y-activePath.y);}},{x:activePath.x+activePath.width/2-pointWidth/2,   y:activePath.y+activePath.height-pointHeight/2,       width:10,height:10,ponitFillStyle,type:activePath.type,id:5,activePath:activePath,resizeFun:(x,y)=>{drawRect(activePath.x, activePath.y ,activePath.width, y-activePath.y);}},{x:activePath.x-pointWidth/2,                      y:activePath.y+activePath.height-pointHeight/2,       width:10,height:10,ponitFillStyle,type:activePath.type,id:6,activePath:activePath,resizeFun:(x,y)=>{drawRect(x, activePath.y ,activePath.x-x+activePath.width, y-activePath.y);}},{x:activePath.x-pointWidth/2,                     y:activePath.y+activePath.height/2-pointHeight/2,width:10,height:10,ponitFillStyle, type:activePath.type,id:7,activePath:activePath,resizeFun:(x,y)=>{drawRect(x, activePath.y ,activePath.x-x+activePath.width, activePath.height);}},];// drawResizePoint( activePath.points);break;case 'ellipse':activePath.points = [{x:activePath.x - pointWidth/2,y:activePath.y - activePath.radiusY - pointHeight/2,                   width:10,height:10,ponitFillStyle,type:activePath.type,id:0,activePath:activePath,resizeFun:(x,y)=>{drawEllipse(activePath.x,activePath.y,activePath.radiusX,Math.abs(y-activePath.y));},},{x:activePath.x + activePath.radiusX - pointWidth/2,y:activePath.y - pointHeight/2,                   width:10,height:10,ponitFillStyle,type:activePath.type,id:0,activePath:activePath,resizeFun:(x,y)=>{drawEllipse(activePath.x,activePath.y,Math.abs(x - activePath.x),activePath.radiusY);},},{x:activePath.x - pointWidth/2,y:activePath.y + activePath.radiusY - pointHeight/2,                   width:10,height:10,ponitFillStyle,type:activePath.type,id:0,activePath:activePath,resizeFun:(x,y)=>{drawEllipse(activePath.x,activePath.y,activePath.radiusX,Math.abs(y-activePath.y));},},{x:activePath.x - activePath.radiusX - pointWidth/2,y:activePath.y - pointHeight/2,                   width:10,height:10,ponitFillStyle,type:activePath.type,id:0,activePath:activePath,resizeFun:(x,y)=>{drawEllipse(activePath.x,activePath.y,Math.abs(x - activePath.x),activePath.radiusY);},},]// drawResizePoint( activePath.points);break;case 'line':activePath.points = [{ x:activePath.startX - pointWidth/2,y:activePath.startY - pointHeight/2,                   width:10,height:10,ponitFillStyle,type:activePath.type,id:0,activePath:activePath,resizeFun:(x,y)=>{drawLine(x,y,activePath.x,activePath.y);},},{ x:activePath.x - pointWidth/2,y:activePath.y - pointHeight/2,                   width:10,height:10,ponitFillStyle,type:activePath.type,id:0,activePath:activePath,resizeFun:(x,y)=>{drawLine(activePath.startX,activePath.startY,x,y);},}]// drawResizePoint( activePath.points);break;}drawResizePoint( activePath.points);}//画resize的点const drawResizePoint = (points)=>{resizePointList = [];for(let i=0;i<points.length;i++){let resizePoint = points[i];let path = new Path2D();topCtx.beginPath();topCtx.moveTo(resizePoint.x,resizePoint.y);path.rect(resizePoint.x,resizePoint.y,resizePoint.width,resizePoint.height);topCtx.strokeStyle = resizePoint.ponitFillStyle;topCtx.stroke(path);resizePoint.path = path;resizePointList.push(resizePoint)}}//画椭圆形const drawEllipse = (x,y,radiusX,radiusY)=>{pathObj = null;//清除topCtx画布topCtx.clearRect(0,0,canvasWidth,canvasHeight);topCtx.beginPath();let path = new Path2D();// 椭圆path.ellipse(x,y,radiusX,radiusY,0,0, Math.PI*2,true);topCtx.strokeStyle = strokeStyle;topCtx.stroke(path);pathObj = {type:'ellipse',shape:'stroke',path,x, y, radiusX, radiusY,lineWidth:topCtx.lineWidth||lineWidth,strokeStyle:topCtx.strokeStyle||strokeStyle,points:[],};}//画矩形const drawRect = (x,y,width,height)=>{pathObj = null;//清除topCtx画布topCtx.clearRect(0,0,canvasWidth,canvasHeight);topCtx.beginPath();let path = new Path2D();// 矩形//这里需要确认起始点和结束点//即  不管画出的矩形是向上,向下 左上角点为起始点,做下角点为结束点let beginX = width<0?x+width:x;let beginY = height<0?y+height:ypath.rect(beginX,beginY,Math.abs(width),Math.abs(height));topCtx.strokeStyle = strokeStyle;topCtx.stroke(path);pathObj = {type:'rect',shape:'stroke',path,x:beginX, y:beginY, width:Math.abs(width), height:Math.abs(height),lineWidth:topCtx.lineWidth||lineWidth,strokeStyle:topCtx.strokeStyle||strokeStyle,points:[],};}//橡皮擦const drawEraser = (x,y)=>{//橡皮擦圆形半径const radius = lineWidth/2;botCtx.beginPath(); for(let i=0;i<radius*2;i++){//勾股定理高hlet h = Math.abs( radius - i); //i>radius h = i-radius; i<radius  h = radius - i//勾股定理llet l = Math.sqrt(radius*radius -h*h); //矩形高度let rectHeight = 1;//矩形宽度let rectWidth = 2*l;//矩形Xlet rectX = x-l;//矩形Ylet rectY = y-radius + i;botCtx.clearRect(rectX, rectY, rectWidth, rectHeight);}}//画透明度直线const drawLine = (startX,startY,x,y)=>{if(!isDown)return;pathObj = null;//清空当前画布内容topCtx.clearRect(0,0,canvasWidth,canvasHeight);//必须每次都beginPath  不然会卡topCtx.beginPath();let path = new Path2D();path.moveTo(startX,startY);path.lineTo(x,y);topCtx.strokeStyle = strokeStyle;topCtx.stroke(path);pathObj = {type:'line',shape:'stroke',path,x, y, startX, startY,lineWidth:topCtx.lineWidth||lineWidth,strokeStyle:topCtx.strokeStyle||strokeStyle,points:[],};}//画带透明度涂鸦const drawCurve = (drawPointsParams)=>{// drawPoints.push({x,y});if(!drawPointsParams||drawPointsParams.length<1)returnpathObj = null;//清空当前画布内容topCtx.clearRect(0,0,canvasWidth,canvasHeight);//必须每次都beginPath  不然会卡topCtx.beginPath();let path = new Path2D();path.moveTo(drawPointsParams[0].x,drawPointsParams[0].y);for(let i=1;i<drawPointsParams.length;i++){path.lineTo(drawPointsParams[i].x,drawPointsParams[i].y);}topCtx.strokeStyle = strokeStyle;topCtx.stroke(path);pathObj = {type:'curve',shape:'stroke',path,drawPoints:drawPointsParams,lineWidth:topCtx.lineWidth||lineWidth,strokeStyle:topCtx.strokeStyle||strokeStyle};}//切换操作const changeType = (type,that)=>{// if(drawType == type) return;let tools = document.getElementsByClassName('img_tool');for(let i=0;i<tools.length;i++){let ele = tools[i];if(ele.classList.contains('img_tool_active'))ele.classList.remove('img_tool_active');}that.classList.add('img_tool_active');drawType = type;//撤销if(drawType == 'revoke'){if(historyIndex>0){historyIndex--;drawImage(historyList[historyIndex]);}//恢复}else if(drawType == 'restore'){if(historyIndex<historyList.length - 1){historyIndex++;drawImage(historyList[historyIndex]);}}}const drawImage = (img)=>{botCtx.clearRect(0,0,canvasWidth,canvasHeight);botCtx.drawImage(img,0,0);}//canvas添加鼠标事件topCan.addEventListener('mousedown',mousedown);topCan.addEventListener('mousemove',mousemove);topCan.addEventListener('mouseup',mouseup);//全局添加鼠标抬起事件document.addEventListener('mouseup',(e)=>{let x = (e||window.event).offsetX;let y = (e||window.event).offsetY;let classList = (e.target || {}).classList || [];if(classList.contains('img_tool'))return;if(!isCanUp){isDown = false;// topCan内容画到botCan上if(isDrag){isDrag = false;activePath = null;if(isDragMove){isDragMove = false;pathList.pop();}else{pathObj = pathList.pop();}topToBot();return}if(drawType == 'line'&&!isDrag){let clientX = topCan.getBoundingClientRect().x;let clientY = topCan.getBoundingClientRect().y;drawLine(startPoint.x,startPoint.y,x-clientX,y-clientY);}// topCan内容画到botCan上topToBot();}});//全局添加鼠标移动事件document.addEventListener('mousemove',(e)=>{if(isMove)return isMove = false;let x = (e||window.event).offsetX;let y = (e||window.event).offsetY;if(drawType == 'line'&&!isDrag){let clientX = topCan.getBoundingClientRect().x;let clientY = topCan.getBoundingClientRect().y;drawLine(startPoint.x,startPoint.y,x-clientX,y-clientY);}});</script>
</body>
</html>

请添加图片描述
请添加图片描述

总结

踩坑路漫漫长@~@

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

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

相关文章

AI预测福彩3D第23弹【2024年4月1日预测--第4套算法重新开始计算第9次测试】

今天继续对第4套算法进行测试&#xff0c;因为第4套算法已连续多期命中&#xff0c;相对来说还算稳定。好了&#xff0c;废话不多说了&#xff0c;直接上预测的结果吧~ 2024年4月1日福彩3D的七码预测结果如下 第一套&#xff1a; 百位&#xff1a;0 1 …

智慧城市一屏统览,数字孪生综合治理

现代城市作为一个复杂系统&#xff0c;牵一发而动全身&#xff0c;城市化进程中产生新的矛盾和社会问题都会影响整个城市系统的正常运转。智慧城市是应对这些问题的策略之一。城市工作要树立系统思维&#xff0c;从构成城市诸多要素、结构、功能等方面入手&#xff0c;系统推进…

深入理解鸿蒙生命周期:从应用到组件

在开发鸿蒙&#xff08;HarmonyOS&#xff09;应用时&#xff0c;理解生命周期的概念至关重要。生命周期不仅关乎应用的性能优化&#xff0c;还涉及到资源管理和用户体验等多个方面。本文将详细解析鸿蒙操作系统中应用、页面和组件的生命周期&#xff0c;帮助开发者更好地掌握这…

基于SpringBoot的游戏商城系统的设计与实现(论文+源码)_kaic

目录 1前言 1.1研究的背景及意义 1.2国内外的研究状况和发展趋势 2需求分析 2.1系统需求分析 2.1.1技术可行性 2.1.2经济可行性 2.1.3操作可行性 2.2系统的开发环境 2.2.1 Springboot框架 2.2.2 数据库Mysql 2.2.3 IntelliJ IDEA平台 2.2.4 Mybatis和MyBatis-plus 2.2.5 前端框…

海外网红营销攻略:如何精准打动Z世代,让品牌成为消费首选?

随着Z世代的崛起&#xff0c;海外网红营销成为各大品牌争相采用的一种全新推广策略。这一代年轻人对于网络内容的接受程度和参与度远远超出了前几代人&#xff0c;他们对于品牌形象、产品特点更加注重个性化和原创性。因此&#xff0c;如何精准地打动Z世代&#xff0c;让品牌成…

解读langchain与详细步骤

langchain框架目前以python或javascript包的形式提供&#xff0c;具体来说是TypeScript。 假如你想从你自己的数据、你自己的文件中具体了解一些情况&#xff0c;它可以是一本书&#xff0c;一个pdf文件&#xff0c;一个包含专有信息的数据库。Langchain允许你将GPT-4这样的大…

C语言比较三个数按照从大到小排列

今天让我们来看看如何比较三个数的大小并且排列它们吧&#xff0c;相信大家都有自己的思路&#xff0c;今天我来和大家分享一下我在做这道题时的感悟。 第一种方法 首先根据题目要求&#xff0c;我们需要先比较三个数&#xff0c;之后对它们进行从大到小的一个输出&#xff0c;…

如何在CentOS7部署Wiki.js知识库并实现分享好友公网远程使用【内网穿透】

文章目录 1. 安装Docker2. 获取Wiki.js镜像3. 本地服务器打开Wiki.js并添加知识库内容4. 实现公网访问Wiki.js5. 固定Wiki.js公网地址 不管是在企业中还是在自己的个人知识整理上&#xff0c;我们都需要通过某种方式来有条理的组织相应的知识架构&#xff0c;那么一个好的知识整…

基于PHP的新闻管理系统(用户发布版)

有需要请加文章底部Q哦 可远程调试 基于PHP的新闻管理系统(用户发布版) 一 介绍 此新闻管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。本新闻管理系统采用用户发布新闻&#xff0c;管理员审核后展示模式。 技术栈&am…

Vue element-plus 导航栏 [el-menu]

导航栏 [el-menu] Menu 菜单 | Element Plus el-menu有很多属性和子标签&#xff0c;为网站提供导航功能的菜单。 常用标签&#xff1a; 它里面有两个子标签。el-menu-item&#xff0c;它其实就是el-menu每一个里面的item&#xff0c;item就是真实匹配到路由的每个栏目&#…

如何给图片添加水印?

如何给图片添加水印&#xff1f;在现代职场中&#xff0c;图片的使用已经成为了日常工作的一部分&#xff0c;而给图片添加水印也逐渐成为了一种常见的需求。无论是在设计、广告、营销还是其他领域&#xff0c;给工作中的图片加水印都有其重要性和实用性。工作中给图片加水印的…

C# 排序的多种实现方式(经典)

一、 对数组进行排序 最常见的排序是对一个数组排序&#xff0c;比如&#xff1a; int[] aArray new int[8] { 18, 17, 21, 23, 11, 31, 27, 38 }; 1、利用冒泡排序进行排序&#xff1a; &#xff08;即每个值都和它后面的数值比较&#xff0c;每次拿出最小值&#xff09; s…

linux设置Nacos自启动

前提&#xff1a;已经安装好nacos应用 可参考&#xff1a;Nacos单机版安装-CSDN博客 1. 创建nacos.service 1.1 在 /lib/systemd/system 目录底下&#xff0c;新建nacos.service文件 [Unit] Descriptionnacos Afternetwork.target[Service]Typeforking# 单机启动方式&#…

Qt实现无边框圆角窗口

我们在使用QDialog的时候许多场景下都不需要默认的标题栏&#xff0c;这时候我们需要设置他的标志位。 this->setWindowFlags(Qt::FramelessWindowHint);由于现代的窗口风格&#xff0c;我们一般会设置窗口为圆角边框的样式&#xff0c;我们可以使用qss的方式来进行设置。 …

STM32——超声测距HC_SR04记录

一、HC_SR04简述 HC-SR04超声波测距模块可提供 2cm-400cm的非接触式距离感测功能&#xff0c;测距精度可达高到 3mm&#xff1b;模块包括超声波发射器、接收器与控制电路。 基本工作原理&#xff1a; (1)采用IO 口TRIG 触发测距&#xff0c;给最少10us 的高电平信呈。 (2)模块…

自定义 Unity Scene 的界面工具

介绍 文档中会进行SceneView的自定义扩展&#xff0c;实现显示常驻GUI和添加自定义叠加层&#xff08;Custom Overlay&#xff09;。 最近项目开发用回了原生的Unity UI相关内容。对于之前常用的FairyGUI来说&#xff0c;原生的UGUI对于UI同学来讲有些不太方便。再加上这次会…

自定义口令加入群聊怎么弄?用词令关键词直达口令加入微信群延长群二维码7天有效方法

微信口令加入群聊有二种方式 一、微信面对面建群 微信面对面建群的方式适合现实中的朋友之间相互认识且想要建立群聊的场景。微信面对面建群口令加入群聊的有效距离是在几十米范围内&#xff0c;因此只能是附近几十米范围内的人&#xff0c;正确输入微信面对面建群口令后才可…

台球王子,Android小游戏开发

使用 Android Studio 开发了一款休闲游戏 —— 《台球王子》 关键词&#xff1a;台球 A. 项目描述 台球作为一项优雅、策略性强的运动&#xff0c;在众多游戏类型中却相对较少。因此&#xff0c;开发《台球王子》小游戏&#xff0c;可以让更多玩家能够轻松享受到台球的乐趣。…

Python问题列表

文章目录 1、使用pip安装的模块都存放到哪里了&#xff1f;2、安装fitz包报错&#xff0c;如何解决&#xff1f;3、python代码运行时&#xff0c;控制台输出乱码如何解决。4、vscode中第三方库不自动补齐 1、使用pip安装的模块都存放到哪里了&#xff1f; 答&#xff1a; pip是…

易图讯智慧感知应急指挥三维电子沙盘系统设计

易图讯&#xff08;www.3dgis.top&#xff09;智慧感知应急指挥三维电子沙盘系统充分融合了物联网与人工智能识别分析技术&#xff0c;实现了从输入到输出的高效智能响应。在物联网方面&#xff0c;系统通过各类传感器和设备&#xff0c;实时采集环境、设备状态等关键数据&…