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>
总结
踩坑路漫漫长@~@
相关文章:
canvas画图,画矩形、圆形、直线可拖拽移动,可拖拽更改尺寸大小
提示:canvas画图,画矩形,圆形,直线,曲线可拖拽移动 文章目录 前言一、画矩形,圆形,直线,曲线可拖拽移动总结 前言 一、画矩形,圆形,直线,曲线可拖…...
Github 2024-04-04 Go开源项目日报 Top10
根据Github Trendings的统计,今日(2024-04-04统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10Python项目1Prometheus监控系统和时间序列数据库 创建周期:4149 天开发语言:Go协议类型:Apache License 2.0Star数量:52463 个Fork…...
并发与限流实战:如何利用 RabbitMQ 在 SpringBoot 应用中实现并发控制与流量限制
在高并发场景下,如大促销、秒杀等,我们可以采用 RabbitMQ 配合 SpringBoot 来实现并发控制与流量限制。你可以将 RabbitMQ 作为一个缓冲区,暂存大量并发请求,然后消费者可以根据自身处理能力去处理这些请求。下面就以一个高并发订…...
VUE实现下一页的功能
实现步骤:1、确定分页参数:确定当前页码和每页显示的数量;2、获取数据:使用vue的axios或其他http库向后端发送请求,传递当前页码和每页显示的数量作为参数;3、更新数据:在vue组件中,…...
GraalVM运行模式和企业级应用
文章目录 GraalVM运行模式JIT模式AOT模式 GraalVM的问题和解决方案GraalVM企业级应用传统架构的问题Serverless架构函数计算Serverless应用场景Serverless应用 GraalVM内存参数 GraalVM运行模式 JIT模式 JIT( Just-In-Time )模式 ,即时编译模…...
数据挖掘入门项目二手交易车价格预测之特征工程
文章目录 目标常见的特征工程具体步骤1. 导入数据2. 删除异常值3. 特征构造3.1 为树模型构造特征3.2 为LR NN 之类的模型构造特征 4. 特征筛选过滤式包裹式嵌入式 5. 总结 本文数据集来自阿里天池:https://tianchi.aliyun.com/competition/entrance/231784/informat…...
MFC通用静态库制作与使用
开发环境VS2013 1、新建工程,选择Win32 Project,命名,选择路径等 2、选择Static library ,勾选MFC 3、点击完成。在工程中添加相应的头文件、源文件等通用功能函数或者类。 4、在其他工程引入使用。在使用的工程项目设置中Linker…...
点亮创意:ChatGPT如何搭桥DALL-E图像编辑新纪元
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
《QT实用小工具·十二》邮件批量发送工具
1、概述 源码放在文章末尾 该项目实现了邮件的批量发送,如下图所示: 项目部分代码如下所示: #ifndef SMTPCLIENT_H #define SMTPCLIENT_H#include <QtGui> #include <QtNetwork> #if (QT_VERSION > QT_VERSION_CHECK(5,0,…...
4.2总结
了解了部分Api的使用并学习了接口的API API API包含了较多种类(System,Runtime等) System其实就是一个工具类,提供了一些与系统相关的方法 下面有一些常间的System方法 方法名说明public static void exit (int status)终止当前运行的ja…...
ArcGIS 10.8中文版详细安装教程(附安装包)
ArcGIS 10.8中文版详细安装教程(附安装包) 关键词:ArcGIS 10.8中文版安装 1.概述 ArcGIS Desktop 10.8中文版是由ESRI公司开发的一款专业的地理信息系统,一套完整的桌面GIS软件套件,它包含ArcMap、ArcCatalog、ArcG…...
什么是EL表达式?怎么使用?
文章目录 一、什么是EL表达式1、命令格式:${作用域对象别名.共享数据} 二、EL表达式与作用域对象别名1、JSP文件可以使用的作用域对象2、EL表达式提供作用域对象别名3、EL表达式将引用对象属性写入到响应体4、EL表达式简化版 三、EL表达式与运算表达式四、EL表达式提…...
基于php医院预约挂号系统
摘 要 随着信息时代的来临,过去的管理方式缺点逐渐暴露,对过去的医院预约挂号管理方式的缺点进行分析,采取计算机方式构建医院预约挂号系统。本文通过阅读相关文献,研究国内外相关技术,开发并设计一款医院预约挂号系统…...
Java NIO详解
一、概念 NIO, 即new io,也叫非阻塞io 二、NIO三个核心组件: Buffer数据缓冲区Channel通道Selector选择器 1、Buffer缓冲区 缓冲区本质上是一个可以存放数据的内存块(类似数组),可以在这里进行数据写入和读取。此…...
InstantID作者的风格保持新项目InstantStyle发布,一个强化版的IPapadter来了!
之前已经和大家介绍过InstantID相关相关的文章,感兴趣的小伙伴可以点击下面链接进行阅读~ 无缝衔接Stable Diffusion,一张照片几秒钟就能生成个性化图片-InstantID_instant-id 模型-CSDN博客 今天向大家介绍Ins…...
【Java程序员面试专栏 综合面试指南】5年资深程序员面试指南
基础知识对于5年内工作经验的同学考察相对比较多。包括编程语言、计算机网络、操作系统、设计模式、分布式知识、MySQL、Redis这种。其中随着年限的增长,基础知识考察的会越来越少,例如操作系统基本上只在学生阶段考察,计算机网络对于5年经验来说也考察的相对较少。5年以上对…...
echart 仪表盘实现指针的渐变色及添加图片
需求: 在仪表盘中设置指针为渐变色,并在仪表盘中间添加图片。 实现重点: 1、仪表盘指针渐变色的实现 渐变色通过设置pointer的itemStyle属性内的color实现,重点是echart版本,这个原本使用4.8.0的版本不起作用ÿ…...
C#面试题目含参考答案(一)
前言 面试是应聘一个工作岗位的环节,来考察一个人的工作能力与综合素质。在应聘C#程序员或与C#相关岗位时,我们都会被问到一些与.NET、C#、数据库、业务知识或编程思想等问题。本文列举一些问题及提供参考答案,题目(一)。 题目 1、什么是面向对象的三大特性 参考答案:…...
【Canvas技法】图解绘制圆弧的重要函数 arc(x,y,r,startAngle,endAngle,clockWise)
【一图释疑】 【绘制上图用代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>Html5/Canvas中绘制圆弧的重要函数 arc(x,y,r,startA…...
vulhub中Apache Solr 远程命令执行漏洞复现(CVE-2019-0193)
Apache Solr 是一个开源的搜索服务器。Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现。此次漏洞出现在Apache Solr的DataImportHandler,该模块是一个可选但常用的模块,用于从数据库和其他源中提取数据。它具有一个功能&#…...
水泥5G智能制造工厂数字孪生可视化平台,推进水泥行业数字化转型
水泥5G智能制造工厂数字孪生可视化平台,推进水泥行业数字化转型。水泥5G智能制造工厂数字孪生可视化平台,是水泥行业数字化转型的关键推手。数字孪生平台运用先进的信息技术和数字化手段,实现水泥生产过程的数字化模拟、可视化监控和智能化管…...
vue 一个简单实例化Vue.js 是一个流行的前端框架,如何创建一个基本的计数器应用
当然可以!Vue.js 是一个流行的前端框架,用于构建用户界面。下面是一个简单的 Vue.js 例子,演示了如何创建一个基本的计数器应用。 首先,确保你已经在项目中引入了 Vue.js。你可以通过 CDN 引入 Vue.js,或者在项目中安…...
1.k8s架构
k8s集群架构 一个Kubernetes集群至少包含一个控制平面(control plane),以及一个或多个工作节点(worker node)。控制平面(Control Plane) : 控制平面负责管理工作节点和维护集群状态。所有任务分配都来自于控制平面。工作节点(Worker Node) : 工作节点负责执行由控制…...
【Linux】详解动态库链接和加载对可执行程序底层的理解
一、动静态库链接的几种情况 如果我们同时提供动态库和静态库,gcc默认使用的是动态库。如果我们非要使用静态库,要加-static选项。如果我们只提供静态库,那可执行程序没办法,只能对该库进行静态链接,但程序不一定整体…...
中文Mistral模型介绍(Chinese-Mistral)——中文大语言模型
中文Mistral简介 Chinese-Mistral由清华大学地学系地球空间信息科学实验室开发。 该模型基于Mistral发布的Mistral-7B-v0.1训练得到。首先进行中文词表扩充,然后采用实验室提出的PREPARED训练框架(under review)在中英双语语料上进行增量预训…...
yolo v5 中 letterbox对不规则矩形框的输入调整
在对数据或特征的处理中,为了避免输入图像或特征,经过resize等等操作,改变了目标特征的尺度信息,一般会引入一些操作,比如: 在特征维度,加入SPP(空间金字塔池化)&#x…...
STL是什么?如何理解STL?
文章目录 1. 什么是STL2. STL的版本3. STL的六大组件4. 如何学习STL5.STL的缺陷 1. 什么是STL STL(standard template libaray-标准模板库):是C标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。 2. …...
【Spring篇】Spring IoC DI
个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【Spring系列】 本专栏旨在分享学习Spring MVC的一点学习心得,欢迎大家在评论区交流讨论💌 目录 前言一、IoC二、…...
Python语言例题集(010)
#!/usr/bin/python3 #在链表的末端插入新的节点。 class Node(): def init(self,dataNone): self.datadata self.nextNone class LinkedList(): def init(self): self.headNone def printList(self):ptrself.headwhile ptr:print(ptr.data)ptrptr.nextdef ending(self,newd…...
redis---主从复制
主从复制是指将一台redis服务器的数据复制到其他redis服务器,也叫主节点和从节点。 一个主节点可以有多个从节点。而每个从节点只能有一个主节点。数据的复制是单向的,只能由主节点到从节点。一般来说,主节点负责写操作,从节点负…...
双线主机可以做彩票网站吗/网站优化包括对什么优化
64位windows安装storm前需要先搞定zookeeper和python,所以下面我们3步走: 一、zookeeper 1、上https://zookeeper.apache.org/点击下方download到新页面,还得点一次中间的download,再选一个镜像链接http://mirrors.tuna.tsinghua.…...
网站建设活动/seo外包 杭州
操作系统复习一,单项选择题1.在下列性质中,()不是分时系统的特征。a. 多路性b. 交互性c. 独占性d.成批性2.分时系统的响应与下列哪一个因素无关。()a. 时间片长短b. 系统时钟的频率c. 终端用户数d.主存和外存之间的信息交换量3. 所谓临界区是指()。a. 一个缓冲区b. …...
驻马店市网站建设/北京推广
ImageCaptureCore 浏览媒体设备并通过您的应用以编程方式对其进行控制。 使用教程 使用ImageCaptureCore,您的应用程序可以: 发现连接的相机和扫描仪查看和修改已连接相机上的文件夹,文件和元数据使用系留拍摄直接在连接的相机上拍摄照片执行…...
深圳电商网络网站建设/今日热点头条
文章目录码云镜像下载darknet_ros包下载权重文件编译修改话题寻找:修改:修改使用的yolo识别路障等物体码云镜像下载darknet_ros包 请不要直接克隆,请git clone --recursive 用于循环克隆git子项目,否则克隆的包不完整 cd qianRu…...
国外网站网页设计/网络推广竞价外包
UPS不间断电源的通信接口越来越多,而且因为 UPS非常易于扩展的特性,使用通信口的智能设备越来越多,成为一种潮流和趋势。UPS电源是机房设备中是非常重要的一个成员,其因它的电路简单,可靠性以及效率高,过载…...
502 bad gateway wordpress/国外免费网站服务器
实际开发中,捕获多个异常的方式,如下:#codingutf-8try:print(-----test--1---)open(123.txt,r) # 如果123.txt文件不存在,那么会产生 IOError 异常print(-----test--2---)print(num)# 如果num变量没有定义,那么会产生 …...