Cesium 常用标绘线、面、矩形、圆、曲面、曲线、攻击箭头、钳击箭头,标绘与修改。

news2024/9/21 9:26:24

前言:直接放效果图,符合就往下看,不符合出门右转。

在这里插入图片描述

由于篇幅有限,只贴出各个标绘的关键代码。

1、线段

  • 基于坐标点,加载不同的材质。
//动态加载
const entity = this._viewer.entities.add({
   polyline: {
       positions: new CallbackProperty(() => {
           return this._positions;
       }, false),
       show: true,
       material: Color.RED,
       width: 3,
       clampToGround: true //是否贴地
   }
});

//静态
 const primitive = scene.groundPrimitives.add(
 new GroundPolylinePrimitive({
         geometryInstances: new GeometryInstance({
             geometry: new GroundPolylineGeometry({
                 positions: line,
                 width: this._width,
             }),
             id: this.id
         }),
         appearance: new PolylineMaterialAppearance({
             material:
                 Material.fromType("Image", {
                     image: this._imageUrl,
                     repeat: this._repeat
                 })
         }),
     })
 );

2、多边形

  • 基于做坐标点,加载不同的材质
//动态
const entity = this._viewer.entities.add({
     polygon: {
         hierarchy: new CallbackProperty(() => {
             return new PolygonHierarchy(this._positions)
         }, false),
         show: true,
         fill: true,
         material: Color.RED.withAlpha(0.5),
         //@ts-ignore
         clampToGround: true,
         width: 3,
         outlineColor: Color.BLACK,
         outlineWidth: 1,
         outline: true
     }
 });
//静态
const  primite = scene.groundPrimitives.add(
  new GroundPrimitive({
        geometryInstances: new GeometryInstance({
            id: this._id,
            geometry: new PolygonGeometry({
                polygonHierarchy: {
                    positions: positions,
                    holes: []
                },
            }),
        }),
        appearance: new EllipsoidSurfaceAppearance({
            material: Material.fromType("Grid", this._grid)
        }),
        classificationType: ClassificationType.TERRAIN,
    })
)

3、绘制直线箭头

  • 根据箭头算法,提供两个点的坐标
//动态
const arrowEntity = this._viewer.entities.add({
   polygon: {
       hierarchy: new CallbackProperty(() => {
           const length = this._positions.length;
           const p1 = this._positions[0];
           const p2 = this._positions[length - 1];
           const firstPoint = this.cartesianToLatlng(p1);
           const endPoints = this.cartesianToLatlng(p2);
           let arrow = [];
           let res = this.fineArrow([firstPoint[0], firstPoint[1]], [endPoints[0], endPoints[1]]);
           if (res) {
               for (let i = 0; i < res.length; i++) {
                   let cart3 = new Cartesian3(res[i].x, res[i].y, res[i].z);
                   arrow.push(cart3);
               }
               return new PolygonHierarchy(arrow);
           }
       }, false),
       show: true,
       fill: true,
       material: Color.RED.withAlpha(0.5)
   }
})
  • 箭头算法
/**
 * 
 * @param t 二维坐标
 * @param o 二维坐标
 * @returns 两点之间的距离
 */
export function distance(t: number[], o: number[]) {
  return Math.sqrt(Math.pow(t[0] - o[0], 2) + Math.pow(t[1] - o[1], 2));
}
/**
 * 
 * @param positionArr 点坐标数组
 * @returns 距离
 */
export function wholeDistance(positionArr: number[][]) {
  let dis = 0;
  const length = positionArr.length - 1;
  for (let i = 0; i < length; i++) {
    dis += distance(positionArr[i], positionArr[i + 1]);
  }
  return dis;
}
export function getBaseLength(positionArr: number[][]) {
  return Math.pow(wholeDistance(positionArr), 0.99);
}

/**
 * 
 * @param t 
 * @param o 
 * @param e 
 * @param r 
 * @param n 
 * @returns 获取第三个点的坐标 
 */
export function getThirdPoint(
  t: number[],
  o: number[],
  e: number,
  r: number,
  n: boolean = false
) {
  let g = getAzimuth(t, o),
    i = n ? g + e : g - e,
    s = r * Math.cos(i),
    a = r * Math.sin(i);
  return [o[0] + s, o[1] + a];
}
/**
 * 
 * @param t 
 * @param o 
 * @returns 获取方位角
 */
export function getAzimuth(t: number[], o: number[]): number {
  let e = 0,
    r = Math.asin(Math.abs(o[1] - t[1]) / distance(t, o));
  o[1] >= t[1] && o[0] >= t[0]
    ? (e = r + Math.PI)
    : o[1] >= t[1] && o[0] < t[0]
      ? (e = 2 * Math.PI - r)
      : o[1] < t[1] && o[0] < t[0]
        ? (e = r)
        : o[1] < t[1] && o[0] >= t[0]
          ? (e = Math.PI - r)
          : 0;
  return e;
}
fineArrowDefualParam() {
   return {
       tailWidthFactor: 0.15,
       neckWidthFactor: 0.2,
       headWidthFactor: 0.25,
       headAngle: Math['PI'] / 8.5,
       neckAngle: Math['PI'] / 0xd
   };
}
fineArrow(po1: number[], po2: number[]) {
    if ((po1.length < 2) || (po2.length < 2)) return;
    //画箭头的函数
    let tailWidthFactor = this.fineArrowDefualParam().tailWidthFactor;
    let neckWidthFactor = this.fineArrowDefualParam().neckWidthFactor;
    let headWidthFactor = this.fineArrowDefualParam().headWidthFactor;
    let headAngle = this.fineArrowDefualParam().headAngle;
    let neckAngle = this.fineArrowDefualParam().neckAngle;
    let o = [];
    o[0] = po1;
    o[1] = po2;
    var e = o[0],
        r = o[1],
        n = getBaseLength(o),
        g = n * tailWidthFactor,
        //尾部宽度因子
        i = n * neckWidthFactor,
        //脖子宽度银子
        s = n * headWidthFactor,
        //头部宽度因子
        a = getThirdPoint(r, e, Math.PI / 2, g, !0),
        l = getThirdPoint(r, e, Math.PI / 2, g, !1),
        u = getThirdPoint(e, r, headAngle, s, !1),
        c = getThirdPoint(e, r, headAngle, s, !0),
        p = getThirdPoint(e, r, neckAngle, i, !1),
        h = getThirdPoint(e, r, neckAngle, i, !0),
        d = [];
    d.push(a[0], a[1], p[0], p[1], u[0], u[1], r[0], r[1], c[0], c[1], h[0], h[1], l[0], l[1], e[0], e[1]);
    return Cartesian3.fromDegreesArray(d)
}

4、攻击箭头

  • 提供坐标点 绘制攻击箭头也叫燕尾箭头
import initXp from 'algorithm.js'
//动态
const xp = initXp()
const update = () => {
     //计算面
     if (positions.length < 3) {
         return null;
     }
     let lnglatArr = [], lnglat;
     for (var i = 0; i < positions.length; i++) {
         lnglat = this.cartesianToLatlng(positions[i]);
         lnglatArr.push(lnglat)
     }
     const res = xp.algorithm.tailedAttackArrow(lnglatArr);
     const returnData = res.polygonalPoint;
     return new PolygonHierarchy(returnData);
 }
this._viewer.entities.add({
  polygon: new PolygonGraphics({
       hierarchy: new CallbackProperty(update, false),
       show: true,
       fill: true,
       material: this.fillMaterial
   })
});

function cartesianToLatlng(position: Cartesian3) {
   const latlng =
       this._viewer.scene.globe.ellipsoid.cartesianToCartographic(position);
   const lat = CesiumMath.toDegrees(latlng.latitude);
   const lng = CesiumMath.toDegrees(latlng.longitude);
   return [lng, lat];
}

5、钳击箭头

  • 一共需要提供五个点
 const update = () => {
  //计算面
    if (positions.length < 3) {
        return null;
    }
    var lnglatArr = [];
    for (var i = 0; i < positions.length; i++) {
        var lnglat = this.cartesianToLatlng(positions[i]);
        lnglatArr.push(lnglat)
    }
    const xp = initXp()
    let res = xp.algorithm.doubleArrow(lnglatArr);
    const returnData = res.polygonalPoint;
    return new PolygonHierarchy(returnData);
}
return this._viewer.entities.add({
    polygon: new PolygonGraphics({
        hierarchy: new CallbackProperty(update, false),
        show: true,
        fill: true,
        material: this.fillMaterial
    })
});

function cartesianToLatlng(position: Cartesian3) {
  const latlng =
      this._viewer.scene.globe.ellipsoid.cartesianToCartographic(position);
  const lat = CesiumMath.toDegrees(latlng.latitude);
  const lng = CesiumMath.toDegrees(latlng.longitude);
  return [lng, lat];
}

6、矩形

  • 提供两个点
import { point } from "@turf/helpers"
import rhumbBearing from "@turf/rhumb-bearing"
import distance from "@turf/distance"
import destination from "@turf/destination"
const entity = this._viewer.entities.add({
 polygon: {
      hierarchy: new CallbackProperty(() => {

          if (this._positions[0] && this._positions[1] && this._positions[2]) {
              const r0 = Cartographic.fromCartesian(this._positions[0])
              const r1 = Cartographic.fromCartesian(this._positions[1]) // 辅助点
              const r2 = Cartographic.fromCartesian(this._positions[2])

              const p0 = point([r0.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])
              const p1 = point([r1.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])
              const p2 = point([r2.longitude * 180 / Math.PI, r2.latitude * 180 / Math.PI])

              const bearing1 = rhumbBearing(p0, p1)
              const bearing2 = rhumbBearing(p0, p2)
              const angle1 = bearing2 - bearing1

              // 对角长度
              const length = distance(p0, p2, { units: 'miles' })

              const len1 = Math.cos(angle1 / 180 * Math.PI) * length
              const dest1 = destination(p0, len1, bearing1, { units: 'miles' })

              const angle2 = 90 - angle1
              const len2 = Math.cos(angle2 / 180 * Math.PI) * length
              const dest2 = destination(p0, len2, 90 + bearing1, { units: 'miles' })
              //@ts-ignore
              const coordinates = [this._positions[0], Cartesian3.fromDegrees(...dest1.geometry.coordinates), this._positions[2], Cartesian3.fromDegrees(...dest2.geometry.coordinates)]

              return new PolygonHierarchy(coordinates)
          }

      }, false),
      material: this._color
  },
})

7、绘制椭圆

  • 绘制椭圆需要两个点,注意长轴必须大于短轴,长短轴一致时为圆
import { point } from "@turf/helpers"
import distance from "@turf/distance"
const entity = this._viewer.entities.add({
  //@ts-ignore
    position: new CallbackProperty(() => {
        return this._positions[0]
    }, false),
    ellipse: {
        // 半短轴(画圆:半短轴和半长轴一致即可)
        semiMinorAxis: new CallbackProperty(() => {
            const r0 = Cartographic.fromCartesian(this._positions[0])
            const r1 = Cartographic.fromCartesian(this._positions[1])
            const p0 = point([r0.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])
            let p3 = point([r1.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])
            if (this._isEllipse) {
                let p1 = point([r1.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])
                let p2 = point([r0.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])
                let len1, len2
                len1 = distance(p0, p1, { units: 'kilometers' }) * 1000
                len2 = distance(p0, p2, { units: 'kilometers' }) * 1000
                return len1 < len2 ? len1 : len2
            } else return distance(p0, p3, { units: 'kilometers' }) * 1000
        }, false),
        // 半长轴
        semiMajorAxis: new CallbackProperty(() => {
            const r0 = Cartographic.fromCartesian(this._positions[0])
            const r1 = Cartographic.fromCartesian(this._positions[1])
            const p0 = point([r0.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])
            let p3 = point([r1.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])
            if (this._isEllipse) {
                let p1 = point([r1.longitude * 180 / Math.PI, r0.latitude * 180 / Math.PI])
                let p2 = point([r0.longitude * 180 / Math.PI, r1.latitude * 180 / Math.PI])
                let len1, len2
                len1 = distance(p0, p1, { units: 'kilometers' }) * 1000
                len2 = distance(p0, p2, { units: 'kilometers' }) * 1000
                return len1 > len2 ? len1 : len2
            } else return distance(p0, p3, { units: 'kilometers' }) * 1000
        }, false),
        // 填充色
        material: this._color,
    },
});

8、绘制曲线

  • 绘制曲线利用bezier算法
import { lineString, bezierSpline } from '@turf/turf'
const entity = this._viewer.entities.add({
   polyline: {
       positions: new CallbackProperty(() => {
           const lngLatPoints = this._positions.map(i => this.cartesianToLatlng(i))
           const pos = bezierSpline(lineString(lngLatPoints)).geometry.coordinates
           return Cartesian3.fromDegreesArray(pos.flat())
       }, false),
       show: true,
       material: Color.RED,
       width: 3,
       clampToGround: true //是否贴地
   }
});

9、绘制封闭曲面

  • 根据turf
 const entity = this._viewer.entities.add({
   polygon: {
         hierarchy: new CallbackProperty(() => {
             if (this._positions.length < 2) return []
             let pnts = []
             for (let p = 0; p < this._positions.length; p++) {
                 pnts.push(this.cartesianToLatlng(this._positions[p]))
             }
             pnts.push(pnts[0], pnts[1])
             let normals: number[][] = []
             let pList: Cartesian3[] = []
             for (let i = 0; i < pnts.length - 2; i++) {
                 let normalPoints = this.getBisectorNormals(this._t, pnts[i], pnts[i + 1], pnts[i + 2])
                 normals = normals.concat(normalPoints)
             }
             let count = normals.length
             normals = [normals[count - 1]].concat(normals.slice(0, count - 1))
             for (let i = 0; i < pnts.length - 2; i++) {
                 let pnt1 = pnts[i]
                 let pnt2 = pnts[i + 1]
                 pList.push(this.latlngTocartesian(pnt1))
                 for (let t = 0; t <= this._FITTING_COUNT; t++) {
                     let pnt = this.getCubicValue(t / this._FITTING_COUNT, pnt1, normals[i * 2], normals[i * 2 + 1], pnt2)
                     pList.push(this.latlngTocartesian(pnt))
                 }
                 pList.push(this.latlngTocartesian(pnt2))
             }
             return new PolygonHierarchy(pList)
         }, false),
         show: true,
         fill: true,
         material: Color.RED.withAlpha(0.5),
         //@ts-ignore
         clampToGround: true,
         width: 3,
         outlineColor: Color.BLACK,
         outlineWidth: 1,
         outline: true
     }
 });
 function getBisectorNormals(t: number, pnt1: number[], pnt2: number[], pnt3: number[]): number[][] {
        let normal = this.getNormal(pnt1, pnt2, pnt3)
        let bisectorNormalRight: number[] = []
        let bisectorNormalLeft: number[] = []
        let dt: number, x: number, y: number
        let dist = Math.sqrt(normal[0] * normal[0] + normal[1] * normal[1])
        let uX = normal[0] / dist
        let uY = normal[1] / dist
        let d1 = this.mathDistance(pnt1, pnt2)
        let d2 = this.mathDistance(pnt2, pnt3)

        if (dist > this._ZERO_TOLERANCE) {
            if (this.isClockWise(pnt1, pnt2, pnt3)) {
                dt = t * d1
                x = pnt2[0] - dt * uY
                y = pnt2[1] + dt * uX
                bisectorNormalRight = [x, y]
                dt = t * d2
                x = pnt2[0] + dt * uY
                y = pnt2[1] - dt * uX
                bisectorNormalLeft = [x, y]
            } else {
                dt = t * d1
                x = pnt2[0] + dt * uY
                y = pnt2[1] - dt * uX
                bisectorNormalRight = [x, y]
                dt = t * d2
                x = pnt2[0] - dt * uY
                y = pnt2[1] + dt * uX
                bisectorNormalLeft = [x, y]
            }
        } else {
            x = pnt2[0] + t * (pnt1[0] - pnt2[0])
            y = pnt2[1] + t * (pnt1[1] - pnt2[1])
            bisectorNormalRight = [x, y]
            x = pnt2[0] + t * (pnt3[0] - pnt2[0])
            y = pnt2[1] + t * (pnt3[1] - pnt2[1])
            bisectorNormalLeft = [x, y]
        }
        return [bisectorNormalRight, bisectorNormalLeft]
    }
     getNormal(pnt1: number[], pnt2: number[], pnt3: number[]) {
        let dX1 = pnt1[0] - pnt2[0]
        let dY1 = pnt1[1] - pnt2[1]
        let d1 = Math.sqrt(dX1 * dX1 + dY1 * dY1)
        dX1 /= d1
        dY1 /= d1
        let dX2 = pnt3[0] - pnt2[0]
        let dY2 = pnt3[1] - pnt2[1]
        let d2 = Math.sqrt(dX2 * dX2 + dY2 * dY2)
        dX2 /= d2
        dY2 /= d2
        let uX = dX1 + dX2
        let uY = dY1 + dY2
        return [uX, uY]
    }
    function mathDistance(pnt1: number[], pnt2: number[]) {
        return (Math.sqrt(Math.pow((pnt1[0] - pnt2[0]), 2) + Math.pow((pnt1[1] - pnt2[1]), 2)))
    }
    function isClockWise(pnt1: number[], pnt2: number[], pnt3: number[]) {
        return ((pnt3[1] - pnt1[1]) * (pnt2[0] - pnt1[0]) > (pnt2[1] - pnt1[1]) * (pnt3[0] - pnt1[0]))
    }
  • 雷达在我之前博客中

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

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

相关文章

K8S网络管理

这里写目录标题 1 网络管理1.1Service1.1.1 网络体系1.1.2 工作模型1.1.3 SVC实践1.1.4 IPVS实践 1.2 其他资源1.2.1 域名服务1.2.2 CoreDNS1.2.3 无头服务 1.3 flannel方案1.3.1 网络方案1.3.2 flannel1.3.3 主机网络 1 网络管理 1.1Service 1.1.1 网络体系 学习目标 这一…

Shell脚本 中运行sudo命令

在shell脚本中有时需要使用sudo进行提权&#xff0c;运行包含这类脚本的文件时通常需要我们在终端输入sudo密码&#xff0c;但是在一些无人值守的应用中显然就不太适合了。本文通过构建一个多用户的ubuntu操作环境&#xff0c;来展示脚本中需要使用sudo命令时的应用场景。 我们…

基于vue3+vite+ts,使用nexus发布组件库

1、前提条件 已部署nexus3&#xff0c;可参考&#xff1a; Ubuntu部署和体验Nexus3-腾讯云开发者社区-腾讯云 代理设置&#xff1a; 【Nexus】通过Nexus搭建Npm私库_猫巳的博客-CSDN博客 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一…

Java --- springboot3之可观测性

目录 一、可观测性 二、定制健康监控的端点 三、定制metrics 四、整合PrometheusGrafana 一、可观测性 导入pom依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></d…

如何从PCB上直接启动Power DC直流压降仿真分析工具

如何从PCB上直接启动Power DC直流压降仿真分析工具 POWER DC的启动除了可以通过POWER DC.exe直接启动外,还可以直接通过Allegro的PCB界面直接启动,二者软件是支持关联的。如何启动,具体操作如下 用166或者172版本打开PCB点击File点击Change Edi

JVM源码剖析之JVM层面调用Java方法

先看以下2个案例。 Runnable runnable () -> {System.out.println(1); }; new Thread(runnable).start(); 为什么调用Thread的start方法就能执行Runnable的代码&#xff1f; public static void main(String[] args) {System.out.println(1); } 作为Java开发者&#x…

基于差速驱动移动基座的三维变型机器人轨迹优化

在执行任务时&#xff0c;服务机器人的功能结构变化可能会限制其自主导航能力&#xff0c;从而影响其行动力。本文的研究&#xff0c;旨在解决复杂三维环境中可变形机器人的轨迹规划问题&#xff0c;特别是应用最为广泛的基于差速驱动移动基座的移动机器人的轨迹规划。 这种全…

如何下载一个网站的全部网页文件 如何极速下载网页上的文件

许多网站上都有非常多的内容&#xff0c;一个个下载比较麻烦&#xff0c;那么我们如何下载一个网站的全部网页文件&#xff1f;我们可以使用下载软件抓取整个站点上检索出所有内容&#xff0c;然后通过过滤器选择自己需要的内容。如何极速下载网页上的文件&#xff1f;我们可以…

电脑-问题

如果使用了小米路由器&#xff0c;有望 但是平凡跳转到miwifi进行检查&#xff0c;或者显示证书问题 在浏览器设置里搜索dns&#xff0c;将 确定如何通过安全连接来连接到网站后面部分改成自定义&#xff1a; https://dns.alidns.com/dns-query 主要原因是&#xff1a; edge新…

C++图形开发(4):下落的小球

文章目录 1.小球自上而下依次出现2.下落的小球低配版3.下落的小球高配版 1.小球自上而下依次出现 首先&#xff0c;我们来使小球自上而下依次出现&#xff1a; 分析&#xff1a;要使小球自上而下依次出现&#xff0c;也就是指在一个小球出现之后让程序暂停一段时间&#xff0c…

基于单片机电子密码锁射频卡识别指纹门禁密码锁系统的设计与实现

功能介绍 通过指纹进行开锁或者是按键输入当前的密码&#xff0c;修改密码&#xff0c;对IC卡可以进行注册&#xff0c;删除。当有RFID卡进入到读卡器的读卡范围内时&#xff0c;则会自动读取卡序列号&#xff0c;单片机根据卡的序列号对卡进行判断。若该卡是有效卡&#xff0c…

【 SVG 】二、SVG 容器元素

一、本文概述 本文所介绍的 svg 中元素&#xff0c;通常不会直接作为直接展示元素&#xff0c;而是配合其他基础元素&#xff0c;以实现指定功能的图层组&#xff0c;本文围绕 svg 常用容器元素&#xff0c;进行实战应用&#xff1b; 二、 SVG 容器元素&#xff08;常用&#x…

「软件测试」最全面试问题和回答,全文背熟不拿下offer算我输

一般要应聘关于测试的工作&#xff0c;面试题会不会很难?下面小编整理了软件测试面试题及答案&#xff0c;欢迎参考! 一、引言 1.1 文档目的 本次文档是为了收集在面试中遇到的一问题与常见的一些答案并不是唯一答案 二、职业规划 2.1 简单的自我介绍下 面试宫&#xff…

层层剥开Transformer;Windows Copilot初版非常简陋

&#x1f989; AI新闻 &#x1f680; 微软Win11引入Windows Copilot功能&#xff0c;但初版非常简陋 摘要&#xff1a;微软在Win11 Build 23493预览版更新中引入了Windows Copilot功能&#xff0c;该功能在任务栏上新增了一个图标按钮。点击按钮后&#xff0c;屏幕右侧会跳出…

10_Activiti7

工作流(workflow)系统 具有工作流的系统,使用的专门的建模语言(BPMN)定义 通过计算机对业务流程自动化执行管理 使用传统方式实现 ​ 代码工作量大,若流程发生改变的话,编写 的代码也会发生响应的改变 工作流引擎 按照BPMN规范进行部署,将业务和节点的流程进行分离 没有…

oracle rowscn 简单记录

可以通过ROWSCN 侦测row是否有变化&#xff0c;但需要注意&#xff1a; 默认是一个block的scn 相同可以通过create table ROWDEPENDENCIES 在每行上记录无论哪种模式&#xff0c;ROW SCN是一个大致值&#xff0c;不是准确值 NOROWDEPENDENCIES | ROWDEPENDENCIES This claus…

软件测试丨常用测试策略与测试手段

测试策略是指在特定环境约束之下&#xff0c;描述软件开发周期中关于测试原则、方法、方式的纲要&#xff0c;并阐述了它们之间如何配合&#xff0c;以高效地减少缺陷、提升质量。 测试策略中需要描述测试类型与测试目标以及测试方法&#xff0c;准入准出的条件&#xff0c;以…

初学spring5(六)静态/动态代理模式

学习回顾&#xff1a;初学spring5&#xff08;五&#xff09;使用注解开发 一、代理模式 为什么要学习代理模式&#xff0c;因为AOP的底层机制就是动态代理&#xff01; 代理模式&#xff1a; 静态代理动态代理 学习aop之前 , 我们要先了解一下代理模式&#xff01; 二、静态代…

【前端】element button鼠标点击按钮更改样式

目录 一、实现效果二、代码如下&#x1f680;写在最后 一、实现效果 二、代码如下 <span><el-button type"text"><img src"../../../../../src/assets/slice/question.png" style"font-size: 14px;margin-bottom: 0.26rem">&l…

安全响应中心 — 垃圾邮件事件报告(6.28)

2023年6月 第四周 样本概况 ✅ 类型1&#xff1a;伪造正常转发邮件&#xff08;链接&#xff09; 钓鱼邮件一直是邮件防护绕不开的话题。近日安全团队收到了一批钓鱼邮件&#xff0c;发送者将正常邮件内容和钓鱼内容拼凑在一起&#xff0c;将一封钓鱼邮件伪装成经过转发的正…