js jquery写一个画板 实现撤回、清空、换色的功能

news2024/11/25 2:26:53

画布的canvas画板的大小就是这个画板图片的大小

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no,initial-scale=1.0, maximum-scale=1.0, mininum-scale=1.0"
    />
    <link rel="stylesheet" href="../css/common.css" />
    <link rel="stylesheet" href="../css/animate.min.css" />
    <title>page4</title>
  </head>
  <body>
    <style>
      body {
        margin: 0;
        padding: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
      }
      #box {
        position: relative;
        width: calc(100vh * 16 / 9);
        height: 100vh;
        max-height: 100%;
        /* background-color: #ccc; */
        display: flex;
        justify-content: center;
        align-items: center;
        text-align: center;
        font-size: 24px;
        background: url("../images/page4Bg.png");
        background-size: contain;
      }
      .btn {
        transition: transform 0.1s;
      }
      .btn:hover {
        transform: scale(1.1);
      }
      img {
        position: absolute;
        /* cursor: pointer; */
      }
      .hei {
        position: fixed;
        z-index: 999;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgb(0, 0, 0);
      }
      .color_btn_selected {
        border: 2px solid blueviolet;
        box-sizing: border-box;
        border-radius: 50%;
      }
    </style>
    <!-- 黑幕 -->
    <div class="hei"></div>
    <div id="box">
      <!-- 返回 -->
      <img
        onclick="ret()"
        class="btn"
        style="width: 4.5%; top: 3%; left: 3%;cursor: pointer;"
        src="../images/fanhui@2x.png"
        alt=""
      />
      <!-- 重玩 -->
      <img
        id="clear_btn"
        class="op_btn btn chongwan"
        style="width: 9.5%; bottom: 3%; right: 38.5%;cursor: pointer;"
        src="../images/cwBtn.png "
        alt=""
      />
      <!-- 语音 -->
      <img
        class="btn yuyin"
        onclick="playMp3()"
        style="width: 9.5%; bottom: 3%; right: 28%;cursor: pointer;"
        src="../images/yuyin@2x.png"
        alt=""
      />
      <!-- 上一页 -->
      <img
        class="btn shangyiye"
        onclick="pre()"
        style="width: 12%; bottom: 3%; right: 15%;cursor: pointer;"
        src="../images/syy.png"
        alt=""
      />
      <!-- 下一页 -->
      <img
        class="btn xiayiye"
        onclick="next()"
        style="width: 12%; bottom: 3%; right: 2%;cursor: pointer;"
        src="../images/nextPage.png"
        alt=""
      />
      <!-- 背景 -->
      <img
        style="width: 80%; top: 50%; left: 50%;transform: translate(-50%,-55%);"
        src="../images/hb_bg.png"
        alt=""
      />
      <!-- 画板 -->
      <img
        class="hb"
        style="width: 32%;
        top: 28%;
        left: 18%;"
        src="../images/hb_img.png"
        alt=""
      />
      <!-- 撤销 -->
      <img
        id="cx_btn"
        class="op_btn btn"
        style="width: 9%;
        top: 68%;
        left: 41%;cursor: pointer;"
        src="../images/hb_cx.png"
        alt=""
      />
      <!-- 颜色 -->
      <img
        id="black_btn"
        class="color_btn color_btn_selected"
        itemColor="#000000"
        style="width: 2.5%;
        top: 68.6%;
        left: 18%;cursor: pointer;"
        src="../images/hb_hei.png"
        alt=""
      />
      <img
        id="red_btn"
        class="color_btn"
        itemColor="#ff5656"
        style="width: 2.5%;
                top: 68.6%;
                left: 21.7%;cursor: pointer;"
        src="../images/hb_red.png"
        alt=""
      />
      <img
        id="yellow_btn"
        class="color_btn"
        itemColor="#ffbe21"
        style="width: 2.5%;
              top: 68.6%;
              left: 25.4%;cursor: pointer;"
        src="../images/hb_h.png"
        alt=""
      />
      <img
        id="green_btn"
        class="color_btn"
        itemColor="#6ad226"
        style="width: 2.5%;
              top: 68.6%;
              left: 29.1%;cursor: pointer;"
        src="../images/hb_lv.png"
        alt=""
      />
      <img
        id="blue_btn"
        class="color_btn"
        itemColor="#5da1ff"
        style="width: 2.5%;
               top: 68.6%;
               left: 32.8%;cursor: pointer;"
        src="../images/hb_l.png"
        alt=""
      />
      <img
        id="purple_btn"
        class="color_btn"
        itemColor="#e56dff"
        style="width: 2.5%;
        top: 68.6%;
        left: 36.5%;cursor: pointer;"
        src="../images/hb_z.png"
        alt=""
      />
      <canvas
        id="canvas"
        style="position: absolute;
        z-index: 999;
        top: 28%;
        left: 18%;
        /* border: 1px solid red; */
        border-radius: 25px;
        width: 377px;
        height: 252px;"
      ></canvas>
    </div>
    <script src="../js/jquery-1.12.3.js"></script>
    <!-- <script type="text/javascript" src="../js/handingWrite.js"></script> -->
    <script>
      function resizeBox() {
        var box = document.getElementById("box");
        var width = window.innerWidth; // 获取窗口宽度
        var height = window.innerHeight; // 获取窗口高度
        // 计算盒子的高度
        var boxHeight = Math.min(height, (width / 16) * 9); // 高度最多为100%
        // 设置盒子的样式
        box.style.height = boxHeight + "px";
      }
      // 初始化时调整盒子大小
      resizeBox();
      // 监听窗口大小改变事件
      window.addEventListener("resize", function () {
        resizeBox();
      });
    </script>
    <script>
      function pre() {
        new Audio("../mp3/pages.mp3").play();
        $(".hei").fadeIn(500); // 2000毫秒为过渡效果持续时间
        setTimeout(() => {
          window.location.href = "./page3.html";
        }, 500);
      }
    </script>
    <script>
      var playing = false;
      var audio = null;
      function playMp3() {
        if (playing) {
          return; // 如果正在播放,不执行后续操作
        }
        playing = true; // 设置为正在播放状态
        if (audio) {
          audio.pause(); // 停止当前音频的播放
        }
        audio = new Audio("../mp3/P4-1.mp3");
        audio.addEventListener("ended", function () {
          playing = false; // 播放结束后设置为非播放状态
        });
        audio.play();
      }
    </script>
    <!-- 设置页面所欲图片禁止拖拽 -->
    <script>
      var images = document.querySelectorAll("img"); // 获取所有图片元素
      for (var i = 0; i < images.length; i++) {
        images[i].draggable = false; // 将draggable属性设置为false
      }
    </script>
    <script>
      // 语音按钮
      const imgElement = document.querySelector(".btn.yuyin");
      imgElement.addEventListener("mousedown", function (event) {
        // 更改图片元素的src属性
        imgElement.src = "../images/axyy.png";
      });
      imgElement.addEventListener("mouseup", function (event) {
        imgElement.src = "../images/yuyin@2x.png";
      });
      imgElement.addEventListener("mouseleave", function (event) {
        imgElement.src = "../images/yuyin@2x.png";
      });

      // 上一页按钮
      const imgElement2 = document.querySelector(".btn.shangyiye");
      imgElement2.addEventListener("mousedown", function (event) {
        // 更改图片元素的src属性
        imgElement2.src = "../images/As.png";
      });
      imgElement2.addEventListener("mouseup", function (event) {
        imgElement2.src = "../images/syy.png";
      });
      imgElement2.addEventListener("mouseleave", function (event) {
        imgElement2.src = "../images/syy.png";
      });

      // 下一页按钮
      const imgElement3 = document.querySelector(".btn.xiayiye");
      imgElement3.addEventListener("mousedown", function (event) {
        // 更改图片元素的src属性
        imgElement3.src = "../images/Ax.png";
      });
      imgElement3.addEventListener("mouseup", function (event) {
        imgElement3.src = "../images/nextPage.png";
      });
      imgElement3.addEventListener("mouseleave", function (event) {
        imgElement3.src = "../images/nextPage.png";
      });

      // 重玩按钮
      const imgElement4 = document.querySelector('.btn.chongwan');
      imgElement4.addEventListener('mousedown', function(event) {
        // 更改图片元素的src属性
        imgElement4.src = '../images/axcw.png';
      });
      imgElement4.addEventListener('mouseup', function(event) {
        imgElement4.src = '../images/cwBtn.png';
      });
      imgElement3.addEventListener('mouseleave', function(event) {
        imgElement4.src = '../images/cwBtn.png';
      });

      $("#clear_btn").mousedown(function (event) {
        // 更改图片元素的src属性
        $(this).attr("src", "../images/axcw.png");
      });

      $("#clear_btn").mouseup(function (event) {
        $(this).attr("src", "../images/cwBtn.png");
      });

      $("#clear_btn").mouseleave(function (event) {
        $(this).attr("src", "../images/cwBtn.png");
      });
    </script>
    <script>
      // 在页面加载完成后执行
      $(document).ready(function () {
        // 设置一个延时,以便看到渐变过渡效果
        setTimeout(function () {
          $(".hei").fadeOut(500, function () {
            // 渐变过渡结束后隐藏盒子
            $(this).hide();
          });
        }, 0);
      });
    </script>
    <script>
      function next() {
        new Audio("../mp3/pages.mp3").play();
        $(".hei").fadeIn(500); // 2000毫秒为过渡效果持续时间
        setTimeout(() => {
          window.location.href = "./page5.html";
        }, 500);
      }
    </script>
    <!-- 返回列表 -->
    <script>
      function ret() {
        $(".hei").fadeIn(500); // 2000毫秒为过渡效果持续时间
        setTimeout(() => {
          window.location.href = "../../../../../page2.html";
        }, 500);
      }
    </script>
    <!-- 画板 -->
    <script>
      var canvas = document.getElementById("canvas");
      var canvasWidth = document.querySelector(".hb").offsetWidth;
      var canvasHeight = document.querySelector(".hb").offsetHeight;
      var cxt = canvas.getContext("2d");
      canvas.width = canvasWidth;
      canvas.height = canvasHeight;
      $("#canvas").css("width", canvasWidth + "px")
      $("#canvas").css("height", canvasHeight + "px")
      var isMouseDown = false;
      var lastLoc = { x: 0, y: 0 }; //起笔坐标
      var lastTime = 0; //用于计算时间
      var lastLineWidth = -1;
      var lineColor = "#000000";
      paths = []; // 存储绘制的路径
      colors = []; // 存储绘制的颜色
      drawGrid(cxt);
      // 鼠标按下
      function beginStroke(point) {
      	isMouseDown = true;
      	lastLoc = windowToCanvas(point.x, point.y);
      	lastTime = new Date().getTime();
      	paths.push([]); // 创建新的路径数组
      	paths[paths.length - 1].push(lastLoc); // 将起点坐标加入当前路径
      	colors.push(lineColor); // 存储绘制的颜色
      }
      // 鼠标结束
      function endStroke() {
        console.log("color",lineColor);
      	isMouseDown = false;
      }
      // 鼠标移动
      function moveStroke(point) {
      	var curLoc = windowToCanvas(point.x, point.y);
      	var curTime = new Date().getTime();
      	var s = calcDistance(curLoc, lastLoc); // 获取笔锋经过的距离
      	var t = curTime - lastTime; // 获取笔锋经过的时间 ,用于计算行笔速度,赋值不同的宽度
      	var lineWidth = calcLineWidth(t, s);
      	cxt.beginPath();
      	cxt.moveTo(lastLoc.x, lastLoc.y);
      	cxt.lineTo(curLoc.x, curLoc.y);
      	cxt.strokeStyle = lineColor;
      	cxt.lineWidth = lineWidth;
      	cxt.lineCap = "round";
      	cxt.lineJoin = "round";
      	cxt.stroke();
      	cxt.closePath();
      	lastLoc = curLoc;
      	lastTime = curTime;
      	lastLineWidth = lineWidth;
      	paths[paths.length - 1].push(curLoc); // 将当前点加入当前路径
      }
      canvas.onmousedown = function (e) {
      	e.preventDefault();
      	beginStroke({ x: e.clientX, y: e.clientY });
      };
      canvas.onmouseup = function (e) {
      	endStroke();
      	e.preventDefault();
      };
      canvas.onmouseout = function (e) {
      	endStroke();
      	e.preventDefault();
      };
      canvas.onmousemove = function (e) {
      	e.preventDefault();
      	if (isMouseDown) {
      		moveStroke({ x: e.clientX, y: e.clientY });
      	}
      };
      // 触屏事件
      canvas.addEventListener("touchstart", function (e) {
      	e.preventDefault();
      	var touch = e.touches[0];
      	beginStroke({ x: touch.pageX, y: touch.pageY });
      });
      canvas.addEventListener("touchmove", function (e) {
      	e.preventDefault();
      	if (isMouseDown) {
      		var touch = e.touches[0];
      		moveStroke({ x: touch.pageX, y: touch.pageY });
      	}
      });
      canvas.addEventListener("touchend", function (e) {
      	e.preventDefault();
      	endStroke();
      });
      // }
      var maxLineWidth = 10;
      var minLineWidth = 10;
      var maxStrokeV = 10;
      var minStrokeV = 0.1;
      function calcLineWidth(t, s) {
      	// 计算运笔速度和时间,获取不同得到宽度
      	var resultLineWidth = 0;
      	var v = s / t;
      	if (v <= minStrokeV) {
      		resultLineWidth = maxLineWidth;
      	} else if (v >= maxStrokeV) {
      		resultLineWidth = minLineWidth;
      	} else {
      		resultLineWidth =
      			maxLineWidth -
      			((v - minStrokeV) / (maxStrokeV - minStrokeV)) *
      			(maxLineWidth - minLineWidth);
      	}
      	if ((lastLineWidth == -1)) {
      		return resultLineWidth;
      	}
      	return (lastLineWidth * 2) / 3 + (resultLineWidth * 1) / 3;
      }
      function calcDistance(loc1, loc2) {
      	return Math.sqrt(
      		(loc1.x - loc2.x) * (loc1.x - loc2.x) +
      		(loc1.y - loc2.y) * (loc1.y - loc2.y)
      	);
      }
      function windowToCanvas(x, y) {
      	var box = canvas.getBoundingClientRect();
      	return { x: x - box.left, y: y - box.top };
      }
      function drawGrid(cxt) {
      	cxt.save();
      	cxt.beginPath();
      	// cxt.moveTo(3, 3);
      	// cxt.lineTo(canvas.width - 3, 3);
      	// cxt.lineTo(canvas.width - 3, canvas.height - 3);
      	// cxt.lineTo(3, canvas.height - 3);
      	// cxt.lineTo(3, 3);
      	// cxt.lineWidth = 6;
      	// cxt.strokeStyle = "red";
      	// cxt.closePath();
      	// cxt.stroke();
      	// cxt.restore();
      	// cxt.save();
      	// cxt.beginPath();
      	// cxt.moveTo(3, 3);
      	// cxt.lineTo(canvas.width, canvas.height);
      	// cxt.moveTo(canvas.width, 3);
      	// cxt.lineTo(3, canvas.height);
      	// cxt.moveTo(canvas.width / 2, 3);
      	// cxt.lineTo(canvas.width / 2, canvas.height);
      	// cxt.moveTo(3, canvas.height / 2);
      	// cxt.lineTo(canvas.width, canvas.height / 2);
      	// cxt.strokeStyle = "red";
      	cxt.lineWidth = 1;
      	cxt.stroke();
      	cxt.closePath();
      	cxt.restore();
      }
      // 撤回
      $("#cx_btn").click(function (e) {
      	if (paths.length > 0) {
      		paths.pop(); // 删除最后一个路径
      		colors.pop(); // 删除最后一个颜色
      		cxt.clearRect(0, 0, canvas.width, canvas.height);
      		drawGrid(cxt);
      		// 重新绘制剩余的路径
      		for (var i = 0; i < paths.length; i++) {
      			var path = paths[i];
      			for (var j = 0; j < path.length - 1; j++) {
      				cxt.beginPath();
      				cxt.moveTo(path[j].x, path[j].y);
      				cxt.lineTo(path[j + 1].x, path[j + 1].y);
      				cxt.strokeStyle = colors[i];
      				cxt.lineWidth = lastLineWidth;
      				cxt.lineCap = "round";
      				cxt.lineJoin = "round";
      				cxt.stroke();
      				cxt.closePath();
      			}
      		}
      	}
      });
      // 清除
      $("#clear_btn").click(function (e) {
        paths = []; // 清空绘制的路径
        colors = []; // 清空绘制的颜色
      	cxt.clearRect(0, 0, canvas.width, canvas.height);
      	drawGrid(cxt);
      })
      // 换颜色
      $(".color_btn").click(function () {
      	if (!$(this).hasClass("color_btn_selected")) {
      		$(this).addClass("color_btn_selected").siblings().removeClass("color_btn_selected");
      	}
      	lineColor = $(this).attr("itemColor");
      })
    </script>
  </body>
</html>

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

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

相关文章

鸿蒙剥离 AOSP 不兼容 Android 热门问题汇总,不吹不黑不吵

上周发了一篇 《鸿蒙终于不套壳了&#xff1f;纯血 HarmonyOS NEXT 即将到来》的相关资讯&#xff0c;没想到大家「讨&#xff08;fa&#xff09;论&#xff08;xie&#xff09;」的热情很高&#xff0c;莫名蹭了一波流量&#xff0c;虽然流量对我来说也没什么用&#xff0c;但…

HOT82-杨辉三角

leetcode原题链接&#xff1a;杨辉三角 题目描述 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例…

python什么版本比较稳定,python哪个版本用得最多

这篇文章主要介绍了哪个版本的python最好用&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 想学习Python的人都会有一个困惑&#xff0c;那就是Python目前有两个版本Python2和…

windows下dll文件的创建详细教程

1、前言 dll文件是啥&#xff0c;就不作过多赘述了。现在直接教大家如何创建与使用dll文件。 本文基于windows系统&#xff0c;使用的编译相关工具为visual studio 2019。 2、创建dll 2.1 创建dll工程 首先打开visual studio&#xff0c;然后选择创建新项目&#xff0c;在搜…

11、Nvidia显卡驱动、CUDA、cuDNN、Anaconda及Tensorflow Pytorch版本

Nvidia显卡驱动、CUDA、cuDNN、Anaconda及Tensorflow-GPU版本 一、确定版本关系二、安装过程1.安装显卡驱动2、安装CUDA3、安装cudnn4、安装TensorFlow5、安装pytorch 三、卸载 一、确定版本关系 TensorFlow Pytorch推出cuda和cudnn的版本&#xff0c;cuda版本推出驱动可选版本…

【软件测试】Linux环境下Docker搭建+Docker搭建MySQL服务(详细)

目录&#xff1a;导读 前言 一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 Linux之docker搭…

PyTorch深度学习实战(11)——卷积神经网络

PyTorch深度学习实战&#xff08;11&#xff09;——卷积神经网络 0. 前言1. 全连接网络的缺陷2. 卷积神经网络基本组件2.1 卷积2.2 步幅和填充2.3 池化2.3 卷积神经网络完整流程 3. 卷积和池化相比全连接网络的优势4. 使用 PyTorch 构建卷积神经网络4.1 使用 PyTorch 构建 CNN…

python中yield关键字

yield和return 理解一个东西最好的办法就是找一个和它类似的东西&#xff0c;然后再搞清楚它们之间的区别。 yield最类似的东西就是return&#xff0c;因为他们起到了同样的作用&#xff1a;返回值。 看这个return的函数&#xff1a; def have_some_wine():print(先开一瓶酒&a…

【云驻共创】华为云之手把手教你搭建IoT物联网应用充电桩实时监控大屏

文章目录 前言1.什么是充电桩2.什么是IOT3.什么是端、边、云、应用协同4.什么是Astro轻应用 一、玩转lOT动态实时大屏&#xff08;线下实际操作&#xff09;1.Astro轻应用说明1.1 场景说明1.2 资费说明1.3 整体流程 2.操作步骤2.1 开通设备接入服务2.2 创建产品2.3 注册设备2.4…

OpenCV图像处理——几何变换

目录 图像缩放图像平移图像旋转图像的仿射变换透射变换图像金字塔 图像缩放 cv.resize(src,dsize,fx0,fy0,interpolationcv2.INTER_LINEAR)import numpy as np import cv2 as cv import matplotlib.pyplot as pltkidscv.imread(./汪学长的随堂资料/4/图像操作/dog.jpg) plt.im…

微信小游戏中的迷宫算法:解密小游戏背后的智慧

引言 随着科技的发展&#xff0c;微信小游戏成为人们休闲娱乐的新选择。其中一些小游戏不仅仅是简单的娱乐&#xff0c;还融入了复杂的算法&#xff0c;如迷宫算法&#xff0c;为玩家带来了更多的挑战和乐趣。本文将带您深入了解什么是迷宫算法&#xff0c;以及如何在微信小游…

MySQL数据库——概述-MySQL的安装、启动与停止和客户端连接、关系型数据库(RDBMS)、数据模型

目录 概述&#xff08;1/2&#xff09; MySQL安装 MySQL启动与停止 客户端连接 概述&#xff08;2/2&#xff09; 关系型数据库&#xff08;RDBMS&#xff09; 数据模型 概述&#xff08;1/2&#xff09; 名称全称简称数据库存储数据的仓库&#xff0c;数据是有组织的进…

C# 一种求平方根的方法 立方根也可以 极大 极小都可以

不知道研究这些干啥&#xff0c;纯纯的浪费时间。。。 public static double TQSquare(double number){Random random1 new Random(DateTime.Now.Millisecond);double x1 0, resultX1 0, diff 9999999999, diffTemporary 0;for (int i 0; i < 654321; i){if (random1…

高赞:为什么别选计算机专业?

在知乎看到一个这样的问题&#xff1a;“为什么别选计算机专业&#xff1f;” 这个话题有 800 万人次浏览。以下是一位匿名用户的高赞回答&#xff0c;内容可能比较主观化&#xff0c;仅代表原作者个人观点。如果有不同意见欢迎留言区交流啊&#xff01; 不明白现在鼓吹计算机…

最强自动化测试框架Playwright(25)-浏览器

Browser | Playwright Python 方法 创建page页面 from playwright.sync_api import sync_playwrightdef run(playwright):firefox playwright.firefoxbrowser firefox.launch()page browser.new_page()page.goto("https://example.com")browser.close()with sy…

Android学习之路(4) UI控件之输入框

本节引言&#xff1a; 在本节中&#xff0c;我们来学习第二个很常用的控件EditText(输入框)&#xff1b; 和TextView非常类似&#xff0c;最大的区别是&#xff1a;EditText可以接受用户输入&#xff01; 1.设置默认提示文本 如下图&#xff0c;相信你对于这种用户登录的界面并…

【考研数学】概率论与梳理统计 | 第一章——随机事件与概率(1)

文章目录 一、随机试验与随机事件1.1 随机试验1.2 样本空间1.3 随机事件 二、事件的运算与关系2.1 事件的运算2.2 事件的关系2.3 事件运算的性质 三、概率的公理化定义与概率的基本性质3.1 概率的公理化定义3.2 概率的基本性质 写在最后 一、随机试验与随机事件 1.1 随机试验 …

ESG评级能否促进企业绿色转型(2009-2021年)

参照胡洁&#xff08;2023&#xff09;的做法&#xff0c;对来自数量经济技术经济研究《ESG评级能否促进企业绿色转型—基于多时点双重差分法的验证》一文中的基准回归部分进行复刻。 本文从非正式环境规制视角出发&#xff0c;基于商道融绿首次公布上市公司 ESG 评级的外生冲…

路径规划 | 详解维诺图Voronoi算法(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 维诺图规划原理2 ROS C实现(栅格图搜索)3 Python实现(路图搜索)4 Matlab实现(路图搜索) 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细介绍全局规划(图搜索、采样法、智能算法等)&#…

validation之自定义注解@Constraint

前言&#xff1a; 首先&#xff0c;接口参数校验应该都不陌生&#xff0c;大部分应该都会借助javax.validation进行快捷校验&#xff0c;一般都是在入参字段上添加NotNull、NotEmpty等&#xff0c;对于一些特殊的入参校验逻辑&#xff0c;可能不是很适用&#xff0c;现在介绍一…